Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18a725d

Browse files
committed
refactor
- show messages that indicate why sometimes key-presses are ignored - maintain previous selection in a clearer fashion - maintain seelction from glob-mode as well - switch title to `entry` as it's not only 'file's there, also directories. - also show how many entries there are visible
1 parent f1fc13e commit 18a725d

9 files changed

Lines changed: 104 additions & 63 deletions

File tree

src/interactive/app/eventloop.rs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::interactive::state::FilesystemScan;
12
use crate::interactive::{
23
app::navigation::Navigation,
34
state::FocussedPane,
@@ -64,15 +65,18 @@ impl AppState {
6465
}
6566

6667
pub fn traverse(&mut self, traversal: &Traversal, input: Vec<PathBuf>) -> Result<()> {
67-
let background_traversal = BackgroundTraversal::start(
68+
let traverasal = BackgroundTraversal::start(
6869
traversal.root_index,
6970
&self.walk_options,
7071
input,
7172
false,
7273
true,
7374
)?;
7475
self.navigation_mut().view_root = traversal.root_index;
75-
self.active_traversal = Some((background_traversal, None));
76+
self.scan = Some(FilesystemScan {
77+
active_traversal: traverasal,
78+
previous_selection: None,
79+
});
7680
Ok(())
7781
}
7882

@@ -130,7 +134,11 @@ impl AppState {
130134
where
131135
B: Backend,
132136
{
133-
if let Some((active_traversal, selected_name)) = &mut self.active_traversal {
137+
if let Some(FilesystemScan {
138+
active_traversal,
139+
previous_selection,
140+
}) = self.scan.as_mut()
141+
{
134142
crossbeam::select! {
135143
recv(events) -> event => {
136144
let Ok(event) = event else {
@@ -153,13 +161,13 @@ impl AppState {
153161

154162
if let Some(is_finished) = active_traversal.integrate_traversal_event(traversal, event) {
155163
self.stats = active_traversal.stats;
156-
let selected_name = selected_name.clone();
164+
let previous_selection = previous_selection.clone();
157165
if is_finished {
158166
let root_index = active_traversal.root_idx;
159167
self.recompute_sizes_recursively(traversal, root_index);
160-
self.active_traversal = None;
168+
self.scan = None;
161169
}
162-
self.update_state_during_traversal(traversal, selected_name.as_ref(), is_finished);
170+
self.update_state_during_traversal(traversal, previous_selection.as_ref(), is_finished);
163171
self.refresh_screen(window, traversal, display, terminal)?;
164172
};
165173
}
@@ -182,16 +190,21 @@ impl AppState {
182190
fn update_state_during_traversal(
183191
&mut self,
184192
traversal: &mut Traversal,
185-
selected_name: Option<&PathBuf>,
193+
previous_selection: Option<&(PathBuf, usize)>,
186194
is_finished: bool,
187195
) {
188196
let tree_view = self.tree_view(traversal);
189197
self.entries = tree_view.sorted_entries(self.navigation().view_root, self.sorting);
190198

191199
if !self.received_events {
192-
let selected_entry = selected_name
193-
.and_then(|selected_name| self.entries.iter().find(|e| e.name == *selected_name));
194-
if let Some(selected_entry) = selected_entry {
200+
let previously_selected_entry =
201+
previous_selection.and_then(|(selected_name, selected_idx)| {
202+
self.entries
203+
.iter()
204+
.find(|e| e.name == *selected_name)
205+
.or_else(|| self.entries.get(*selected_idx))
206+
});
207+
if let Some(selected_entry) = previously_selected_entry {
195208
self.navigation_mut().selected = Some(selected_entry.index);
196209
} else if is_finished {
197210
self.navigation_mut().selected = self.entries.first().map(|b| b.index);
@@ -239,8 +252,12 @@ impl AppState {
239252
Tab => {
240253
self.cycle_focus(window);
241254
}
242-
Char('/') if !glob_focussed && self.active_traversal.is_none() => {
243-
self.toggle_glob_search(window);
255+
Char('/') if !glob_focussed => {
256+
if self.scan.is_some() {
257+
self.message = Some("glob search disabled during traversal".into());
258+
} else {
259+
self.toggle_glob_search(window);
260+
}
244261
}
245262
Char('?') if !glob_focussed => self.toggle_help_pane(window),
246263
Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) && !glob_focussed => {
@@ -338,18 +355,32 @@ impl AppState {
338355
what: Refresh,
339356
) -> anyhow::Result<()> {
340357
// If another traversal is already running do not do anything.
341-
if self.active_traversal.is_some() {
358+
if self.scan.is_some() {
359+
self.message = Some("Traversal already running".into());
342360
return Ok(());
343361
}
344362

345-
// If we are displaing root of the glob search results then cancel the search.
363+
let previous_selection = self.navigation().selected.and_then(|sel_index| {
364+
tree.tree().node_weight(sel_index).map(|w| {
365+
(
366+
w.name.clone(),
367+
self.entries
368+
.iter()
369+
.enumerate()
370+
.find_map(|(idx, e)| (e.index == sel_index).then_some(idx))
371+
.expect("selected item is always in entries"),
372+
)
373+
})
374+
});
375+
376+
// If we are displaying the root of the glob search results then cancel the search.
346377
if let Some(glob_tree_root) = tree.glob_tree_root {
347378
if glob_tree_root == self.navigation().view_root {
348379
self.quit_glob_mode(tree, window)
349380
}
350381
}
351382

352-
let (remove_index, skip_root, index, parent_index) = match what {
383+
let (remove_root_node, skip_root, index, parent_index) = match what {
353384
Refresh::Selected => {
354385
let Some(selected) = self.navigation().selected else {
355386
return Ok(());
@@ -367,31 +398,26 @@ impl AppState {
367398
),
368399
};
369400

370-
let selected_name = self
371-
.navigation()
372-
.selected
373-
.and_then(|w| tree.tree().node_weight(w).map(|w| w.name.clone()));
374-
375401
let mut path = tree.path_of(index);
376402
if path.to_str() == Some("") {
377403
path = PathBuf::from(".");
378404
}
379-
tree.remove_entries(index, remove_index);
405+
tree.remove_entries(index, remove_root_node);
380406
tree.recompute_sizes_recursively(parent_index);
381407

382408
self.entries = tree.sorted_entries(self.navigation().view_root, self.sorting);
383409
self.navigation_mut().selected = self.entries.first().map(|e| e.index);
384410

385-
self.active_traversal = Some((
386-
BackgroundTraversal::start(
411+
self.scan = Some(FilesystemScan {
412+
active_traversal: BackgroundTraversal::start(
387413
parent_index,
388414
&self.walk_options,
389415
vec![path],
390416
skip_root,
391417
false,
392418
)?,
393-
selected_name,
394-
));
419+
previous_selection,
420+
});
395421

396422
self.received_events = false;
397423
Ok(())

src/interactive/app/handlers.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ impl AppState {
162162
}
163163

164164
pub fn reset_message(&mut self) {
165-
if self.active_traversal.is_some() {
165+
if self.scan.is_some() {
166166
self.message = Some("-> scanning <-".into());
167167
} else {
168168
self.message = None;
@@ -312,7 +312,8 @@ impl AppState {
312312
let parent_idx = tree_view
313313
.fs_parent_of(index)
314314
.expect("us being unable to delete the root index");
315-
let entries_deleted = tree_view.remove_entries(index, true);
315+
let entries_deleted =
316+
tree_view.remove_entries(index, true /* remove node at `index` */);
316317

317318
if !tree_view.exists(self.navigation().view_root) {
318319
self.go_to_root(tree_view);

src/interactive/app/state.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ pub struct Cursor {
2424
pub y: u16,
2525
}
2626

27+
pub(crate) struct FilesystemScan {
28+
pub active_traversal: BackgroundTraversal,
29+
/// The selected item prior to starting the traversal, if available, based on its name or index into [`AppState::entries`].
30+
pub previous_selection: Option<(PathBuf, usize)>,
31+
}
32+
2733
pub struct AppState {
2834
pub navigation: Navigation,
2935
pub glob_navigation: Option<Navigation>,
@@ -33,7 +39,7 @@ pub struct AppState {
3339
pub message: Option<String>,
3440
pub focussed: FocussedPane,
3541
pub received_events: bool,
36-
pub active_traversal: Option<(BackgroundTraversal, Option<PathBuf>)>,
42+
pub scan: Option<FilesystemScan>,
3743
pub stats: TraversalStats,
3844
pub walk_options: WalkOptions,
3945
}
@@ -49,7 +55,7 @@ impl AppState {
4955
message: None,
5056
focussed: Default::default(),
5157
received_events: false,
52-
active_traversal: None,
58+
scan: None,
5359
stats: TraversalStats::default(),
5460
walk_options,
5561
}

src/interactive/app/terminal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ mod tests {
9999
where
100100
B: Backend,
101101
{
102-
while self.state.active_traversal.is_some() {
102+
while self.state.scan.is_some() {
103103
if let Some(res) = self.state.process_event(
104104
&mut self.window,
105105
&mut self.traversal,

src/interactive/app/tests/journeys_readonly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fn simple_user_journey_read_only() -> Result<()> {
4040
);
4141

4242
assert!(
43-
app.state.active_traversal.is_none(),
43+
app.state.scan.is_none(),
4444
"it will not think it is still scanning as there is no traversal"
4545
);
4646

src/interactive/app/tree_view.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ impl TreeView<'_> {
5959
current_path(&self.traversal.tree, view_root, self.glob_tree_root)
6060
}
6161

62-
pub fn remove_entries(&mut self, index: TreeIndex, remove_index: bool) -> usize {
62+
pub fn remove_entries(&mut self, root_index: TreeIndex, remove_root_node: bool) -> usize {
6363
let mut entries_deleted = 0;
64-
let mut bfs = Bfs::new(self.tree(), index);
64+
let mut bfs = Bfs::new(self.tree(), root_index);
6565

6666
while let Some(nx) = bfs.next(&self.tree()) {
67-
if nx == index && !remove_index {
67+
if nx == root_index && !remove_root_node {
6868
continue;
6969
}
7070
self.tree_mut().remove_node(nx);

src/interactive/widgets/entries.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,18 @@ impl Entries {
6363
let list = &mut self.list;
6464

6565
let total: u128 = entries.iter().map(|b| b.size).sum();
66-
let (item_count, item_size): (u64, u128) = entries
66+
let (recursive_item_count, item_size): (u64, u128) = entries
6767
.iter()
6868
.map(|f| (f.entry_count.unwrap_or(1), f.size))
6969
.reduce(|a, b| (a.0 + b.0, a.1 + b.1))
7070
.unwrap_or_default();
71-
let title = title(current_path, item_count, *display, item_size);
71+
let title = title(
72+
current_path,
73+
entries.len(),
74+
recursive_item_count,
75+
*display,
76+
item_size,
77+
);
7278
let title_block = title_block(&title, *border_style);
7379
let inner_area = title_block.inner(area);
7480
let entry_in_view = entry_in_view(*selected, entries);
@@ -155,15 +161,17 @@ fn title_block(title: &str, border_style: Style) -> Block<'_> {
155161
.borders(Borders::ALL)
156162
}
157163

158-
fn title(current_path: &str, item_count: u64, display: DisplayOptions, size: u128) -> String {
164+
fn title(
165+
current_path: &str,
166+
item_count: usize,
167+
recursive_item_count: u64,
168+
display: DisplayOptions,
169+
size: u128,
170+
) -> String {
159171
format!(
160-
" {} ({} file{}, {}) ",
172+
" {} ({item_count} visible, {} total, {}) ",
161173
current_path,
162-
COUNT.format(item_count as f64),
163-
match item_count {
164-
1 => "",
165-
_ => "s",
166-
},
174+
COUNT.format(recursive_item_count as f64),
167175
display.byte_format.display(size)
168176
)
169177
}

src/interactive/widgets/footer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl Footer {
3737

3838
let spans = vec![
3939
Span::from(format!(
40-
"Sort mode: {} Total disk usage: {} Processed {} items {progress} ",
40+
"Sort mode: {} Total disk usage: {} Processed {} entries {progress} ",
4141
match sort_mode {
4242
SortMode::SizeAscending => "size ascending",
4343
SortMode::SizeDescending => "size descending",

0 commit comments

Comments
 (0)