diff options
author | Canop <cano.petrole@gmail.com> | 2022-03-31 20:51:11 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2022-03-31 20:51:11 +0200 |
commit | 51153d26ce0c4ab80c7b0678ddbec03b3b01b34a (patch) | |
tree | f9b0468a580d0ae854101eb389953ab6eba8c7f8 /src | |
parent | 7019073b69a03aeb633ab0fabc84fecbf3482c2b (diff) |
Sort by type, with dirs either first or last
3 new internals.
With `:st` you can select to sort by type with directories first,
sort by type with directories last, or not sorting.
Fix #467
Diffstat (limited to 'src')
-rw-r--r-- | src/app/panel_state.rs | 34 | ||||
-rw-r--r-- | src/display/displayable_tree.rs | 2 | ||||
-rw-r--r-- | src/tree/sort.rs | 13 | ||||
-rw-r--r-- | src/tree/tree.rs | 32 | ||||
-rw-r--r-- | src/tree_build/builder.rs | 4 | ||||
-rw-r--r-- | src/verb/builtin.rs | 1 | ||||
-rw-r--r-- | src/verb/internal.rs | 3 |
7 files changed, 78 insertions, 11 deletions
diff --git a/src/app/panel_state.rs b/src/app/panel_state.rs index f1f2375..01b2129 100644 --- a/src/app/panel_state.rs +++ b/src/app/panel_state.rs @@ -232,6 +232,40 @@ pub trait PanelState { bang, con, ), + Internal::sort_by_type => self.with_new_options( + screen, + &|o| { + o.sort = match o.sort { + Sort::TypeDirsFirst => Sort::TypeDirsLast, + Sort::TypeDirsLast => Sort::None, + _ => Sort::TypeDirsFirst, + }; + }, + bang, + con, + ), + Internal::sort_by_type_dirs_first => self.with_new_options( + screen, + &|o| { + o.sort = match o.sort { + Sort::TypeDirsFirst => Sort::None, + _ => Sort::TypeDirsFirst, + }; + }, + bang, + con, + ), + Internal::sort_by_type_dirs_last => self.with_new_options( + screen, + &|o| { + o.sort = match o.sort { + Sort::TypeDirsLast => Sort::None, + _ => Sort::TypeDirsLast, + }; + }, + bang, + con, + ), Internal::no_sort => self.with_new_options(screen, &|o| o.sort = Sort::None, bang, con), Internal::toggle_counts => { self.with_new_options(screen, &|o| o.show_counts ^= true, bang, con) diff --git a/src/display/displayable_tree.rs b/src/display/displayable_tree.rs index be5f2db..f1a827c 100644 --- a/src/display/displayable_tree.rs +++ b/src/display/displayable_tree.rs @@ -566,7 +566,7 @@ impl<'a, 's, 't> DisplayableTree<'a, 's, 't> { } Col::Size => { - if tree.options.sort.is_some() { + if tree.options.sort.prevent_deep_display() { // as soon as there's only one level displayed we can show the size bars self.write_line_size_with_bar(cw, line, &label_style, total_size, selected)? } else { diff --git a/src/tree/sort.rs b/src/tree/sort.rs index 2f22e71..3450b0b 100644 --- a/src/tree/sort.rs +++ b/src/tree/sort.rs @@ -9,10 +9,19 @@ pub enum Sort { Count, Date, Size, + TypeDirsFirst, + TypeDirsLast, } impl Sort { - pub fn is_some(self) -> bool { - !matches!(self, Sort::None) + pub fn prevent_deep_display(self) -> bool { + match self { + Self::None => false, + Self::Count => true, + Self::Date => true, + Self::Size => true, + Self::TypeDirsFirst => false, + Self::TypeDirsLast => false, + } } } diff --git a/src/tree/tree.rs b/src/tree/tree.rs index 0ff91fe..441c197 100644 --- a/src/tree/tree.rs +++ b/src/tree/tree.rs @@ -70,6 +70,7 @@ impl Tree { /// - compute left branchs pub fn after_lines_changed(&mut self) { + // we need to order the lines to build the tree. // It's a little complicated because // - we want a case insensitive sort @@ -89,9 +90,31 @@ impl Tree { let mut bid = line.bid; loop { if let Some(l) = bid_lines.get(&bid) { + let lower_name = l.path.file_name().map_or( + "".to_string(), + |name| name.to_string_lossy().to_lowercase(), + ); + let sort_prefix = match self.options.sort { + Sort::TypeDirsFirst => { + if l.is_dir() { + " " + } else { + l.path.extension().and_then(|s| s.to_str()).unwrap_or("") + } + } + Sort::TypeDirsLast => { + if l.is_dir() { + "~~~~~~~~~~~~~~" + } else { + l.path.extension().and_then(|s| s.to_str()).unwrap_or("") + } + } + _ => { "" } + }; sort_path = format!( - "{}-{}/{}", - l.path.to_string_lossy().to_lowercase(), + "{}{}-{}/{}", + sort_prefix, + lower_name, bid.index(), // to be sure to separate paths having the same lowercase sort_path, ); @@ -462,9 +485,6 @@ impl Tree { /// /// (does nothing if it's None) fn sort_siblings(&mut self) { - if !self.options.sort.is_some() { - return; - } match self.options.sort { Sort::Count => { // we'll try to keep the same path selected @@ -494,7 +514,7 @@ impl Tree { }); self.try_select_path(&selected_path); } - Sort::None => {} + _ => {} } } diff --git a/src/tree_build/builder.rs b/src/tree_build/builder.rs index 14113d7..2465630 100644 --- a/src/tree_build/builder.rs +++ b/src/tree_build/builder.rs @@ -87,7 +87,7 @@ impl<'c> TreeBuilder<'c> { None }; let root_id = BLine::from_root(&mut blines, path, root_ignore_chain, &options)?; - let trim_root = match (options.trim_root, options.pattern.is_some(), options.sort.is_some()) { + let trim_root = match (options.trim_root, options.pattern.is_some(), options.sort.prevent_deep_display()) { // we never want to trim the root if there's a sort (_, _, true) => false, // if the user don't want root trimming, we don't trim @@ -303,7 +303,7 @@ impl<'c> TreeBuilder<'c> { } } else { // this depth is finished, we must go deeper - if self.options.sort.is_some() { + if self.options.sort.prevent_deep_display() { // in sort mode, only one level is displayed break; } diff --git a/src/verb/builtin.rs b/src/verb/builtin.rs index 8bf70d6..69fc310 100644 --- a/src/verb/builtin.rs +++ b/src/verb/builtin.rs @@ -214,6 +214,7 @@ pub fn builtin_verbs() -> Vec<Verb> { internal(sort_by_count).with_shortcut("sc"), internal(sort_by_date).with_shortcut("sd"), internal(sort_by_size).with_shortcut("ss"), + internal(sort_by_type).with_shortcut("st"), external("rm", "rm -rf {file}", StayInBroot), internal(toggle_counts).with_shortcut("counts"), internal(toggle_dates).with_shortcut("dates"), diff --git a/src/verb/internal.rs b/src/verb/internal.rs index 1bc9dd8..a43591a 100644 --- a/src/verb/internal.rs +++ b/src/verb/internal.rs @@ -116,6 +116,9 @@ Internals! { sort_by_count: "sort by count" false, sort_by_date: "sort by date" false, sort_by_size: "sort by size" false, + sort_by_type: "sort by type" false, + sort_by_type_dirs_first: "sort by type, dirs first" false, + sort_by_type_dirs_last: "sort by type, dirs last" false, clear_stage: "empty the staging area" false, stage: "add selection to staging area" true, unstage: "remove selection from staging area" true, |