diff --git a/book/src/editor.md b/book/src/editor.md index 667a7147c..7dbcd4b41 100644 --- a/book/src/editor.md +++ b/book/src/editor.md @@ -280,6 +280,7 @@ Search specific options. | Key | Description | Default | |--|--|---------| | `smart-case` | Enable smart case regex searching (case-insensitive unless pattern contains upper case characters) | `true` | +| `ignore-case-unless-smart` | Enable case-insensitive search, unless overridden by `smart-case` behavior | `false` | | `wrap-around`| Whether the search should wrap after depleting the matches | `true` | ### `[editor.whitespace]` Section diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 2cbdeb451..f61646e99 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2285,7 +2285,7 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir let case_insensitive = if search_config.smart_case { !query.chars().any(char::is_uppercase) } else { - false + search_config.ignore_case_unless_smart }; let wrap_around = search_config.wrap_around; if let Ok(regex) = rope::RegexBuilder::new() @@ -2457,6 +2457,7 @@ fn global_search(cx: &mut Context) { struct GlobalSearchConfig { smart_case: bool, + ignore_case_unless_smart: bool, file_picker_config: helix_view::editor::FilePickerConfig, directory_style: Style, number_style: Style, @@ -2466,6 +2467,7 @@ fn global_search(cx: &mut Context) { let config = cx.editor.config(); let config = GlobalSearchConfig { smart_case: config.search.smart_case, + ignore_case_unless_smart: config.search.ignore_case_unless_smart, file_picker_config: config.file_picker.clone(), directory_style: cx.editor.theme.get("ui.text.directory"), number_style: cx.editor.theme.get("constant.numeric.integer"), @@ -2517,8 +2519,10 @@ fn global_search(cx: &mut Context) { .map(|doc| (doc.path().cloned(), doc.text().to_owned())) .collect(); + let use_case_insensitive = !config.smart_case && config.ignore_case_unless_smart; let matcher = match RegexMatcherBuilder::new() .case_smart(config.smart_case) + .case_insensitive(use_case_insensitive) .build(query) { Ok(matcher) => { diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 106bfbfb8..e31769797 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -120,7 +120,7 @@ pub fn raw_regex_prompt( let case_insensitive = if config.search.smart_case { !input.chars().any(char::is_uppercase) } else { - false + config.search.ignore_case_unless_smart }; match rope::RegexBuilder::new() diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index cb9586e79..448f3e5f1 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -490,6 +490,8 @@ impl Default for LspConfig { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] pub struct SearchConfig { + /// Enables case-insensitive search, unless overridden by `smart_case` behavior. Defaults to false. + pub ignore_case_unless_smart: bool, /// Smart case: Case insensitive searching unless pattern contains upper case characters. Defaults to true. pub smart_case: bool, /// Whether the search should wrap after depleting the matches. Default to true. @@ -1040,6 +1042,7 @@ impl Default for SearchConfig { Self { wrap_around: true, smart_case: true, + ignore_case_unless_smart: false, } } }