return user to their previous position if they exit a subdir (#725)

* return user to their previous position if they enter a subdir

* fix lint

* implement changes proposed by adam

Co-authored-by: Adam Perkowski <adas1per@protonmail.com>

* add newline back

* coalesce `visit_stack` and `position_stack` (#6)

---------

Co-authored-by: nyx <nnyyxxxx@users.noreply.github.com>
Co-authored-by: Adam Perkowski <adas1per@protonmail.com>
Co-authored-by: cartercanedy <99052281+cartercanedy@users.noreply.github.com>
This commit is contained in:
nyx 2024-10-31 14:30:22 -04:00 committed by GitHub
parent 0c8977192f
commit 2d14a0a7b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -52,7 +52,7 @@ pub struct AppState {
current_tab: ListState, current_tab: ListState,
/// This stack keeps track of our "current directory". You can think of it as `pwd`. but not /// This stack keeps track of our "current directory". You can think of it as `pwd`. but not
/// just the current directory, all paths that took us here, so we can "cd .." /// just the current directory, all paths that took us here, so we can "cd .."
visit_stack: Vec<NodeId>, visit_stack: Vec<(NodeId, usize)>,
/// This is the state associated with the list widget, used to display the selection in the /// This is the state associated with the list widget, used to display the selection in the
/// widget /// widget
selection: ListState, selection: ListState,
@ -78,6 +78,13 @@ pub struct ListEntry {
pub has_children: bool, pub has_children: bool,
} }
enum SelectedItem {
UpDir,
Directory,
Command,
None,
}
impl AppState { impl AppState {
pub fn new(theme: Theme, override_validation: bool) -> Self { pub fn new(theme: Theme, override_validation: bool) -> Self {
let (temp_dir, tabs) = linutil_core::get_tabs(!override_validation); let (temp_dir, tabs) = linutil_core::get_tabs(!override_validation);
@ -89,7 +96,7 @@ impl AppState {
focus: Focus::List, focus: Focus::List,
tabs, tabs,
current_tab: ListState::default().with_selected(Some(0)), current_tab: ListState::default().with_selected(Some(0)),
visit_stack: vec![root_id], visit_stack: vec![(root_id, 0usize)],
selection: ListState::default().with_selected(Some(0)), selection: ListState::default().with_selected(Some(0)),
filter: Filter::new(), filter: Filter::new(),
multi_select: false, multi_select: false,
@ -554,7 +561,7 @@ impl AppState {
self.filter.update_items( self.filter.update_items(
&self.tabs, &self.tabs,
self.current_tab.selected().unwrap(), self.current_tab.selected().unwrap(),
*self.visit_stack.last().unwrap(), self.visit_stack.last().unwrap().0,
); );
if !self.is_current_tab_multi_selectable() { if !self.is_current_tab_multi_selectable() {
self.multi_select = false; self.multi_select = false;
@ -578,9 +585,10 @@ impl AppState {
} }
fn enter_parent_directory(&mut self) { fn enter_parent_directory(&mut self) {
self.visit_stack.pop(); if let Some((_, previous_position)) = self.visit_stack.pop() {
self.selection.select(Some(0)); self.selection.select(Some(previous_position));
self.update_items(); self.update_items();
}
} }
fn get_selected_node(&self) -> Option<Rc<ListNode>> { fn get_selected_node(&self) -> Option<Rc<ListNode>> {
@ -607,20 +615,22 @@ impl AppState {
} }
pub fn go_to_selected_dir(&mut self) { pub fn go_to_selected_dir(&mut self) {
let mut selected_index = self.selection.selected().unwrap_or(0); let selected_index = self.selection.selected().unwrap_or(0);
if !self.at_root() && selected_index == 0 { if !self.at_root() && selected_index == 0 {
self.enter_parent_directory(); self.enter_parent_directory();
return; return;
} }
if !self.at_root() { let actual_index = if self.at_root() {
selected_index = selected_index.saturating_sub(1); selected_index
} } else {
selected_index - 1
};
if let Some(item) = self.filter.item_list().get(selected_index) { if let Some(item) = self.filter.item_list().get(actual_index) {
if item.has_children { if item.has_children {
self.visit_stack.push(item.id); self.visit_stack.push((item.id, selected_index));
self.selection.select(Some(0)); self.selection.select(Some(0));
self.update_items(); self.update_items();
} }
@ -652,7 +662,6 @@ impl AppState {
pub fn selected_item_is_up_dir(&self) -> bool { pub fn selected_item_is_up_dir(&self) -> bool {
let selected_index = self.selection.selected().unwrap_or(0); let selected_index = self.selection.selected().unwrap_or(0);
!self.at_root() && selected_index == 0 !self.at_root() && selected_index == 0
} }
@ -673,24 +682,39 @@ impl AppState {
} }
} }
fn handle_enter(&mut self) { fn get_selected_item_type(&self) -> SelectedItem {
if self.selected_item_is_cmd() { if self.selected_item_is_up_dir() {
if self.selected_commands.is_empty() { SelectedItem::UpDir
if let Some(node) = self.get_selected_node() { } else if self.selected_item_is_dir() {
self.selected_commands.push(node); SelectedItem::Directory
} } else if self.selected_item_is_cmd() {
} SelectedItem::Command
let cmd_names = self
.selected_commands
.iter()
.map(|node| node.name.as_str())
.collect::<Vec<_>>();
let prompt = ConfirmPrompt::new(&cmd_names[..]);
self.focus = Focus::ConfirmationPrompt(Float::new(Box::new(prompt), 40, 40));
} else { } else {
self.go_to_selected_dir(); SelectedItem::None
}
}
fn handle_enter(&mut self) {
match self.get_selected_item_type() {
SelectedItem::UpDir => self.enter_parent_directory(),
SelectedItem::Directory => self.go_to_selected_dir(),
SelectedItem::Command => {
if self.selected_commands.is_empty() {
if let Some(node) = self.get_selected_node() {
self.selected_commands.push(node);
}
}
let cmd_names = self
.selected_commands
.iter()
.map(|node| node.name.as_str())
.collect::<Vec<_>>();
let prompt = ConfirmPrompt::new(&cmd_names[..]);
self.focus = Focus::ConfirmationPrompt(Float::new(Box::new(prompt), 40, 40));
}
SelectedItem::None => {}
} }
} }
@ -724,10 +748,13 @@ impl AppState {
} }
fn refresh_tab(&mut self) { fn refresh_tab(&mut self) {
self.visit_stack = vec![self.tabs[self.current_tab.selected().unwrap()] self.visit_stack = vec![(
.tree self.tabs[self.current_tab.selected().unwrap()]
.root() .tree
.id()]; .root()
.id(),
0usize,
)];
self.selection.select(Some(0)); self.selection.select(Some(0));
self.update_items(); self.update_items();
} }