diff --git a/filetreelist/src/filetree.rs b/filetreelist/src/filetree.rs index 7ffd5c01b9..866c2f996f 100644 --- a/filetreelist/src/filetree.rs +++ b/filetreelist/src/filetree.rs @@ -17,6 +17,12 @@ pub enum MoveSelection { PageUp, } +#[derive(Clone, Copy, PartialEq)] +enum Direction { + Up, + Down, +} + #[derive(Debug, Clone, Copy)] pub struct VisualSelection { pub count: usize, @@ -116,14 +122,22 @@ impl FileTree { fn selection_page_updown( &self, - range: impl Iterator, + current_index: usize, + direction: Direction, ) -> Option { let page_size = self.window_height.get().unwrap_or(0); - range - .filter(|index| self.is_visible_index(*index)) - .take(page_size) - .last() + if direction == Direction::Up { + self.get_new_selection( + (0..=current_index).rev(), + page_size, + ) + } else { + self.get_new_selection( + current_index..(self.items.len()), + page_size, + ) + } } /// @@ -131,25 +145,23 @@ impl FileTree { self.selection.is_some_and(|selection| { let new_index = match dir { MoveSelection::Up => { - self.selection_updown(selection, true) + self.selection_updown(selection, Direction::Up) } MoveSelection::Down => { - self.selection_updown(selection, false) + self.selection_updown(selection, Direction::Down) } MoveSelection::Left => self.selection_left(selection), MoveSelection::Right => { self.selection_right(selection) } - MoveSelection::Top => { - Self::selection_start(selection) - } - MoveSelection::End => self.selection_end(selection), - MoveSelection::PageUp => { - self.selection_page_updown((0..=selection).rev()) - } + MoveSelection::Top => Some(0), + MoveSelection::End => self.selection_end(), + MoveSelection::PageUp => self + .selection_page_updown(selection, Direction::Up), MoveSelection::PageDown => self .selection_page_updown( - selection..(self.items.len()), + selection, + Direction::Down, ), }; @@ -221,98 +233,53 @@ impl FileTree { }) } - const fn selection_start(current_index: usize) -> Option { - if current_index == 0 { - None - } else { - Some(0) - } - } - - fn selection_end(&self, current_index: usize) -> Option { + fn selection_end(&self) -> Option { let items_max = self.items.len().saturating_sub(1); - let mut new_index = items_max; - - loop { - if self.is_visible_index(new_index) { - break; - } - - if new_index == 0 { - break; - } - - new_index = new_index.saturating_sub(1); - new_index = std::cmp::min(new_index, items_max); - } + self.get_new_selection((0..=items_max).rev(), 1) + } - if new_index == current_index { - None - } else { - Some(new_index) - } + fn get_new_selection( + &self, + range: impl Iterator, + take: usize, + ) -> Option { + range + .filter(|index| self.is_visible_index(*index)) + .take(take) + .last() } fn selection_updown( &self, current_index: usize, - up: bool, + direction: Direction, ) -> Option { - let mut index = current_index; - - loop { - index = { - let new_index = if up { - index.saturating_sub(1) - } else { - index.saturating_add(1) - }; - - // when reaching usize bounds - if new_index == index { - break; - } - - if new_index >= self.items.len() { - break; - } - - new_index - }; - - if self.is_visible_index(index) { - break; - } - } - - if index == current_index { - None + if direction == Direction::Up { + self.get_new_selection( + (0..=current_index.saturating_sub(1)).rev(), + 1, + ) } else { - Some(index) + self.get_new_selection( + (current_index + 1)..(self.items.len()), + 1, + ) } } fn select_parent(&self, current_index: usize) -> Option { - let indent = + let current_indent = self.items.tree_items[current_index].info().indent(); - let mut index = current_index; - - while let Some(selection) = self.selection_updown(index, true) - { - index = selection; + let range = (0..=current_index).rev(); - if self.items.tree_items[index].info().indent() < indent { - break; - } - } - - if index == current_index { - None - } else { - Some(index) - } + range.filter(|index| self.is_visible_index(*index)).find( + |index| { + self.items.tree_items[*index].info().indent() + < current_indent + }, + ) } fn selection_left( @@ -340,7 +307,10 @@ impl FileTree { self.items.expand(current_selection, false); return Some(current_selection); } - return self.selection_updown(current_selection, false); + return self.selection_updown( + current_selection, + Direction::Down, + ); } None