summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2019-03-02 17:37:02 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2019-03-02 17:37:02 -0500
commit094015e44075da9e56e90a5dce2be2d99e5b546d (patch)
tree1d4314f0ddac99f462aaece5ba51c5e86fd88960
parentfbf2f40d909a537b9c6e58926f03f648041d2c01 (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.rs4
-rw-r--r--src/commands/search.rs127
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();
}
}