@@ -17,6 +17,12 @@ pub enum MoveSelection {
17
17
PageUp ,
18
18
}
19
19
20
+ #[ derive( PartialEq ) ]
21
+ enum Direction {
22
+ Up ,
23
+ Down ,
24
+ }
25
+
20
26
#[ derive( Debug , Clone , Copy ) ]
21
27
pub struct VisualSelection {
22
28
pub count : usize ,
@@ -116,40 +122,46 @@ impl FileTree {
116
122
117
123
fn selection_page_updown (
118
124
& self ,
119
- range : impl Iterator < Item = usize > ,
125
+ current_index : usize ,
126
+ direction : Direction ,
120
127
) -> Option < usize > {
121
128
let page_size = self . window_height . get ( ) . unwrap_or ( 0 ) ;
122
129
123
- range
124
- . filter ( |index| self . is_visible_index ( * index) )
125
- . take ( page_size)
126
- . last ( )
130
+ if direction == Direction :: Up {
131
+ self . get_new_selection (
132
+ ( 0 ..=current_index) . rev ( ) ,
133
+ page_size,
134
+ )
135
+ } else {
136
+ self . get_new_selection (
137
+ current_index..( self . items . len ( ) ) ,
138
+ page_size,
139
+ )
140
+ }
127
141
}
128
142
129
143
///
130
144
pub fn move_selection ( & mut self , dir : MoveSelection ) -> bool {
131
145
self . selection . is_some_and ( |selection| {
132
146
let new_index = match dir {
133
147
MoveSelection :: Up => {
134
- self . selection_updown ( selection, true )
148
+ self . selection_updown ( selection, Direction :: Up )
135
149
}
136
150
MoveSelection :: Down => {
137
- self . selection_updown ( selection, false )
151
+ self . selection_updown ( selection, Direction :: Down )
138
152
}
139
153
MoveSelection :: Left => self . selection_left ( selection) ,
140
154
MoveSelection :: Right => {
141
155
self . selection_right ( selection)
142
156
}
143
- MoveSelection :: Top => {
144
- Self :: selection_start ( selection)
145
- }
146
- MoveSelection :: End => self . selection_end ( selection) ,
147
- MoveSelection :: PageUp => {
148
- self . selection_page_updown ( ( 0 ..=selection) . rev ( ) )
149
- }
157
+ MoveSelection :: Top => Some ( 0 ) ,
158
+ MoveSelection :: End => self . selection_end ( ) ,
159
+ MoveSelection :: PageUp => self
160
+ . selection_page_updown ( selection, Direction :: Up ) ,
150
161
MoveSelection :: PageDown => self
151
162
. selection_page_updown (
152
- selection..( self . items . len ( ) ) ,
163
+ selection,
164
+ Direction :: Down ,
153
165
) ,
154
166
} ;
155
167
@@ -221,98 +233,54 @@ impl FileTree {
221
233
} )
222
234
}
223
235
224
- const fn selection_start ( current_index : usize ) -> Option < usize > {
225
- if current_index == 0 {
226
- None
227
- } else {
228
- Some ( 0 )
229
- }
230
- }
231
-
232
- fn selection_end ( & self , current_index : usize ) -> Option < usize > {
236
+ fn selection_end ( & self ) -> Option < usize > {
233
237
let items_max = self . items . len ( ) . saturating_sub ( 1 ) ;
234
238
235
- let mut new_index = items_max;
236
-
237
- loop {
238
- if self . is_visible_index ( new_index) {
239
- break ;
240
- }
241
-
242
- if new_index == 0 {
243
- break ;
244
- }
245
-
246
- new_index = new_index. saturating_sub ( 1 ) ;
247
- new_index = std:: cmp:: min ( new_index, items_max) ;
248
- }
239
+ self . get_new_selection ( ( 0 ..=items_max) . rev ( ) , 1 )
240
+ }
249
241
250
- if new_index == current_index {
251
- None
252
- } else {
253
- Some ( new_index)
254
- }
242
+ fn get_new_selection (
243
+ & self ,
244
+ range : impl Iterator < Item = usize > ,
245
+ take : usize ,
246
+ ) -> Option < usize > {
247
+ range
248
+ . filter ( |index| self . is_visible_index ( * index) )
249
+ . take ( take)
250
+ . last ( )
255
251
}
256
252
257
253
fn selection_updown (
258
254
& self ,
259
255
current_index : usize ,
260
- up : bool ,
256
+ direction : Direction ,
261
257
) -> Option < usize > {
262
- let mut index = current_index;
263
-
264
- loop {
265
- index = {
266
- let new_index = if up {
267
- index. saturating_sub ( 1 )
268
- } else {
269
- index. saturating_add ( 1 )
270
- } ;
271
-
272
- // when reaching usize bounds
273
- if new_index == index {
274
- break ;
275
- }
276
-
277
- if new_index >= self . items . len ( ) {
278
- break ;
279
- }
280
-
281
- new_index
282
- } ;
283
-
284
- if self . is_visible_index ( index) {
285
- break ;
286
- }
287
- }
288
-
289
- if index == current_index {
290
- None
258
+ if direction == Direction :: Up {
259
+ self . get_new_selection (
260
+ ( 0 ..=current_index. saturating_sub ( 1 ) ) . rev ( ) ,
261
+ 1 ,
262
+ )
291
263
} else {
292
- Some ( index)
264
+ self . get_new_selection (
265
+ ( current_index + 1 ) ..( self . items . len ( ) ) ,
266
+ 1 ,
267
+ )
293
268
}
294
269
}
295
270
296
271
fn select_parent ( & self , current_index : usize ) -> Option < usize > {
297
- let indent =
272
+ let current_indent =
298
273
self . items . tree_items [ current_index] . info ( ) . indent ( ) ;
299
274
300
- let mut index = current_index;
275
+ let range = ( 0 ..= current_index) . rev ( ) ;
301
276
302
- while let Some ( selection) = self . selection_updown ( index, true )
303
- {
304
- index = selection;
305
-
306
- if self . items . tree_items [ index] . info ( ) . indent ( ) < indent {
307
- break ;
308
- }
309
- }
310
-
311
- if index == current_index {
312
- None
313
- } else {
314
- Some ( index)
315
- }
277
+ range
278
+ . filter ( |index| self . is_visible_index ( * index) )
279
+ . skip_while ( |index| {
280
+ self . items . tree_items [ * index] . info ( ) . indent ( )
281
+ >= current_indent
282
+ } )
283
+ . next ( )
316
284
}
317
285
318
286
fn selection_left (
@@ -340,7 +308,10 @@ impl FileTree {
340
308
self . items . expand ( current_selection, false ) ;
341
309
return Some ( current_selection) ;
342
310
}
343
- return self . selection_updown ( current_selection, false ) ;
311
+ return self . selection_updown (
312
+ current_selection,
313
+ Direction :: Down ,
314
+ ) ;
344
315
}
345
316
346
317
None
0 commit comments