summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Chen <ctj12461@163.com>2023-08-13 23:12:59 +0800
committerGitHub <noreply@github.com>2023-08-13 11:12:59 -0400
commit7ab12658f911bebfa12f836b2a6449e08611e437 (patch)
treec5b00ec5342ff424b05d0f3c1dd283115c73bceb
parent82e231ac004e1f25f0a447bc601e5e3a10dca4d2 (diff)
feat: Add case sensitivity support for searching, selecting and filtering files (#393)
* feat: Add struct and enum definitons for choosing case sensitivity of search * feat: Implement `FromStr` for CaseSensitivity * feat: Add a command to change the configuration of case sensitivity * feat: Add case sensitivity support for search operations * feat: Add case sensitivity support for selection operations * docs: Add explanations for the new feature * feat: Add case sensitivity support for searching with fzf * docs: Add explanations for the new feature * docs: Update documents * feat: Refactor and add case sensitivity support for the filter operation * refactor: Extract codes related to constructing the context for searching * refactor: Extract the common component of searching, selecting and filtering files * refactor: Change the module path and name * feat: Use separate options for case sensitivity configurations * feat: Add support for changing case sensitivity configurations at runtime * docs: Add explanations for the new command
-rw-r--r--config/joshuto.toml8
-rw-r--r--docs/configuration/joshuto.toml.md17
-rw-r--r--docs/configuration/keymap.toml.md28
-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
-rw-r--r--src/config/general/app.rs11
-rw-r--r--src/config/general/app_raw.rs6
-rw-r--r--src/config/general/mod.rs1
-rw-r--r--src/config/general/search_raw.rs60
-rw-r--r--src/config/option/display_option.rs44
-rw-r--r--src/config/option/mod.rs2
-rw-r--r--src/config/option/search_option.rs44
-rw-r--r--src/context/app_context.rs13
-rw-r--r--src/context/matcher.rs108
-rw-r--r--src/context/mod.rs2
-rw-r--r--src/key_command/command.rs8
-rw-r--r--src/key_command/constants.rs1
-rw-r--r--src/key_command/impl_appcommand.rs1
-rw-r--r--src/key_command/impl_appexecute.rs4
-rw-r--r--src/key_command/impl_comment.rs1
-rw-r--r--src/key_command/impl_from_str.rs35
-rw-r--r--src/ui/widgets/tui_footer.rs4
-rw-r--r--src/util/mod.rs1
-rw-r--r--src/util/search.rs7
31 files changed, 543 insertions, 177 deletions
diff --git a/config/joshuto.toml b/config/joshuto.toml
index 3986e35..9c875d4 100644
--- a/config/joshuto.toml
+++ b/config/joshuto.toml
@@ -38,6 +38,14 @@ reverse = false
max_preview_size = 2097152 # 2MB
preview_script = "~/.config/joshuto/preview_file.sh" # make sure it's marked as executable
+[search]
+# insensitive, sensitive, smart
+string_case_sensitivity = "insensitive"
+# see above
+glob_case_sensitivity = "sensitive"
+# see above
+fzf_case_sensitivity = "insensitive"
+
[tab]
# inherit, home, root
home_page = "home"
diff --git a/docs/configuration/joshuto.toml.md b/docs/configuration/joshuto.toml.md
index 1e0ed5c..e9bf8f2 100644
--- a/docs/configuration/joshuto.toml.md
+++ b/docs/configuration/joshuto.toml.md
@@ -85,6 +85,23 @@ directories_first = true
# sort in reverse
reverse = false
+# Configurations related to searching and selecting files
+[search]
+# Different case sensitivities for operations using substring matching
+# - insensitive
+# - sensitive
+# - smart: when the pattern contains at least one uppercase letter, joshuto can search
+# files case-sensitively, otherwise it will ignore the difference between lowercase
+# and uppercase
+# Note that to apply changes after changing configurations at runtime, re-executing
+# the search command is required.
+# For substring matching
+string_case_sensitivity = "insensitive"
+# For glob matching
+glob_case_sensitivity = "sensitive"
+# For matching with fzf
+fzf_case_sensitivity = "insensitive"
+
# Optional list of command aliases (empty by default)
[cmd_aliases]
# q = "quit"
diff --git a/docs/configuration/keymap.toml.md b/docs/configuration/keymap.toml.md
index bc50909..75929f3 100644
--- a/docs/configuration/keymap.toml.md
+++ b/docs/configuration/keymap.toml.md
@@ -313,9 +313,7 @@ function joshuto() {
### `search`: search the current directory via a string
-- case insensitive
-
-### `search_glob`: search the current directory via shell globbing
+### `search_glob`: search the current directory via shell globbing (exact match)
- `:search_glob *.png`
@@ -341,19 +339,37 @@ keymap = [ //..
]
```
-### `filter`:Case insensitively filter the current directory list.
+### `filter`: filter the current directory list.
- `:filter ca`: filter the current directory and show only items with `ca` in the name
-### `toggle_visual`: Enables or disables “visual mode”.
+### `toggle_visual`: enables or disables “visual mode”.
When disabling, the current “visual mode selection” is turned into normal selection.
(See also [Visual Mode](../misc.md#visual-mode).)
-### `escape`: Leave visual mode and withdraw the visual-mode-selection.
+### `escape`: leave visual mode and withdraw the visual-mode-selection.
(See also [Visual Mode](../misc.md#visual-mode).)
+### `set_case_sensitivity`: set case sensitivity for different search operations.
+
+- Options
+ - `--type=string`: change configurations of operations using substring matching
+ - `--type=glob`: change configurations of operations using glob matching
+ - `--type=fzf`: change configurations of operations using fzf
+ - when no option is added, type is set to `string` by default
+- Value
+ - `insensitive`
+ - `sensitive`
+ - `smart`
+
+An example:
+
+```
+:set_case_sensitivity --type=fzf sensitive
+```
+
## Bookmarks
### `add_bookmark`: adds a bookmark to the `bookmarks.toml` file
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();
diff --git a/src/config/general/app.rs b/src/config/general/app.rs
index 9ee900e..65306b7 100644
--- a/src/config/general/app.rs
+++ b/src/config/general/app.rs
@@ -3,7 +3,7 @@ use std::collections::HashMap;
use super::app_raw::AppConfigRaw;
use super::DEFAULT_CONFIG_FILE_PATH;
-use crate::config::option::{DisplayOption, PreviewOption, TabOption};
+use crate::config::option::{DisplayOption, PreviewOption, SearchOption, TabOption};
use crate::error::JoshutoResult;
#[derive(Debug, Clone)]
@@ -15,6 +15,7 @@ pub struct AppConfig {
pub cmd_aliases: HashMap<String, String>,
pub _display_options: DisplayOption,
pub _preview_options: PreviewOption,
+ pub _search_options: SearchOption,
pub _tab_options: TabOption,
}
@@ -38,6 +39,14 @@ impl AppConfig {
&mut self._preview_options
}
+ pub fn search_options_ref(&self) -> &SearchOption {
+ &self._search_options
+ }
+
+ pub fn search_options_mut(&mut self) -> &mut SearchOption {
+ &mut self._search_options
+ }
+
pub fn tab_options_ref(&self) -> &TabOption {
&self._tab_options
}
diff --git a/src/config/general/app_raw.rs b/src/config/general/app_raw.rs
index bebcb9c..58ab74a 100644
--- a/src/config/general/app_raw.rs
+++ b/src/config/general/app_raw.rs
@@ -3,11 +3,12 @@ use std::convert::From;
use serde_derive::Deserialize;
-use crate::config::option::{DisplayOption, PreviewOption, TabOption};
+use crate::config::option::{DisplayOption, PreviewOption, SearchOption, TabOption};
use crate::config::{parse_config_or_default, AppConfig, TomlConfigFile};
use super::display_raw::DisplayOptionRaw;
use super::preview_raw::PreviewOptionRaw;
+use super::search_raw::SearchOptionRaw;
use super::tab_raw::TabOptionRaw;
const fn default_true() -> bool {
@@ -35,6 +36,8 @@ pub struct AppConfigRaw {
pub display_options: DisplayOptionRaw,
#[serde(default, rename = "preview")]
pub preview_options: PreviewOptionRaw,
+ #[serde(default, rename = "search")]
+ pub search_options: SearchOptionRaw,
#[serde(default, rename = "tab")]
pub tab_options: TabOptionRaw,
}
@@ -49,6 +52,7 @@ impl From<AppConfigRaw> for AppConfig {
cmd_aliases: raw.cmd_aliases,
_display_options: DisplayOption::from(raw.display_options),
_preview_options: PreviewOption::from(raw.preview_options),
+ _search_options: SearchOption::from(raw.search_options),
_tab_options: TabOption::from(raw.tab_options),
}
}
diff --git a/src/config/general/mod.rs b/src/config/general/mod.rs
index 7b85b7f..e5b2538 100644
--- a/src/config/general/mod.rs
+++ b/src/config/general/mod.rs
@@ -3,6 +3,7 @@ pub mod app;
mod app_raw;
mod display_raw;
mod preview_raw;
+mod search_raw;
mod sort_raw;
mod tab_raw;
diff --git a/src/config/general/search_raw.rs b/src/config/general/search_raw.rs
new file mode 100644
index 0000000..cd9d397
--- /dev/null
+++ b/src/config/general/search_raw.rs
@@ -0,0 +1,60 @@
+use std::convert::From;
+use std::str::FromStr;
+
+use serde_derive::Deserialize;
+
+use crate::config::option::{CaseSensitivity, SearchOption};
+
+fn default_string_case_sensitivity() -> String {
+ "insensitive".to_string()
+}
+
+fn default_glob_case_sensitivity() -> String {
+ "sensitive".to_string()
+}
+
+fn default_fzf_case_sensitivity() -> String {
+ "insensitive".to_string()
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct SearchOptionRaw {
+ #[serde(default = "default_string_case_sensitivity")]
+ pub string_case_sensitivity: String,
+
+ #[serde(default = "default_glob_case_sensitivity")]
+ pub glob_case_sensitivity: String,
+
+ #[serde(default = "default_fzf_case_sensitivity")]
+ pub fzf_case_sensitivity: String,
+}
+
+impl std::default::Default for SearchOptionRaw {
+ fn default() -> Self {
+ SearchOptionRaw {
+ string_case_sensitivity: default_string_case_sensitivity(),
+ glob_case_sensitivity: default_glob_case_sensitivity(),
+ fzf_case_sensitivity: default_fzf_case_sensitivity(),
+ }
+ }
+}
+
+impl From<SearchOptionRaw> for SearchOption {
+ fn from(raw: SearchOptionRaw) -> Self {
+ let string_case_sensitivity =
+ CaseSensitivity::from_str(raw.string_case_sensitivity.as_str())
+ .unwrap_or(CaseSensitivity::Insensitive);
+
+ let glob_case_sensitivity = CaseSensitivity::from_str(raw.glob_case_sensitivity.as_str())
+ .unwrap_or(CaseSensitivity::Sensitive);
+
+ let fzf_case_sensitivity = CaseSensitivity::from_str(raw.fzf_case_sensitivity.as_str())
+ .unwrap_or(CaseSensitivity::Insensitive);
+
+ Self {
+ string_case_sensitivity,
+ glob_case_sensitivity,
+ fzf_case_sensitivity,
+ }
+ }
+}
diff --git a/src/config/option/display_option.rs b/src/config/option/display_option.rs
index 24fa89c..393c5f0 100644
--- a/src/config/option/display_option.rs
+++ b/src/config/option/display_option.rs
@@ -4,6 +4,7 @@ use ratatui::layout::Constraint;
use crate::config::option::LineMode;
use crate::config::option::SortOption;
+use crate::context::MatchContext;
#[derive(Clone, Copy, Debug)]
pub enum DisplayMode {
@@ -36,7 +37,7 @@ pub struct DisplayOption {
/// Display options valid pre JoshutoDirList in a JoshutoTab
#[derive(Clone, Debug, Default)]
pub struct DirListDisplayOptions {
- filter_string: String,
+ filter_context: MatchContext,
depth: u8,
}
@@ -67,12 +68,12 @@ impl LineNumberStyle {
}
impl DirListDisplayOptions {
- pub fn set_filter_string(&mut self, pattern: &str) {
- self.filter_string = pattern.to_owned();
+ pub fn set_filter_context(&mut self, filter_context: MatchContext) {
+ self.filter_context = filter_context;
}
- pub fn filter_string_ref(&self) -> &str {
- &self.filter_string
+ pub fn filter_context_ref(&self) -> &MatchContext {
+ &self.filter_context
}
pub fn set_depth(&mut self, depth: u8) {
@@ -192,18 +193,6 @@ impl std::default::Default for DisplayOption {
}
}
-fn has_str(entry: &walkdir::DirEntry, pat: &str) -> bool {
- entry
- .file_name()
- .to_str