summaryrefslogtreecommitdiffstats
path: root/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/case_sensitivity.rs26
-rw-r--r--src/commands/filter.rs14
-rw-r--r--src/commands/mod.rs1
-rw-r--r--src/commands/search.rs86
-rw-r--r--src/commands/search_fzf.rs26
-rw-r--r--src/commands/search_glob.rs56
-rw-r--r--src/commands/search_string.rs70
-rw-r--r--src/commands/select.rs13
-rw-r--r--src/commands/subdir_fzf.rs22
9 files changed, 189 insertions, 125 deletions
diff --git a/src/commands/case_sensitivity.rs b/src/commands/case_sensitivity.rs
new file mode 100644
index 0000000..c604b74
--- /dev/null
+++ b/src/commands/case_sensitivity.rs
@@ -0,0 +1,26 @@
+use crate::config::option::CaseSensitivity;
+use crate::context::AppContext;
+use crate::error::JoshutoResult;
+
+#[derive(Clone, Copy, Debug)]
+pub enum SetType {
+ String,
+ Glob,
+ Fzf,
+}
+
+pub fn set_case_sensitivity(
+ context: &mut AppContext,
+ case_sensitivity: CaseSensitivity,
+ set_type: SetType,
+) -> JoshutoResult {
+ let options = context.config_mut().search_options_mut();
+
+ match set_type {
+ SetType::String => options.string_case_sensitivity = case_sensitivity,
+ SetType::Glob => options.glob_case_sensitivity = case_sensitivity,
+ SetType::Fzf => options.fzf_case_sensitivity = case_sensitivity,
+ }
+
+ Ok(())
+}
diff --git a/src/commands/filter.rs b/src/commands/filter.rs
index 2ea818d..fbf1d30 100644
--- a/src/commands/filter.rs
+++ b/src/commands/filter.rs
@@ -1,15 +1,23 @@
-use crate::context::AppContext;
+use crate::context::{AppContext, MatchContext};
use crate::error::JoshutoResult;
use super::reload;
-pub fn filter(context: &mut AppContext, arg: &str) -> JoshutoResult {
+pub fn filter(context: &mut AppContext, pattern: &str) -> JoshutoResult {
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .string_case_sensitivity;
+
+ let filter_context = MatchContext::new_string(pattern, case_sensitivity);
+
let curr_tab = context.tab_context_mut().curr_tab_mut();
let path = curr_tab.cwd().to_path_buf();
+
curr_tab
.option_mut()
.dirlist_options_mut(&path)
- .set_filter_string(arg);
+ .set_filter_context(filter_context);
if let Some(list) = curr_tab.curr_list_mut() {
list.depreciate();
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 0f821bd..4753380 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -1,5 +1,6 @@
pub mod bookmark;
pub mod bulk_rename;
+pub mod case_sensitivity;
pub mod change_directory;
pub mod command_line;
pub mod cursor_move;
diff --git a/src/commands/search.rs b/src/commands/search.rs
index 71beae1..41c2a8d 100644
--- a/src/commands/search.rs
+++ b/src/commands/search.rs
@@ -1,41 +1,87 @@
-use crate::context::AppContext;
+use crate::context::{AppContext, MatchContext};
use crate::error::JoshutoResult;
-use crate::util::search::SearchPattern;
+use crate::tab::JoshutoTab;
use super::cursor_move;
-use super::search_glob;
-use super::search_string;
pub fn search_next(context: &mut AppContext) -> JoshutoResult {
if let Some(search_context) = context.get_search_context() {
- let index = match search_context {
- 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 search_context.is_none() {
+ return Ok(());
+ }
+
+ let curr_tab = &context.tab_context_ref().curr_tab_ref();
+ let index = curr_tab.curr_list_ref().and_then(|c| c.get_index());
+
+ let offset = match index {
+ Some(index) => index + 1,
+ None => return Ok(()),
};
- if let Some(index) = index {
+
+ if let Some(index) = search_next_impl(curr_tab, search_context, offset) {
cursor_move::cursor_move(context, index);
}
}
+
Ok(())
}
+pub(super) fn search_next_impl(
+ curr_tab: &JoshutoTab,
+ match_context: &MatchContext,
+ offset: usize,
+) -> Option<usize> {
+ let curr_list = curr_tab.curr_list_ref()?;
+ let contents_len = curr_list.contents.len();
+
+ for i in 0..contents_len {
+ let file_name = curr_list.contents[(offset + i) % contents_len].file_name();
+
+ if match_context.is_match(file_name) {
+ return Some((offset + i) % contents_len);
+ }
+ }
+
+ None
+}
+
pub fn search_prev(context: &mut AppContext) -> JoshutoResult {
if let Some(search_context) = context.get_search_context() {
- let index = match search_context {
- SearchPattern::Glob(s) => {
- search_glob::search_glob_rev(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 search_context.is_none() {
+ return Ok(());
+ }
+
+ let curr_tab = &context.tab_context_ref().curr_tab_ref();
+ let index = curr_tab.curr_list_ref().and_then(|c| c.get_index());
+
+ let offset = match index {
+ Some(index) => index,
+ None => return Ok(()),
};
- if let Some(index) = index {
+
+ if let Some(index) = search_prev_impl(curr_tab, search_context, offset) {
cursor_move::cursor_move(context, index);
}
}
+
Ok(())
}
+
+fn search_prev_impl(
+ curr_tab: &JoshutoTab,
+ match_context: &MatchContext,
+ offset: usize,
+) -> Option<usize> {
+ let curr_list = curr_tab.curr_list_ref()?;
+ let contents_len = curr_list.contents.len();
+
+ for i in (0..contents_len).rev() {
+ let file_name = curr_list.contents[(offset + i) % contents_len].file_name();
+
+ if match_context.is_match(file_name) {
+ return Some((offset + i) % contents_len);
+ }
+ }
+
+ None
+}
diff --git a/src/commands/search_fzf.rs b/src/commands/search_fzf.rs
index f845c60..9d86b7b 100644
--- a/src/commands/search_fzf.rs
+++ b/src/commands/search_fzf.rs
@@ -3,6 +3,7 @@ use std::io::Write;
use std::process::{Command, Stdio};
use crate::commands::cursor_move;
+use crate::config::option::CaseSensitivity;
use crate::context::AppContext;
use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult};
use crate::ui::AppBackend;
@@ -31,11 +32,26 @@ pub fn search_fzf(context: &mut AppContext, backend: &mut AppBackend) -> Joshuto
backend.terminal_drop();
- let mut fzf = match Command::new("fzf")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .spawn()
- {
+ let mut cmd = Command::new("fzf");
+ cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
+
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .fzf_case_sensitivity;
+
+ match case_sensitivity {
+ CaseSensitivity::Insensitive => {
+ cmd.arg("-i");
+ }
+ CaseSensitivity::Sensitive => {
+ cmd.arg("+i");
+ }
+ // fzf uses smart-case match by default
+ CaseSensitivity::Smart => {}
+ }
+
+ let mut fzf = match cmd.spawn() {
Ok(child) => child,
Err(e) => {
backend.terminal_restore()?;
diff --git a/src/commands/search_glob.rs b/src/commands/search_glob.rs
index 30962c1..c833b8e 100644
--- a/src/commands/search_glob.rs
+++ b/src/commands/search_glob.rs
@@ -1,49 +1,29 @@
-use globset::{GlobBuilder, GlobMatcher};
-
-use crate::context::AppContext;
+use crate::context::{AppContext, MatchContext};
use crate::error::JoshutoResult;
-use crate::tab::JoshutoTab;
-use crate::util::search::SearchPattern;
use super::cursor_move;
+use super::search;
-pub fn search_glob_fwd(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> {
- let curr_list = curr_tab.curr_list_ref()?;
+pub fn search_glob(context: &mut AppContext, pattern: &str) -> JoshutoResult {
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .glob_case_sensitivity;
- let offset = curr_list.get_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 search_context = MatchContext::new_glob(pattern, case_sensitivity)?;
- let offset = curr_list.get_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
-}
+ let curr_tab = &context.tab_context_ref().curr_tab_ref();
+ let index = curr_tab.curr_list_ref().and_then(|c| c.get_index());
-pub fn search_glob(context: &mut AppContext, pattern: &str) -> JoshutoResult {
- let glob = GlobBuilder::new(pattern)
- .case_insensitive(true)
- .build()?
- .compile_matcher();
+ let offset = match index {
+ Some(index) => index + 1,
+ None => return Ok(()),
+ };
- let index = search_glob_fwd(context.tab_context_ref().curr_tab_ref(), &glob);
- if let Some(index) = index {
- cursor_move::cursor_move(context, index);
+ if let Some(new_index) = search::search_next_impl(curr_tab, &search_context, offset) {
+ cursor_move::cursor_move(context, new_index);
}
- context.set_search_context(SearchPattern::Glob(glob));
+
+ context.set_search_context(search_context);
Ok(())
}
diff --git a/src/commands/search_string.rs b/src/commands/search_string.rs
index 53d54ea..084fc89 100644
--- a/src/commands/search_string.rs
+++ b/src/commands/search_string.rs
@@ -1,65 +1,29 @@
-use crate::context::AppContext;
-use crate::tab::JoshutoTab;
-use crate::util::search::SearchPattern;
+use crate::context::{AppContext, MatchContext};
use super::cursor_move;
+use super::search;
-pub fn search_string_fwd(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> {
- let curr_list = curr_tab.curr_list_ref()?;
+pub fn search_string(context: &mut AppContext, pattern: &str, incremental: bool) {
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .string_case_sensitivity;
- let offset = curr_list.get_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
-}
+ let search_context = MatchContext::new_string(pattern, case_sensitivity);
-pub fn search_string_start(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> {
- let curr_list = curr_tab.curr_list_ref()?;
+ let curr_tab = context.tab_context_ref().curr_tab_ref();
- let contents_len = curr_list.contents.len();
- for i in 0..contents_len {
- let file_name_lower = curr_list.contents[i].file_name().to_lowercase();
- if file_name_lower.contains(pattern) {
- return Some(i);
+ if incremental {
+ if let Some(new_index) = search::search_next_impl(curr_tab, &search_context, 0) {
+ cursor_move::cursor_move(context, new_index);
}
- }
- None
-}
+ } else if let Some(index) = curr_tab.curr_list_ref().and_then(|c| c.get_index()) {
+ let offset = index + 1;
-pub fn search_string_rev(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> {
- let curr_list = curr_tab.curr_list_ref()?;
-
- let offset = curr_list.get_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);
+ if let Some(new_index) = search::search_next_impl(curr_tab, &search_context, offset) {
+ cursor_move::cursor_move(context, new_index);
}
}
- None
-}
-
-pub fn search_string(context: &mut AppContext, pattern: &str, incremental: bool) {
- let pattern = pattern.to_lowercase();
- let curr_tab = context.tab_context_ref().curr_tab_ref();
- let index = if incremental {
- search_string_start(curr_tab, pattern.as_str())
- } else {
- search_string_fwd(curr_tab, pattern.as_str())
- };
- if let Some(index) = index {
- cursor_move::cursor_move(context, index);
- }
- context.set_search_context(SearchPattern::String(pattern));
+ context.set_search_context(search_context);
}
diff --git a/src/commands/select.rs b/src/commands/select.rs
index 3bfa227..0ab3023 100644
--- a/src/commands/select.rs
+++ b/src/commands/select.rs
@@ -1,7 +1,5 @@
-use globset::Glob;
-
use crate::config::option::SelectOption;
-use crate::context::AppContext;
+use crate::context::{AppContext, MatchContext};
use crate::error::JoshutoResult;
use super::cursor_move;
@@ -54,13 +52,18 @@ fn select_with_pattern(
pattern: &str,
options: &SelectOption,
) -> JoshutoResult {
- let glob = Glob::new(pattern)?.compile_matcher();
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .glob_case_sensitivity;
+
+ let select_context = MatchContext::new_glob(pattern, case_sensitivity)?;
if let Some(curr_list) = context.tab_context_mut().curr_tab_mut().curr_list_mut() {
let mut found = 0;
curr_list
.iter_mut()
- .filter(|e| glob.is_match(e.file_name()))
+ .filter(|e| select_context.is_match(e.file_name()))
.for_each(|e| {
found += 1;
if options.reverse {
diff --git a/src/commands/subdir_fzf.rs b/src/commands/subdir_fzf.rs
index fee12e9..6bae11a 100644
--- a/src/commands/subdir_fzf.rs
+++ b/src/commands/subdir_fzf.rs
@@ -1,6 +1,7 @@
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
+use crate::config::option::CaseSensitivity;
use crate::context::AppContext;
use crate::error::JoshutoResult;
use crate::ui::AppBackend;
@@ -10,7 +11,26 @@ use super::change_directory::change_directory;
pub fn subdir_fzf(context: &mut AppContext, backend: &mut AppBackend) -> JoshutoResult {
backend.terminal_drop();
- let fzf = Command::new("fzf").stdout(Stdio::piped()).spawn()?;
+ let mut cmd = Command::new("fzf");
+ cmd.stdout(Stdio::piped());
+
+ let case_sensitivity = context
+ .config_ref()
+ .search_options_ref()
+ .fzf_case_sensitivity;
+
+ match case_sensitivity {
+ CaseSensitivity::Insensitive => {
+ cmd.arg("-i");
+ }
+ CaseSensitivity::Sensitive => {
+ cmd.arg("+i");
+ }
+ // fzf uses smart-case match by default
+ CaseSensitivity::Smart => {}
+ }
+
+ let fzf = cmd.spawn()?;
let fzf_output = fzf.wait_with_output();