summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2022-03-31 20:51:11 +0200
committerCanop <cano.petrole@gmail.com>2022-03-31 20:51:11 +0200
commit51153d26ce0c4ab80c7b0678ddbec03b3b01b34a (patch)
treef9b0468a580d0ae854101eb389953ab6eba8c7f8 /src
parent7019073b69a03aeb633ab0fabc84fecbf3482c2b (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.rs34
-rw-r--r--src/display/displayable_tree.rs2
-rw-r--r--src/tree/sort.rs13
-rw-r--r--src/tree/tree.rs32
-rw-r--r--src/tree_build/builder.rs4
-rw-r--r--src/verb/builtin.rs1
-rw-r--r--src/verb/internal.rs3
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,