1+ use crate :: interactive:: state:: FilesystemScan ;
12use 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 ( ( ) )
0 commit comments