mirror of https://github.com/bobwen-dev/hunter
filter by file selection
This commit is contained in:
parent
c5e0b6fa03
commit
15e2f89a64
|
@ -213,6 +213,7 @@ By default hunter uses vi-style keybindings. If you use a QWERTY-like keyboard l
|
|||
| Alt(space) | select with external program |
|
||||
| v | invert selections |
|
||||
| V | clear all selections |
|
||||
| Alt(v) | only show selected files |
|
||||
| t | toggle tag |
|
||||
| h | toggle show hidden |
|
||||
| r | reverse sort |
|
||||
|
|
27
src/files.rs
27
src/files.rs
|
@ -109,6 +109,7 @@ pub struct Files {
|
|||
pub reverse: bool,
|
||||
pub show_hidden: bool,
|
||||
pub filter: Option<String>,
|
||||
pub filter_selected: bool,
|
||||
pub dirty: DirtyBit,
|
||||
pub dirty_meta: AsyncDirtyBit,
|
||||
}
|
||||
|
@ -164,6 +165,7 @@ impl Files {
|
|||
reverse: false,
|
||||
show_hidden: true,
|
||||
filter: None,
|
||||
filter_selected: false,
|
||||
dirty: dirty,
|
||||
dirty_meta: dirty_meta,
|
||||
};
|
||||
|
@ -221,6 +223,7 @@ impl Files {
|
|||
reverse: false,
|
||||
show_hidden: true,
|
||||
filter: None,
|
||||
filter_selected: false,
|
||||
dirty: dirty,
|
||||
dirty_meta: dirty_meta,
|
||||
};
|
||||
|
@ -236,6 +239,7 @@ impl Files {
|
|||
|
||||
pub fn get_file_mut(&mut self, index: usize) -> Option<&mut File> {
|
||||
let filter = self.filter.clone();
|
||||
let filter_selected = self.filter_selected;
|
||||
let show_hidden = self.show_hidden;
|
||||
|
||||
let file = self.files
|
||||
|
@ -243,7 +247,8 @@ impl Files {
|
|||
.filter(|f|
|
||||
f.kind == Kind::Placeholder ||
|
||||
!(filter.is_some() &&
|
||||
!f.name.contains(filter.as_ref().unwrap())))
|
||||
!f.name.contains(filter.as_ref().unwrap())) &&
|
||||
(!filter_selected || f.selected))
|
||||
.filter(|f| !(!show_hidden && f.name.starts_with(".")))
|
||||
.nth(index);
|
||||
file
|
||||
|
@ -254,21 +259,25 @@ impl Files {
|
|||
.iter()
|
||||
.filter(|f|
|
||||
f.kind == Kind::Placeholder ||
|
||||
(!(self.filter.is_some() &&
|
||||
!f.name.contains(self.filter.as_ref().unwrap()))))
|
||||
!(self.filter.is_some() &&
|
||||
!f.name.contains(self.filter.as_ref().unwrap())) &&
|
||||
(!self.filter_selected || f.selected))
|
||||
.filter(|f| !(!self.show_hidden && f.name.starts_with(".")))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_files_mut(&mut self) -> Vec<&mut File> {
|
||||
let filter = self.filter.clone();
|
||||
let filter_selected = self.filter_selected;
|
||||
let show_hidden = self.show_hidden;
|
||||
|
||||
self.files
|
||||
.iter_mut()
|
||||
.filter(|f|
|
||||
f.kind == Kind::Placeholder ||
|
||||
!(filter.is_some() &&
|
||||
!f.name.contains(filter.as_ref().unwrap())))
|
||||
!f.name.contains(filter.as_ref().unwrap())) &&
|
||||
(!filter_selected || f.selected))
|
||||
.filter(|f| !(!show_hidden && f.name.starts_with(".")))
|
||||
.collect()
|
||||
}
|
||||
|
@ -529,12 +538,20 @@ impl Files {
|
|||
self.filter.clone()
|
||||
}
|
||||
|
||||
pub fn toggle_filter_selected(&mut self) {
|
||||
self.filter_selected = !self.filter_selected;
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.get_files().len()
|
||||
}
|
||||
|
||||
pub fn get_selected(&self) -> Vec<&File> {
|
||||
self.files.iter().filter(|f| f.is_selected()).collect()
|
||||
self.get_files()
|
||||
.iter()
|
||||
.filter(|f| f.is_selected())
|
||||
.map(|f| *f)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ pub struct DirSettings {
|
|||
reverse: bool,
|
||||
show_hidden: bool,
|
||||
filter: Option<String>,
|
||||
filter_selected: bool
|
||||
}
|
||||
|
||||
impl DirSettings {
|
||||
|
@ -29,7 +30,8 @@ impl DirSettings {
|
|||
dirs_first: true,
|
||||
reverse: false,
|
||||
show_hidden: true,
|
||||
filter: None
|
||||
filter: None,
|
||||
filter_selected: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +259,7 @@ impl FsCache {
|
|||
files.reverse = tab_settings.dir_settings.reverse;
|
||||
files.show_hidden = tab_settings.dir_settings.show_hidden;
|
||||
files.filter = tab_settings.dir_settings.filter.clone();
|
||||
files.filter_selected = tab_settings.dir_settings.filter_selected;
|
||||
|
||||
if tab_settings.multi_selections.len() > 0 {
|
||||
for file in &mut files.files {
|
||||
|
@ -292,6 +295,7 @@ impl FsCache {
|
|||
reverse: files.reverse,
|
||||
show_hidden: files.show_hidden,
|
||||
filter: files.filter.clone(),
|
||||
filter_selected: files.filter_selected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ impl Listable for ListView<Files> {
|
|||
Key::Char(' ') => self.multi_select_file(),
|
||||
Key::Char('v') => self.invert_selection(),
|
||||
Key::Char('V') => self.clear_selections(),
|
||||
Key::Alt('v') => self.toggle_filter_selected(),
|
||||
Key::Char('t') => self.toggle_tag()?,
|
||||
Key::Char('H') => self.toggle_hidden(),
|
||||
Key::Char('r') => self.reverse_sort(),
|
||||
|
@ -355,17 +356,33 @@ impl ListView<Files>
|
|||
fn multi_select_file(&mut self) {
|
||||
self.selected_file_mut().toggle_selection();
|
||||
|
||||
let selection = self.get_selection();
|
||||
let line = self.render_line(self.selected_file());
|
||||
self.buffer[selection] = line;
|
||||
if !self.content.filter_selected {
|
||||
let selection = self.get_selection();
|
||||
let line = self.render_line(self.selected_file());
|
||||
self.buffer[selection] = line;
|
||||
|
||||
self.move_down();
|
||||
self.move_down();
|
||||
} else {
|
||||
if self.content.filter_selected && self.content.len() == 0 {
|
||||
self.content.toggle_filter_selected();
|
||||
self.core.show_status("Disabled selection filter!").log();
|
||||
}
|
||||
|
||||
// fix cursor when last file is unselected, etc
|
||||
self.refresh().log();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invert_selection(&mut self) {
|
||||
for file in self.content.get_files_mut() {
|
||||
file.toggle_selection();
|
||||
}
|
||||
|
||||
if self.content.filter_selected && self.content.len() == 0 {
|
||||
self.content.toggle_filter_selected();
|
||||
self.core.show_status("Disabled selection filter!").log();
|
||||
}
|
||||
|
||||
self.content.set_dirty();
|
||||
self.refresh().log();
|
||||
}
|
||||
|
@ -520,6 +537,17 @@ impl ListView<Files>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn toggle_filter_selected(&mut self) {
|
||||
self.content.toggle_filter_selected();
|
||||
|
||||
if self.content.len() == 0 {
|
||||
core.show_status("No files selected").log();
|
||||
self.content.toggle_filter_selected();
|
||||
}
|
||||
|
||||
self.refresh().log();
|
||||
}
|
||||
|
||||
fn render_line(&self, file: &File) -> String {
|
||||
let icon = if self.core.config().icons {
|
||||
file.icon()
|
||||
|
@ -607,8 +635,8 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
|
|||
self.on_refresh().log();
|
||||
self.lines = self.len();
|
||||
|
||||
if self.selection >= self.lines && self.selection != 0 {
|
||||
self.selection -= 1;
|
||||
if self.selection >= self.len() && self.selection != 0 {
|
||||
self.selection = self.len() - 1;
|
||||
}
|
||||
|
||||
if self.core.is_dirty() || self.buffer.len() != self.len() {
|
||||
|
|
Loading…
Reference in New Issue