Skip to content

Commit 364f732

Browse files
authored
Merge pull request #275 from joehasson/feat/interactive-mode-sort-by-name
Feature: allow sorting by dirname / filename in interactive mode
2 parents 14a276e + 092a6c5 commit 364f732

File tree

8 files changed

+61
-10
lines changed

8 files changed

+61
-10
lines changed

src/interactive/app/common.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub enum SortMode {
1515
MTimeAscending,
1616
CountDescending,
1717
CountAscending,
18+
NameDescending,
19+
NameAscending,
1820
}
1921

2022
impl SortMode {
@@ -44,6 +46,15 @@ impl SortMode {
4446
_ => CountDescending,
4547
}
4648
}
49+
50+
pub fn toggle_name(&mut self) {
51+
use SortMode::*;
52+
*self = match self {
53+
NameAscending => NameDescending,
54+
NameDescending => NameAscending,
55+
_ => NameAscending,
56+
}
57+
}
4758
}
4859

4960
pub struct EntryDataBundle {
@@ -86,17 +97,26 @@ pub fn sorted_entries(
8697
.cmp(&r.entry_count)
8798
.then_with(|| l.name.cmp(&r.name))
8899
}
100+
fn cmp_name(l: &EntryDataBundle, r: &EntryDataBundle) -> Ordering {
101+
if l.is_dir && !r.is_dir {
102+
Ordering::Less
103+
} else if !l.is_dir && r.is_dir {
104+
Ordering::Greater
105+
} else {
106+
l.name.cmp(&r.name)
107+
}
108+
}
89109
tree.neighbors_directed(node_idx, Direction::Outgoing)
90110
.filter_map(|idx| {
91111
tree.node_weight(idx).map(|entry| {
92-
let use_glob_path = glob_root.map_or(false, |glob_root| glob_root == node_idx);
112+
let use_glob_path = glob_root.is_some_and(|glob_root| glob_root == node_idx);
93113
let (path, exists, is_dir) = {
94114
let path = path_of(tree, idx, glob_root);
95115
if matches!(check, EntryCheck::Disabled) || glob_root == Some(node_idx) {
96116
(path, true, entry.is_dir)
97117
} else {
98118
let meta = path.symlink_metadata();
99-
(path, meta.is_ok(), meta.ok().map_or(false, |m| m.is_dir()))
119+
(path, meta.is_ok(), meta.ok().is_some_and(|m| m.is_dir()))
100120
}
101121
};
102122
EntryDataBundle {
@@ -121,6 +141,8 @@ pub fn sorted_entries(
121141
MTimeDescending => r.mtime.cmp(&l.mtime),
122142
CountAscending => cmp_count(l, r),
123143
CountDescending => cmp_count(l, r).reverse(),
144+
NameAscending => cmp_name(l, r),
145+
NameDescending => cmp_name(l, r).reverse(),
124146
})
125147
.collect()
126148
}

src/interactive/app/eventloop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ impl AppState {
332332
Char('M') => self.toggle_mtime_column(),
333333
Char('c') => self.cycle_count_sorting(&tree_view),
334334
Char('C') => self.toggle_count_column(),
335+
Char('n') => self.cycle_name_sorting(&tree_view),
335336
Char('g') | Char('S') => display.byte_vis.cycle(),
336337
Char('d') => self.mark_entry(
337338
CursorMode::Advance,

src/interactive/app/handlers.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ impl AppState {
146146
);
147147
}
148148

149+
pub fn cycle_name_sorting(&mut self, tree_view: &TreeView<'_>) {
150+
self.sorting.toggle_name();
151+
self.entries = tree_view.sorted_entries(
152+
self.navigation().view_root,
153+
self.sorting,
154+
self.entry_check(),
155+
);
156+
}
157+
149158
pub fn toggle_mtime_column(&mut self) {
150159
self.toggle_column(Column::MTime);
151160
}

src/interactive/app/tests/journeys_readonly.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ fn simple_user_journey_read_only() -> Result<()> {
6868

6969
// SORTING
7070
{
71+
// when hitting the N key
72+
app.process_events(&mut terminal, into_codes("n"))?;
73+
assert_eq!(
74+
app.state.sorting,
75+
SortMode::NameAscending,
76+
"it sets the sort mode to ascending by name"
77+
);
78+
// when hitting the N key again
79+
app.process_events(&mut terminal, into_codes("n"))?;
80+
assert_eq!(
81+
app.state.sorting,
82+
SortMode::NameDescending,
83+
"it sets the sort mode to descending by name"
84+
);
7185
// when hitting the M key
7286
app.process_events(&mut terminal, into_codes("m"))?;
7387
assert_eq!(
@@ -301,9 +315,10 @@ fn simple_user_journey_read_only() -> Result<()> {
301315
"it marks only a single node",
302316
);
303317
assert!(
304-
app.window.mark_pane.as_ref().map_or(false, |p| p
305-
.marked()
306-
.contains_key(&previously_selected_index)),
318+
app.window
319+
.mark_pane
320+
.as_ref()
321+
.is_some_and(|p| p.marked().contains_key(&previously_selected_index)),
307322
"it marks the selected node"
308323
);
309324
assert_eq!(
@@ -341,9 +356,10 @@ fn simple_user_journey_read_only() -> Result<()> {
341356
);
342357

343358
assert!(
344-
app.window.mark_pane.as_ref().map_or(false, |p| p
345-
.marked()
346-
.contains_key(&previously_selected_index)),
359+
app.window
360+
.mark_pane
361+
.as_ref()
362+
.is_some_and(|p| p.marked().contains_key(&previously_selected_index)),
347363
"it leaves the first selected item marked"
348364
);
349365
}

src/interactive/widgets/footer.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ impl Footer {
4545
SortMode::MTimeDescending => "modified descending",
4646
SortMode::CountAscending => "items ascending",
4747
SortMode::CountDescending => "items descending",
48+
SortMode::NameAscending => "name ascending",
49+
SortMode::NameDescending => "name descending",
4850
},
4951
format.display(*total_bytes),
5052
entries_traversed,

src/interactive/widgets/glob.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl GlobPane {
7474
self.input
7575
.graphemes(true)
7676
.take(self.cursor_grapheme_idx)
77-
.map(|g| g.as_bytes().len())
77+
.map(|g| g.len())
7878
.sum::<usize>(),
7979
new_char,
8080
);

src/interactive/widgets/help.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ impl HelpPane {
152152
hotkey("M", "Show/hide modified time.", None);
153153
hotkey("c", "Toggle sort by entries descending/ascending.", None);
154154
hotkey("C", "Show/hide entry count.", None);
155+
hotkey("n", "Toggle sort by name ascending/descending.", None);
155156
hotkey(
156157
"g/S",
157158
"Cycle through percentage display and bar options.",

src/traverse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ impl BackgroundTraversal {
387387
}
388388
}
389389

390-
if self.throttle.as_ref().map_or(false, |t| t.can_update()) {
390+
if self.throttle.as_ref().is_some_and(|t| t.can_update()) {
391391
return Some(false);
392392
}
393393
}

0 commit comments

Comments
 (0)