diff options
author | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-04-25 14:20:01 -0400 |
---|---|---|
committer | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-04-25 14:20:01 -0400 |
commit | 98e7abe8b451448305a4753dcad1bc56b2892a1b (patch) | |
tree | 2480fd7123574b92d08c5e46ebf78f17492d0e69 /src | |
parent | a0fd0d5ec9cc023674099be44a2feea08879b0e9 (diff) |
add back option to string search instead of always glob search
- search will be used for string search
- search_glob will be used for glob search
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/commands.rs | 21 | ||||
-rw-r--r-- | src/commands/mod.rs | 3 | ||||
-rw-r--r-- | src/commands/search.rs | 85 | ||||
-rw-r--r-- | src/commands/search_glob.rs | 54 | ||||
-rw-r--r-- | src/commands/search_string.rs | 47 | ||||
-rw-r--r-- | src/context/context.rs | 7 |
6 files changed, 151 insertions, 66 deletions
diff --git a/src/commands/commands.rs b/src/commands/commands.rs index 096dba1..03036af 100644 --- a/src/commands/commands.rs +++ b/src/commands/commands.rs @@ -50,7 +50,8 @@ pub enum KeyCommand { RenameFileAppend, RenameFilePrepend, - Search(String), + SearchGlob(String), + SearchString(String), SearchNext, SearchPrev, @@ -106,7 +107,8 @@ impl KeyCommand { Self::RenameFileAppend => "rename_append", Self::RenameFilePrepend => "rename_prepend", - Self::Search(_) => "search", + Self::SearchString(_) => "search", + Self::SearchGlob(_) => "search_glob", Self::SearchNext => "search_next", Self::SearchPrev => "search_prev", @@ -251,7 +253,14 @@ impl KeyCommand { JoshutoErrorKind::IoInvalidData, format!("{}: Expected 1, got 0", command), )), - arg => Ok(Self::Search(arg.to_string())), + arg => Ok(Self::SearchString(arg.to_string())), + }, + "search_glob" => match arg { + "" => Err(JoshutoError::new( + JoshutoErrorKind::IoInvalidData, + format!("{}: Expected 1, got 0", command), + )), + arg => Ok(Self::SearchGlob(arg.to_string())), }, "search_next" => Ok(Self::SearchNext), "search_prev" => Ok(Self::SearchPrev), @@ -362,7 +371,8 @@ impl JoshutoRunnable for KeyCommand { Self::RenameFile(p) => rename_file::rename_file(context, p.as_path()), Self::RenameFileAppend => rename_file::rename_file_append(context, backend), Self::RenameFilePrepend => rename_file::rename_file_prepend(context, backend), - Self::Search(pattern) => search::search(context, pattern.as_str()), + Self::SearchGlob(pattern) => search_glob::search_glob(context, pattern.as_str()), + Self::SearchString(pattern) => search_string::search_string(context, pattern.as_str()), Self::SearchNext => search::search_next(context), Self::SearchPrev => search::search_prev(context), @@ -397,7 +407,8 @@ impl std::fmt::Display for KeyCommand { Self::NewDirectory(d) => write!(f, "{} {:?}", self.command(), d), Self::RenameFile(name) => write!(f, "{} {:?}", self.command(), name), - Self::Search(s) => write!(f, "{} {}", self.command(), s), + Self::SearchGlob(s) => write!(f, "{} {}", self.command(), s), + Self::SearchString(s) => write!(f, "{} {}", self.command(), s), Self::SelectFiles(pattern, options) => { write!(f, "{} {} {}", self.command(), pattern, options) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 20289f3..a03e9c5 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -12,6 +12,8 @@ pub mod quit; pub mod reload; pub mod rename_file; pub mod search; +pub mod search_glob; +pub mod search_string; pub mod selection; pub mod set_mode; pub mod shell; @@ -25,3 +27,4 @@ pub mod commands; pub use self::command_keybind::{CommandKeybind, JoshutoCommand, JoshutoRunnable}; pub use self::commands::KeyCommand; +pub use self::search::SearchPattern; diff --git a/src/commands/search.rs b/src/commands/search.rs index 8ff33ca..8bade96 100644 --- a/src/commands/search.rs +++ b/src/commands/search.rs @@ -5,76 +5,45 @@ use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; use crate::tab::JoshutoTab; use super::cursor_move; +use super::search_glob; +use super::search_string; -pub fn _search(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { - let curr_list = curr_tab.curr_list_ref()?; - - let offset = curr_list.index? + 1; - let contents_len = curr_list.len(); - for i in 0..contents_len { - let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); - if glob.is_match(file_name) { - return Some((offset + i) % contents_len); - } - } - None +#[derive(Clone, Debug)] +pub enum SearchPattern { + Glob(GlobMatcher), + String(String), } -pub fn _search_rev(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { - let curr_list = curr_tab.curr_list_ref()?; - let offset = curr_list.index?; - let contents_len = curr_list.len(); - for i in (0..contents_len).rev() { - let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); - if glob.is_match(file_name) { - return Some((offset + i) % contents_len); - } - } - None -} - -pub fn search(context: &mut JoshutoContext, pattern: &str) -> JoshutoResult<()> { - let pattern = pattern.to_lowercase(); - - let glob = match GlobBuilder::new(pattern.as_str()) - .case_insensitive(true) - .build() - { - Ok(s) => s.compile_matcher(), - Err(e) => { - return Err(JoshutoError::new( - JoshutoErrorKind::IoInvalidData, - "Invalid glob input".to_string(), - )); +pub fn search_next(context: &mut JoshutoContext) -> JoshutoResult<()> { + if let Some(s) = context.get_search_state() { + let index = match s { + SearchPattern::Glob(s) => { + search_glob::search_glob_fwd(context.tab_context_ref().curr_tab_ref(), s) + } + SearchPattern::String(s) => { + search_string::search_string_fwd(context.tab_context_ref().curr_tab_ref(), s) + } + }; + if let Some(index) = index { + let _ = cursor_move::cursor_move(index, context); } - }; - - let index = _search(context.tab_context_ref().curr_tab_ref(), &glob); - if let Some(index) = index { - let _ = cursor_move::cursor_move(index, context); } - context.set_search_state(glob); Ok(()) } -fn search_with_func( - context: &mut JoshutoContext, - search_func: fn(&JoshutoTab, &GlobMatcher) -> Option<usize>, -) { +pub fn search_prev(context: &mut JoshutoContext) -> JoshutoResult<()> { if let Some(s) = context.get_search_state() { - let index = search_func(context.tab_context_ref().curr_tab_ref(), s); + let index = match s { + SearchPattern::Glob(s) => { + search_glob::search_glob_fwd(context.tab_context_ref().curr_tab_ref(), s) + } + SearchPattern::String(s) => { + search_string::search_string_rev(context.tab_context_ref().curr_tab_ref(), s) + } + }; if let Some(index) = index { let _ = cursor_move::cursor_move(index, context); } } -} - -pub fn search_next(context: &mut JoshutoContext) -> JoshutoResult<()> { - search_with_func(context, _search); - Ok(()) -} - -pub fn search_prev(context: &mut JoshutoContext) -> JoshutoResult<()> { - search_with_func(context, _search_rev); Ok(()) } diff --git a/src/commands/search_glob.rs b/src/commands/search_glob.rs new file mode 100644 index 0000000..bb87cf8 --- /dev/null +++ b/src/commands/search_glob.rs @@ -0,0 +1,54 @@ +use globset::{GlobBuilder, GlobMatcher}; + +use crate::commands::SearchPattern; +use crate::context::JoshutoContext; +use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; +use crate::tab::JoshutoTab; + +use super::cursor_move; + +pub fn search_glob_fwd(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { + let curr_list = curr_tab.curr_list_ref()?; + + let offset = curr_list.index? + 1; + let contents_len = curr_list.len(); + for i in 0..contents_len { + let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); + if glob.is_match(file_name) { + return Some((offset + i) % contents_len); + } + } + None +} +pub fn search_glob_rev(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { + let curr_list = curr_tab.curr_list_ref()?; + + let offset = curr_list.index?; + let contents_len = curr_list.len(); + for i in (0..contents_len).rev() { + let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); + if glob.is_match(file_name) { + return Some((offset + i) % contents_len); + } + } + None +} + +pub fn search_glob(context: &mut JoshutoContext, pattern: &str) -> JoshutoResult<()> { + let glob = match GlobBuilder::new(pattern).case_insensitive(true).build() { + Ok(s) => s.compile_matcher(), + Err(e) => { + return Err(JoshutoError::new( + JoshutoErrorKind::IoInvalidData, + "Invalid glob input".to_string(), + )); + } + }; + + let index = search_glob_fwd(context.tab_context_ref().curr_tab_ref(), &glob); + if let Some(index) = index { + let _ = cursor_move::cursor_move(index, context); + } + context.set_search_state(SearchPattern::Glob(glob)); + Ok(()) +} diff --git a/src/commands/search_string.rs b/src/commands/search_string.rs new file mode 100644 index 0000000..6cf5fa6 --- /dev/null +++ b/src/commands/search_string.rs @@ -0,0 +1,47 @@ +use crate::commands::SearchPattern; +use crate::context::JoshutoContext; +use crate::error::JoshutoResult; +use crate::tab::JoshutoTab; + +use super::cursor_move; + +pub fn search_string_fwd(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> { + let curr_list = curr_tab.curr_list_ref()?; + + let offset = curr_list.index? + 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() + .to_lowercase(); + if file_name_lower.contains(pattern) { + return Some((offset + i) % contents_len); + } + } + None +} +pub fn search_string_rev(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> { + let curr_list = curr_tab.curr_list_ref()?; + + let offset = curr_list.index?; + 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() + .to_lowercase(); + if file_name_lower.contains(pattern) { + return Some((offset + i) % contents_len); + } + } + None +} + +pub fn search_string(context: &mut JoshutoContext, pattern: &str) -> JoshutoResult<()> { + let pattern = pattern.to_lowercase(); + let index = search_string_fwd(context.tab_context_ref().curr_tab_ref(), pattern.as_str()); + if let Some(index) = index { + let _ = cursor_move::cursor_move(index, context); + } + context.set_search_state(SearchPattern::String(pattern)); + Ok(()) +} diff --git a/src/context/context.rs b/src/context/context.rs index 14e262f..09e9c56 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -5,6 +5,7 @@ use std::thread; use globset::GlobMatcher; +use crate::commands::SearchPattern; use crate::config; use crate::context::{LocalStateContext, TabContext}; use crate::io::{IoWorkerObserver, IoWorkerProgress, IoWorkerThread}; @@ -16,7 +17,7 @@ pub struct JoshutoContext { events: Events, tab_context: TabContext, local_state: Option<LocalStateContext>, - search_state: Option<GlobMatcher>, + search_state: Option<SearchPattern>, message_queue: VecDeque<String>, worker_queue: VecDeque<IoWorkerThread>, worker: Option<IoWorkerObserver>, @@ -81,11 +82,11 @@ impl JoshutoContext { self.local_state.take() } - pub fn set_search_state(&mut self, pattern: GlobMatcher) { + pub fn set_search_state(&mut self, pattern: SearchPattern) { self.search_state = Some(pattern); } - pub fn get_search_state(&self) -> Option<&GlobMatcher> { + pub fn get_search_state(&self) -> Option<&SearchPattern> { self.search_state.as_ref() } |