diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-03-02 17:37:02 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-03-02 17:37:02 -0500 |
commit | 094015e44075da9e56e90a5dce2be2d99e5b546d (patch) | |
tree | 1d4314f0ddac99f462aaece5ba51c5e86fd88960 | |
parent | fbf2f40d909a537b9c6e58926f03f648041d2c01 (diff) |
add support for search_next and search_prev commands
- search is now stateful and keeps track of last search pattern
- search_next will go to the next file that satisfies search pattern
- search_prev will go to the previous file that satisfies search pattern
-rw-r--r-- | src/commands/mod.rs | 4 | ||||
-rw-r--r-- | src/commands/search.rs | 127 |
2 files changed, 111 insertions, 20 deletions
diff --git a/src/commands/mod.rs b/src/commands/mod.rs index f6e0e7f..b58fd0f 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -28,7 +28,7 @@ pub use self::quit::ForceQuit; pub use self::quit::Quit; pub use self::reload_dir::ReloadDirList; pub use self::rename_file::{RenameFile, RenameFileMethod}; -pub use self::search::Search; +pub use self::search::{Search, SearchNext, SearchPrev}; pub use self::selection::SelectFiles; pub use self::set_mode::SetMode; pub use self::show_hidden::ToggleHiddenFiles; @@ -166,6 +166,8 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<Joshut Some(Box::new(self::RenameFile::new(method))) } "search" => Some(Box::new(self::Search::new())), + "search_next" => Some(Box::new(self::SearchNext::new())), + "search_prev" => Some(Box::new(self::SearchPrev::new())), "select_files" => { let mut toggle = false; let mut all = false; diff --git a/src/commands/search.rs b/src/commands/search.rs index f2d55e2..96ec94e 100644 --- a/src/commands/search.rs +++ b/src/commands/search.rs @@ -1,8 +1,16 @@ +use lazy_static::lazy_static; +use std::sync::Mutex; + use crate::commands::{CursorMove, JoshutoCommand, JoshutoRunnable}; use crate::context::JoshutoContext; use crate::textfield::JoshutoTextField; +use crate::tab::JoshutoTab; use crate::ui; +lazy_static! { + static ref search_pattern: Mutex<Option<String>> = Mutex::new(None); +} + #[derive(Clone, Debug)] pub struct Search; @@ -13,6 +21,36 @@ impl Search { pub const fn command() -> &'static str { "search" } + pub fn search(curr_tab: &JoshutoTab, pattern: &str) -> Option<i32> { + if let Some(curr_list) = curr_tab.curr_list.as_ref() { + let offset = curr_list.index as usize + 1; + let contents_len = curr_list.contents.len(); + for i in 0..contents_len { + let file_name_lower = curr_list.contents[(offset + i) % contents_len] + .file_name_as_string + .to_lowercase(); + if file_name_lower.contains(pattern) { + return Some(((offset + i) % contents_len) as i32); + } + } + } + return None; + } + pub fn search_rev(curr_tab: &JoshutoTab, pattern: &str) -> Option<i32> { + if let Some(curr_list) = curr_tab.curr_list.as_ref() { + let offset = curr_list.index as usize; + let contents_len = curr_list.contents.len(); + for i in (0..contents_len).rev() { + let file_name_lower = curr_list.contents[(offset + i) % contents_len] + .file_name_as_string + .to_lowercase(); + if file_name_lower.contains(pattern) { + return Some(((offset + i) % contents_len) as i32); + } + } + } + return None; + } } impl JoshutoCommand for Search {} @@ -40,31 +78,82 @@ impl JoshutoRunnable for Search { } ncurses::doupdate(); - let mut index: Option<i32> = None; - if let Some(user_input) = user_input { let user_input = user_input.to_lowercase(); - let curr_tab = &context.tabs[context.curr_tab_index]; - - if let Some(curr_list) = curr_tab.curr_list.as_ref() { - let offset = curr_list.index as usize; - let contents_len = curr_list.contents.len(); - for i in 0..contents_len { - let file_name_lower = curr_list.contents[(offset + i) % contents_len] - .file_name_as_string - .to_lowercase(); - if file_name_lower.contains(user_input.as_str()) { - index = Some(((offset + i) % contents_len) as i32); - break; - } - } + let index = Self::search(&context.tabs[context.curr_tab_index], &user_input); + if let Some(index) = index { + CursorMove::cursor_move(index, context); + } + let mut data = search_pattern.lock().unwrap(); + *data = Some(user_input); + ncurses::doupdate(); + } + } +} + +#[derive(Clone, Debug)] +pub struct SearchNext; + +impl SearchNext { + pub fn new() -> Self { + SearchNext + } + pub const fn command() -> &'static str { + "search_next" + } +} + +impl JoshutoCommand for SearchNext {} + +impl std::fmt::Display for SearchNext { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(Self::command()) + } +} + +impl JoshutoRunnable for SearchNext { + fn execute(&self, context: &mut JoshutoContext) { + let data = search_pattern.lock().unwrap(); + if let Some(s) = (*data).as_ref() { + let index = Search::search(&context.tabs[context.curr_tab_index], s); + if let Some(index) = index { + CursorMove::cursor_move(index, context); } + ncurses::doupdate(); } + } +} + +#[derive(Clone, Debug)] +pub struct SearchPrev; + +impl SearchPrev { + pub fn new() -> Self { + SearchPrev + } + pub const fn command() -> &'static str { + "search_prev" + } +} - if let Some(index) = index { - CursorMove::cursor_move(index, context); +impl JoshutoCommand for SearchPrev {} + +impl std::fmt::Display for SearchPrev { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(Self::command()) + } +} + +impl JoshutoRunnable for SearchPrev { + fn execute(&self, context: &mut JoshutoContext) { + let data = search_pattern.lock().unwrap(); + if let Some(s) = (*data).as_ref() { + let index = Search::search_rev(&context.tabs[context.curr_tab_index], s); + if let Some(index) = index { + CursorMove::cursor_move(index, context); + } + ncurses::doupdate(); } - ncurses::doupdate(); } } |