vim: Add smartcase search (#16932)
Closes #16878 Release Notes: - Added a vim-style smart case option for search patterns --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
b0045b9324
commit
65bc1ea7c8
5 changed files with 78 additions and 8 deletions
|
@ -289,6 +289,7 @@
|
||||||
// 3. Never populate the search query
|
// 3. Never populate the search query
|
||||||
// "never"
|
// "never"
|
||||||
"seed_search_query_from_cursor": "always",
|
"seed_search_query_from_cursor": "always",
|
||||||
|
"use_smartcase_search": false,
|
||||||
// Inlay hint related settings
|
// Inlay hint related settings
|
||||||
"inlay_hints": {
|
"inlay_hints": {
|
||||||
// Global switch to toggle hints on and off, switched off by default.
|
// Global switch to toggle hints on and off, switched off by default.
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct EditorSettings {
|
||||||
pub scroll_sensitivity: f32,
|
pub scroll_sensitivity: f32,
|
||||||
pub relative_line_numbers: bool,
|
pub relative_line_numbers: bool,
|
||||||
pub seed_search_query_from_cursor: SeedQuerySetting,
|
pub seed_search_query_from_cursor: SeedQuerySetting,
|
||||||
|
pub use_smartcase_search: bool,
|
||||||
pub multi_cursor_modifier: MultiCursorModifier,
|
pub multi_cursor_modifier: MultiCursorModifier,
|
||||||
pub redact_private_values: bool,
|
pub redact_private_values: bool,
|
||||||
pub expand_excerpt_lines: u32,
|
pub expand_excerpt_lines: u32,
|
||||||
|
@ -218,6 +219,7 @@ pub struct EditorSettingsContent {
|
||||||
///
|
///
|
||||||
/// Default: always
|
/// Default: always
|
||||||
pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
|
pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
|
||||||
|
pub use_smartcase_search: Option<bool>,
|
||||||
/// The key to use for adding multiple cursors
|
/// The key to use for adding multiple cursors
|
||||||
///
|
///
|
||||||
/// Default: alt
|
/// Default: alt
|
||||||
|
|
|
@ -567,6 +567,7 @@ impl BufferSearchBar {
|
||||||
active_item.toggle_filtered_search_ranges(deploy.selection_search_enabled, cx);
|
active_item.toggle_filtered_search_ranges(deploy.selection_search_enabled, cx);
|
||||||
}
|
}
|
||||||
self.search_suggested(cx);
|
self.search_suggested(cx);
|
||||||
|
self.smartcase(cx);
|
||||||
self.replace_enabled = deploy.replace_enabled;
|
self.replace_enabled = deploy.replace_enabled;
|
||||||
self.selection_search_enabled = deploy.selection_search_enabled;
|
self.selection_search_enabled = deploy.selection_search_enabled;
|
||||||
if deploy.focus {
|
if deploy.focus {
|
||||||
|
@ -718,13 +719,21 @@ impl BufferSearchBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_search_option(&mut self, search_option: SearchOptions, cx: &mut ViewContext<Self>) {
|
pub fn toggle_search_option(
|
||||||
|
&mut self,
|
||||||
|
search_option: SearchOptions,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
self.search_options.toggle(search_option);
|
self.search_options.toggle(search_option);
|
||||||
self.default_options = self.search_options;
|
self.default_options = self.search_options;
|
||||||
drop(self.update_matches(cx));
|
drop(self.update_matches(cx));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_search_option(&mut self, search_option: SearchOptions) -> bool {
|
||||||
|
self.search_options.contains(search_option)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enable_search_option(
|
pub fn enable_search_option(
|
||||||
&mut self,
|
&mut self,
|
||||||
search_option: SearchOptions,
|
search_option: SearchOptions,
|
||||||
|
@ -819,6 +828,7 @@ impl BufferSearchBar {
|
||||||
editor::EditorEvent::Focused => self.query_editor_focused = true,
|
editor::EditorEvent::Focused => self.query_editor_focused = true,
|
||||||
editor::EditorEvent::Blurred => self.query_editor_focused = false,
|
editor::EditorEvent::Blurred => self.query_editor_focused = false,
|
||||||
editor::EditorEvent::Edited { .. } => {
|
editor::EditorEvent::Edited { .. } => {
|
||||||
|
self.smartcase(cx);
|
||||||
self.clear_matches(cx);
|
self.clear_matches(cx);
|
||||||
let search = self.update_matches(cx);
|
let search = self.update_matches(cx);
|
||||||
|
|
||||||
|
@ -1151,6 +1161,26 @@ impl BufferSearchBar {
|
||||||
self.update_match_index(cx);
|
self.update_match_index(cx);
|
||||||
self.active_match_index.is_some()
|
self.active_match_index.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn should_use_smartcase_search(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
||||||
|
EditorSettings::get_global(cx).use_smartcase_search
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_contains_uppercase(&mut self, str: &String) -> bool {
|
||||||
|
str.chars().any(|c| c.is_uppercase())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn smartcase(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
if self.should_use_smartcase_search(cx) {
|
||||||
|
let query = self.query(cx);
|
||||||
|
if !query.is_empty() {
|
||||||
|
let is_case = self.is_contains_uppercase(&query);
|
||||||
|
if self.has_search_option(SearchOptions::CASE_SENSITIVE) != is_case {
|
||||||
|
self.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -114,6 +114,10 @@ pub fn init(cx: &mut AppContext) {
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_contains_uppercase(str: &str) -> bool {
|
||||||
|
str.chars().any(|c| c.is_uppercase())
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ProjectSearch {
|
pub struct ProjectSearch {
|
||||||
project: Model<Project>,
|
project: Model<Project>,
|
||||||
excerpts: Model<MultiBuffer>,
|
excerpts: Model<MultiBuffer>,
|
||||||
|
@ -651,7 +655,22 @@ impl ProjectSearchView {
|
||||||
});
|
});
|
||||||
// Subscribe to query_editor in order to reraise editor events for workspace item activation purposes
|
// Subscribe to query_editor in order to reraise editor events for workspace item activation purposes
|
||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
cx.subscribe(&query_editor, |_, _, event: &EditorEvent, cx| {
|
cx.subscribe(&query_editor, |this, _, event: &EditorEvent, cx| {
|
||||||
|
match event {
|
||||||
|
EditorEvent::Edited { .. } => {
|
||||||
|
if EditorSettings::get_global(cx).use_smartcase_search {
|
||||||
|
let query = this.search_query_text(cx);
|
||||||
|
if !query.is_empty() {
|
||||||
|
if this.search_options.contains(SearchOptions::CASE_SENSITIVE)
|
||||||
|
!= is_contains_uppercase(&query)
|
||||||
|
{
|
||||||
|
this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -1055,6 +1074,15 @@ impl ProjectSearchView {
|
||||||
fn set_query(&mut self, query: &str, cx: &mut ViewContext<Self>) {
|
fn set_query(&mut self, query: &str, cx: &mut ViewContext<Self>) {
|
||||||
self.query_editor
|
self.query_editor
|
||||||
.update(cx, |query_editor, cx| query_editor.set_text(query, cx));
|
.update(cx, |query_editor, cx| query_editor.set_text(query, cx));
|
||||||
|
if EditorSettings::get_global(cx).use_smartcase_search {
|
||||||
|
if !query.is_empty() {
|
||||||
|
if self.search_options.contains(SearchOptions::CASE_SENSITIVE)
|
||||||
|
!= is_contains_uppercase(query)
|
||||||
|
{
|
||||||
|
self.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_results_editor(&mut self, cx: &mut ViewContext<Self>) {
|
fn focus_results_editor(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
|
|
@ -302,11 +302,15 @@ impl Vim {
|
||||||
query = search_bar.query(cx);
|
query = search_bar.query(cx);
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(search_bar.search(
|
let mut options = SearchOptions::REGEX | SearchOptions::CASE_SENSITIVE;
|
||||||
&query,
|
if search_bar.should_use_smartcase_search(cx) {
|
||||||
Some(SearchOptions::CASE_SENSITIVE | SearchOptions::REGEX),
|
options.set(
|
||||||
cx,
|
SearchOptions::CASE_SENSITIVE,
|
||||||
))
|
search_bar.is_contains_uppercase(&query),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(search_bar.search(&query, Some(options), cx))
|
||||||
});
|
});
|
||||||
let Some(search) = search else { return };
|
let Some(search) = search else { return };
|
||||||
let search_bar = search_bar.downgrade();
|
let search_bar = search_bar.downgrade();
|
||||||
|
@ -368,7 +372,12 @@ impl Vim {
|
||||||
} else {
|
} else {
|
||||||
replacement.search
|
replacement.search
|
||||||
};
|
};
|
||||||
|
if search_bar.should_use_smartcase_search(cx) {
|
||||||
|
options.set(
|
||||||
|
SearchOptions::CASE_SENSITIVE,
|
||||||
|
search_bar.is_contains_uppercase(&search),
|
||||||
|
);
|
||||||
|
}
|
||||||
search_bar.set_replacement(Some(&replacement.replacement), cx);
|
search_bar.set_replacement(Some(&replacement.replacement), cx);
|
||||||
Some(search_bar.search(&search, Some(options), cx))
|
Some(search_bar.search(&search, Some(options), cx))
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue