Merge 9c35cd6a87
into bd4e943597
This commit is contained in:
commit
5398443e94
3 changed files with 159 additions and 9 deletions
|
@ -143,7 +143,7 @@ impl SearchQuery {
|
|||
pub fn regex(
|
||||
query: impl ToString,
|
||||
whole_word: bool,
|
||||
case_sensitive: bool,
|
||||
mut case_sensitive: bool,
|
||||
include_ignored: bool,
|
||||
one_match_per_line: bool,
|
||||
files_to_include: PathMatcher,
|
||||
|
@ -153,6 +153,14 @@ impl SearchQuery {
|
|||
) -> Result<Self> {
|
||||
let mut query = query.to_string();
|
||||
let initial_query = Arc::from(query.as_str());
|
||||
|
||||
if let Some((case_sensitive_from_pattern, new_query)) =
|
||||
Self::case_sensitive_from_pattern(&query)
|
||||
{
|
||||
case_sensitive = case_sensitive_from_pattern;
|
||||
query = new_query
|
||||
}
|
||||
|
||||
if whole_word {
|
||||
let mut word_query = String::new();
|
||||
if let Some(first) = query.get(0..1)
|
||||
|
@ -192,6 +200,45 @@ impl SearchQuery {
|
|||
})
|
||||
}
|
||||
|
||||
/// Extracts case sensitivity settings from pattern items in the provided
|
||||
/// query and returns the same query, with the pattern items removed.
|
||||
///
|
||||
/// The following pattern modifiers are supported:
|
||||
///
|
||||
/// - `\c` (case_sensitive: false)
|
||||
/// - `\C` (case_sensitive: true)
|
||||
///
|
||||
/// If no pattern item were found, `None` will be returned.
|
||||
fn case_sensitive_from_pattern(query: &str) -> Option<(bool, String)> {
|
||||
if !(query.contains("\\c") || query.contains("\\C")) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut was_escaped = false;
|
||||
let mut new_query = String::new();
|
||||
let mut is_case_sensitive = None;
|
||||
|
||||
for c in query.chars() {
|
||||
if was_escaped {
|
||||
if c == 'c' {
|
||||
is_case_sensitive = Some(false);
|
||||
} else if c == 'C' {
|
||||
is_case_sensitive = Some(true);
|
||||
} else {
|
||||
new_query.push('\\');
|
||||
new_query.push(c);
|
||||
}
|
||||
was_escaped = false
|
||||
} else if c == '\\' {
|
||||
was_escaped = true
|
||||
} else {
|
||||
new_query.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
is_case_sensitive.map(|c| (c, new_query))
|
||||
}
|
||||
|
||||
pub fn from_proto(message: proto::SearchQuery) -> Result<Self> {
|
||||
let files_to_include = if message.files_to_include.is_empty() {
|
||||
message
|
||||
|
@ -596,4 +643,87 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_case_sensitive_pattern_items() {
|
||||
let case_sensitive = false;
|
||||
let search_query = SearchQuery::regex(
|
||||
"test\\C",
|
||||
false,
|
||||
case_sensitive,
|
||||
false,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("Should be able to create a regex SearchQuery");
|
||||
|
||||
assert_eq!(
|
||||
search_query.case_sensitive(),
|
||||
true,
|
||||
"Case sensitivity should be enabled when \\C pattern item is present in the query."
|
||||
);
|
||||
|
||||
let case_sensitive = true;
|
||||
let search_query = SearchQuery::regex(
|
||||
"test\\c",
|
||||
true,
|
||||
case_sensitive,
|
||||
false,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("Should be able to create a regex SearchQuery");
|
||||
|
||||
assert_eq!(
|
||||
search_query.case_sensitive(),
|
||||
false,
|
||||
"Case sensitivity should be disabled when \\c pattern item is present, even if initially set to true."
|
||||
);
|
||||
|
||||
let case_sensitive = false;
|
||||
let search_query = SearchQuery::regex(
|
||||
"test\\c\\C",
|
||||
false,
|
||||
case_sensitive,
|
||||
false,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("Should be able to create a regex SearchQuery");
|
||||
|
||||
assert_eq!(
|
||||
search_query.case_sensitive(),
|
||||
true,
|
||||
"Case sensitivity should be enabled when \\C is the last pattern item, even after a \\c."
|
||||
);
|
||||
|
||||
let case_sensitive = false;
|
||||
let search_query = SearchQuery::regex(
|
||||
"tests\\\\C",
|
||||
false,
|
||||
case_sensitive,
|
||||
false,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("Should be able to create a regex SearchQuery");
|
||||
|
||||
assert_eq!(
|
||||
search_query.case_sensitive(),
|
||||
false,
|
||||
"Case sensitivity should not be enabled when \\C pattern item is preceded by a backslash."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -810,6 +810,7 @@ impl BufferSearchBar {
|
|||
});
|
||||
}
|
||||
|
||||
/// Returns the sanitized query string with pattern items removed.
|
||||
pub fn query(&self, cx: &App) -> String {
|
||||
self.query_editor.read(cx).text(cx)
|
||||
}
|
||||
|
@ -909,6 +910,17 @@ impl BufferSearchBar {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn disable_search_option(
|
||||
&mut self,
|
||||
search_option: SearchOptions,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.search_options.contains(search_option) {
|
||||
self.toggle_search_option(search_option, window, cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_search_options(&mut self, search_options: SearchOptions, cx: &mut Context<Self>) {
|
||||
self.search_options = search_options;
|
||||
self.adjust_query_regex_language(cx);
|
||||
|
@ -1514,18 +1526,25 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
});
|
||||
let cx = cx.add_empty_window();
|
||||
let editor =
|
||||
cx.new_window_entity(|window, cx| Editor::for_buffer(buffer.clone(), None, window, cx));
|
||||
|
||||
let search_bar = cx.new_window_entity(|window, cx| {
|
||||
let mut editor = None;
|
||||
let window = cx.add_window(|window, cx| {
|
||||
let default_key_bindings = settings::KeymapFile::load_asset_allow_partial_failure(
|
||||
"keymaps/default-macos.json",
|
||||
cx,
|
||||
)
|
||||
.unwrap();
|
||||
cx.bind_keys(default_key_bindings);
|
||||
editor = Some(cx.new(|cx| Editor::for_buffer(buffer.clone(), None, window, cx)));
|
||||
let mut search_bar = BufferSearchBar::new(None, window, cx);
|
||||
search_bar.set_active_pane_item(Some(&editor), window, cx);
|
||||
search_bar.set_active_pane_item(Some(&editor.clone().unwrap()), window, cx);
|
||||
search_bar.show(window, cx);
|
||||
search_bar
|
||||
});
|
||||
let search_bar = window.root(cx).unwrap();
|
||||
|
||||
(editor, search_bar, cx)
|
||||
let cx = VisualTestContext::from_window(*window, cx).into_mut();
|
||||
|
||||
(editor.unwrap(), search_bar, cx)
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
@ -1133,13 +1133,14 @@ impl ProjectSearchView {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the search query text without pattern items.
|
||||
pub fn search_query_text(&self, cx: &App) -> String {
|
||||
self.query_editor.read(cx).text(cx)
|
||||
}
|
||||
|
||||
fn build_search_query(&mut self, cx: &mut Context<Self>) -> Option<SearchQuery> {
|
||||
// Do not bail early in this function, as we want to fill out `self.panels_with_errors`.
|
||||
let text = self.query_editor.read(cx).text(cx);
|
||||
let text = self.search_query_text(cx);
|
||||
let open_buffers = if self.included_opened_only {
|
||||
Some(self.open_buffers(cx))
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue