From 5d68f49e59728b2c04cb6a47fc99708f406a23d1 Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Tue, 30 Jul 2024 23:20:56 +0100 Subject: [PATCH 1/6] Fix always selecting the first item to run --- src/list.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/list.rs b/src/list.rs index 753b9e02..567d2d70 100644 --- a/src/list.rs +++ b/src/list.rs @@ -414,11 +414,6 @@ impl CustomList { /// /// Returns `Some(command)` when command is selected, othervise we returns `None` fn handle_enter(&mut self) -> Option { - // Ensure an item is selected if none is selected - if self.list_state.selected().is_none() { - self.list_state.select(Some(0)); - } - // Get the selected index let selected = self.list_state.selected().unwrap(); From c2c4c8796d01c78daf2ee21a8e2a4c3bf5bcb2bc Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Wed, 31 Jul 2024 00:13:57 +0100 Subject: [PATCH 2/6] Removed try_scroll down and up, there is a builtin for that --- src/list.rs | 93 +++++++++++++++++++++-------------------------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/src/list.rs b/src/list.rs index 567d2d70..d6e9336c 100644 --- a/src/list.rs +++ b/src/list.rs @@ -50,6 +50,19 @@ impl PreviewWindowState { } } +use std::fs::OpenOptions; +use std::io::Write; + +fn log_debug_info(info: &str) { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open("debug.log") + .unwrap(); + + writeln!(file, "{}", info).unwrap(); +} + impl CustomList { pub fn new() -> Self { // When a function call ends with an exclamation mark, it means it's a macro, like in this @@ -264,7 +277,7 @@ impl CustomList { return None; } - self.try_scroll_down(); + self.list_state.select_next(); None } KeyCode::Char('k') | KeyCode::Up => { @@ -275,7 +288,7 @@ impl CustomList { return None; } - self.try_scroll_up(); + self.list_state.select_previous(); None } // The 'p' key toggles the preview on and off @@ -320,38 +333,6 @@ impl CustomList { } } - fn try_scroll_up(&mut self) { - if let Some(selected) = self.list_state.selected() { - if selected > 0 { - self.list_state.select(Some(selected.saturating_sub(1))); - } - } - } - - fn try_scroll_down(&mut self) { - let count = if self.filter_query.is_empty() { - let curr = self - .inner_tree - .get(*self.visit_stack.last().unwrap()) - .unwrap(); - curr.children().count() - } else { - self.filtered_items.len() - }; - - if let Some(curr_selection) = self.list_state.selected() { - if self.at_root() { - self.list_state - .select(Some((curr_selection + 1).min(count - 1))); - } else { - // When we are not at the root, we have to account for 1 more "virtual" node, `..`. So - // the count is 1 bigger (select is 0 based, because it's an index) - self.list_state - .select(Some((curr_selection + 1).min(count))); - } - } - } - /// Scroll the preview window down fn scroll_preview_window_down(&mut self) { if let Some(pw_state) = &mut self.preview_window_state { @@ -376,7 +357,7 @@ impl CustomList { /// This could probably be integrated into the 'handle_enter()' method to avoid code /// duplication, but I don't want to make too major changes to the codebase. fn get_selected_command(&self) -> Option { - let selected = self.list_state.selected().unwrap(); + let selected_index = self.list_state.selected().unwrap_or(0); if self.filter_query.is_empty() { // No filter query, use the regular tree navigation @@ -385,25 +366,27 @@ impl CustomList { .get(*self.visit_stack.last().unwrap()) .unwrap(); - // If we are not at the root and the first item is selected, it's the `..` item - if !self.at_root() && selected == 0 { + if !self.at_root() && selected_index == 0 { return None; } - for (mut idx, node) in curr.children().enumerate() { - if !self.at_root() { - idx += 1; - } - if idx == selected { + let mut actual_index = selected_index; + if !self.at_root() { + actual_index -= 1; // Adjust for the ".." item if not at root + } + + for (idx, node) in curr.children().enumerate() { + if idx == actual_index { return Some(node.value().command.clone()); } } } else { // Filter query is active, use the filtered items - if let Some(filtered_node) = self.filtered_items.get(selected) { + if let Some(filtered_node) = self.filtered_items.get(selected_index) { return Some(filtered_node.command.clone()); } } + None } @@ -414,8 +397,7 @@ impl CustomList { /// /// Returns `Some(command)` when command is selected, othervise we returns `None` fn handle_enter(&mut self) -> Option { - // Get the selected index - let selected = self.list_state.selected().unwrap(); + let selected_index = self.list_state.selected().unwrap_or(0); if self.filter_query.is_empty() { // No filter query, use the regular tree navigation @@ -424,21 +406,19 @@ impl CustomList { .get(*self.visit_stack.last().unwrap()) .unwrap(); - // if we are not at the root, and the first element is selected, - // we can be sure it's '..', so we go up the directory - if !self.at_root() && selected == 0 { + if !self.at_root() && selected_index == 0 { self.visit_stack.pop(); self.list_state.select(Some(0)); return None; } - for (mut idx, node) in curr.children().enumerate() { - // at this point, we know that we are not on the .. item, and our indexes of the items never had .. - // item. so to balance it out, in case the selection index contains .., se add 1 to our node index - if !self.at_root() { - idx += 1; - } - if idx == selected { + let mut actual_index = selected_index; + if !self.at_root() { + actual_index -= 1; // Adjust for the ".." item if not at root + } + + for (idx, node) in curr.children().enumerate() { + if idx == actual_index { if node.has_children() { self.visit_stack.push(node.id()); self.list_state.select(Some(0)); @@ -450,10 +430,11 @@ impl CustomList { } } else { // Filter query is active, use the filtered items - if let Some(filtered_node) = self.filtered_items.get(selected) { + if let Some(filtered_node) = self.filtered_items.get(selected_index) { return Some(filtered_node.command.clone()); } } + None } From 28915896520639787ad6e768c29c21342b5b2375 Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Wed, 31 Jul 2024 00:14:50 +0100 Subject: [PATCH 3/6] Remove debug crate I used to fix this problem --- src/list.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/list.rs b/src/list.rs index d6e9336c..c794aafa 100644 --- a/src/list.rs +++ b/src/list.rs @@ -50,19 +50,6 @@ impl PreviewWindowState { } } -use std::fs::OpenOptions; -use std::io::Write; - -fn log_debug_info(info: &str) { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open("debug.log") - .unwrap(); - - writeln!(file, "{}", info).unwrap(); -} - impl CustomList { pub fn new() -> Self { // When a function call ends with an exclamation mark, it means it's a macro, like in this From bddc943258df6b5e3ce349e58090bcde62b5857f Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Wed, 31 Jul 2024 01:14:33 +0100 Subject: [PATCH 4/6] Change filter logic and fix wrong command on select bug --- src/list.rs | 11 ++++++----- src/main.rs | 9 +++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/list.rs b/src/list.rs index c794aafa..193092a5 100644 --- a/src/list.rs +++ b/src/list.rs @@ -129,8 +129,7 @@ impl CustomList { } /// Draw our custom widget to the frame - pub fn draw(&mut self, frame: &mut Frame, area: Rect, filter: String, state: &AppState) { - self.filter(filter); + pub fn draw(&mut self, frame: &mut Frame, area: Rect, state: &AppState) { let item_list: Vec = if self.filter_query.is_empty() { let mut items: Vec = vec![]; @@ -168,9 +167,7 @@ impl CustomList { } items } else { - let mut sorted_items = self.filtered_items.clone(); - sorted_items.sort_by(|a, b| a.name.cmp(b.name)); - sorted_items + self.filtered_items .iter() .map(|node| { Line::from(format!("{} {}", state.theme.cmd_icon, node.name)) @@ -225,6 +222,7 @@ impl CustomList { self.filtered_items.clear(); let query_lower = query.to_lowercase(); + let mut stack = vec![self.inner_tree.root().id()]; while let Some(node_id) = stack.pop() { @@ -238,6 +236,7 @@ impl CustomList { stack.push(child.id()); } } + self.filtered_items.sort_by(|a, b| a.name.cmp(b.name)); } /// Resets the selection to the first item @@ -345,6 +344,7 @@ impl CustomList { /// duplication, but I don't want to make too major changes to the codebase. fn get_selected_command(&self) -> Option { let selected_index = self.list_state.selected().unwrap_or(0); + println!("Selected Index: {}", selected_index); if self.filter_query.is_empty() { // No filter query, use the regular tree navigation @@ -370,6 +370,7 @@ impl CustomList { } else { // Filter query is active, use the filtered items if let Some(filtered_node) = self.filtered_items.get(selected_index) { + println!("Filtered Node Name: {}", filtered_node.name); return Some(filtered_node.command.clone()); } } diff --git a/src/main.rs b/src/main.rs index b6a175b7..e222c3ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -117,7 +117,7 @@ fn run(terminal: &mut Terminal, state: &AppState) -> io::Result<( //Render the search bar (First chunk of the screen) frame.render_widget(search_bar, chunks[0]); //Render the command list (Second chunk of the screen) - custom_list.draw(frame, chunks[1], search_input.clone(), state); + custom_list.draw(frame, chunks[1], state); if let Some(ref mut command) = &mut command_opt { command.draw(frame, state); @@ -154,12 +154,17 @@ fn run(terminal: &mut Terminal, state: &AppState) -> io::Result<( //Insert user input into the search bar if in_search_mode { match key.code { - KeyCode::Char(c) => search_input.push(c), + KeyCode::Char(c) => { + search_input.push(c); + custom_list.filter(search_input.clone()); + }, KeyCode::Backspace => { search_input.pop(); + custom_list.filter(search_input.clone()); } KeyCode::Esc => { search_input = String::new(); + custom_list.filter(search_input.clone()); in_search_mode = false } KeyCode::Enter => { From bc604780abc08b8b55922d7a4db13fe1ef82fe18 Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Wed, 31 Jul 2024 01:19:07 +0100 Subject: [PATCH 5/6] Fix bad comma --- src/list.rs | 1 - src/main.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/list.rs b/src/list.rs index 193092a5..92a81a8e 100644 --- a/src/list.rs +++ b/src/list.rs @@ -130,7 +130,6 @@ impl CustomList { /// Draw our custom widget to the frame pub fn draw(&mut self, frame: &mut Frame, area: Rect, state: &AppState) { - let item_list: Vec = if self.filter_query.is_empty() { let mut items: Vec = vec![]; // If we are not at the root of our filesystem tree, we need to add `..` path, to be able diff --git a/src/main.rs b/src/main.rs index e222c3ca..3d82461c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -157,7 +157,7 @@ fn run(terminal: &mut Terminal, state: &AppState) -> io::Result<( KeyCode::Char(c) => { search_input.push(c); custom_list.filter(search_input.clone()); - }, + } KeyCode::Backspace => { search_input.pop(); custom_list.filter(search_input.clone()); From 7dda423ed55404fd0b081caea11ecc2262fb6691 Mon Sep 17 00:00:00 2001 From: afonsofrancof Date: Wed, 31 Jul 2024 01:25:43 +0100 Subject: [PATCH 6/6] I will slap the linter in the face --- src/list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/list.rs b/src/list.rs index 87594afb..4bf11d55 100644 --- a/src/list.rs +++ b/src/list.rs @@ -282,7 +282,7 @@ impl CustomList { None } - KeyCode::Enter => { + KeyCode::Enter => { if self.preview_window_state.is_none() { self.handle_enter() } else {