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(
|
pub fn regex(
|
||||||
query: impl ToString,
|
query: impl ToString,
|
||||||
whole_word: bool,
|
whole_word: bool,
|
||||||
case_sensitive: bool,
|
mut case_sensitive: bool,
|
||||||
include_ignored: bool,
|
include_ignored: bool,
|
||||||
one_match_per_line: bool,
|
one_match_per_line: bool,
|
||||||
files_to_include: PathMatcher,
|
files_to_include: PathMatcher,
|
||||||
|
@ -153,6 +153,14 @@ impl SearchQuery {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let mut query = query.to_string();
|
let mut query = query.to_string();
|
||||||
let initial_query = Arc::from(query.as_str());
|
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 {
|
if whole_word {
|
||||||
let mut word_query = String::new();
|
let mut word_query = String::new();
|
||||||
if let Some(first) = query.get(0..1)
|
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> {
|
pub fn from_proto(message: proto::SearchQuery) -> Result<Self> {
|
||||||
let files_to_include = if message.files_to_include.is_empty() {
|
let files_to_include = if message.files_to_include.is_empty() {
|
||||||
message
|
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 {
|
pub fn query(&self, cx: &App) -> String {
|
||||||
self.query_editor.read(cx).text(cx)
|
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>) {
|
pub fn set_search_options(&mut self, search_options: SearchOptions, cx: &mut Context<Self>) {
|
||||||
self.search_options = search_options;
|
self.search_options = search_options;
|
||||||
self.adjust_query_regex_language(cx);
|
self.adjust_query_regex_language(cx);
|
||||||
|
@ -1514,18 +1526,25 @@ mod tests {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let cx = cx.add_empty_window();
|
let mut editor = None;
|
||||||
let editor =
|
let window = cx.add_window(|window, cx| {
|
||||||
cx.new_window_entity(|window, cx| Editor::for_buffer(buffer.clone(), None, window, cx));
|
let default_key_bindings = settings::KeymapFile::load_asset_allow_partial_failure(
|
||||||
|
"keymaps/default-macos.json",
|
||||||
let search_bar = cx.new_window_entity(|window, cx| {
|
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);
|
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.show(window, cx);
|
||||||
search_bar
|
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]
|
#[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 {
|
pub fn search_query_text(&self, cx: &App) -> String {
|
||||||
self.query_editor.read(cx).text(cx)
|
self.query_editor.read(cx).text(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_search_query(&mut self, cx: &mut Context<Self>) -> Option<SearchQuery> {
|
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`.
|
// 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 {
|
let open_buffers = if self.included_opened_only {
|
||||||
Some(self.open_buffers(cx))
|
Some(self.open_buffers(cx))
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue