Highlight regex in the project search input (#25147)

Follow-up of https://github.com/zed-industries/zed/pull/25005

Project search also has regex search option, highlight it the same way
too.

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-02-19 13:04:44 +02:00 committed by GitHub
parent 48417866cc
commit 2274e88299
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,6 +3,7 @@ use crate::{
ReplaceAll, ReplaceNext, SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ReplaceAll, ReplaceNext, SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive,
ToggleIncludeIgnored, ToggleRegex, ToggleReplace, ToggleWholeWord, ToggleIncludeIgnored, ToggleRegex, ToggleReplace, ToggleWholeWord,
}; };
use anyhow::Context as _;
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use editor::{ use editor::{
actions::SelectAll, items::active_match_index, scroll::Autoscroll, Anchor, Editor, actions::SelectAll, items::active_match_index, scroll::Autoscroll, Anchor, Editor,
@ -15,7 +16,7 @@ use gpui::{
ParentElement, Point, Render, SharedString, Styled, Subscription, Task, TextStyle, ParentElement, Point, Render, SharedString, Styled, Subscription, Task, TextStyle,
UpdateGlobal, WeakEntity, Window, UpdateGlobal, WeakEntity, Window,
}; };
use language::Buffer; use language::{Buffer, Language};
use menu::Confirm; use menu::Confirm;
use project::{ use project::{
search::{SearchInputKind, SearchQuery}, search::{SearchInputKind, SearchQuery},
@ -29,6 +30,7 @@ use std::{
ops::{Not, Range}, ops::{Not, Range},
path::Path, path::Path,
pin::pin, pin::pin,
sync::Arc,
}; };
use theme::ThemeSettings; use theme::ThemeSettings;
use ui::{ use ui::{
@ -167,6 +169,7 @@ pub struct ProjectSearchView {
filters_enabled: bool, filters_enabled: bool,
replace_enabled: bool, replace_enabled: bool,
included_opened_only: bool, included_opened_only: bool,
regex_language: Option<Arc<Language>>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
} }
@ -613,6 +616,7 @@ impl ProjectSearchView {
self.current_settings(), self.current_settings(),
); );
}); });
self.adjust_query_regex_language(cx);
} }
fn toggle_opened_only(&mut self, _window: &mut Window, _cx: &mut Context<Self>) { fn toggle_opened_only(&mut self, _window: &mut Window, _cx: &mut Context<Self>) {
@ -791,6 +795,22 @@ impl ProjectSearchView {
} }
})); }));
let languages = project.read(cx).languages().clone();
cx.spawn(|project_search_view, mut cx| async move {
let regex_language = languages
.language_for_name("regex")
.await
.context("loading regex language")?;
project_search_view
.update(&mut cx, |project_search_view, cx| {
project_search_view.regex_language = Some(regex_language);
project_search_view.adjust_query_regex_language(cx);
})
.ok();
anyhow::Ok(())
})
.detach_and_log_err(cx);
// Check if Worktrees have all been previously indexed // Check if Worktrees have all been previously indexed
let mut this = ProjectSearchView { let mut this = ProjectSearchView {
workspace, workspace,
@ -808,6 +828,7 @@ impl ProjectSearchView {
filters_enabled, filters_enabled,
replace_enabled: false, replace_enabled: false,
included_opened_only: false, included_opened_only: false,
regex_language: None,
_subscriptions: subscriptions, _subscriptions: subscriptions,
}; };
this.entity_changed(window, cx); this.entity_changed(window, cx);
@ -1338,6 +1359,28 @@ impl ProjectSearchView {
pub fn results_editor(&self) -> &Entity<Editor> { pub fn results_editor(&self) -> &Entity<Editor> {
&self.results_editor &self.results_editor
} }
fn adjust_query_regex_language(&self, cx: &mut App) {
let enable = self.search_options.contains(SearchOptions::REGEX);
let query_buffer = self
.query_editor
.read(cx)
.buffer()
.read(cx)
.as_singleton()
.expect("query editor should be backed by a singleton buffer");
if enable {
if let Some(regex_language) = self.regex_language.clone() {
query_buffer.update(cx, |query_buffer, cx| {
query_buffer.set_language(Some(regex_language), cx);
})
}
} else {
query_buffer.update(cx, |query_buffer, cx| {
query_buffer.set_language(None, cx);
})
}
}
} }
fn buffer_search_query( fn buffer_search_query(
@ -1461,7 +1504,6 @@ impl ProjectSearchBar {
search_view.search(cx); search_view.search(cx);
} }
}); });
cx.notify(); cx.notify();
true true
} else { } else {
@ -1666,31 +1708,34 @@ impl ProjectSearchBar {
} }
fn render_text_input(&self, editor: &Entity<Editor>, cx: &Context<Self>) -> impl IntoElement { fn render_text_input(&self, editor: &Entity<Editor>, cx: &Context<Self>) -> impl IntoElement {
let (color, use_syntax) = if editor.read(cx).read_only(cx) {
(cx.theme().colors().text_disabled, false)
} else {
(cx.theme().colors().text, true)
};
let settings = ThemeSettings::get_global(cx); let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle { let text_style = TextStyle {
color: if editor.read(cx).read_only(cx) { color,
cx.theme().colors().text_disabled
} else {
cx.theme().colors().text
},
font_family: settings.buffer_font.family.clone(), font_family: settings.buffer_font.family.clone(),
font_features: settings.buffer_font.features.clone(), font_features: settings.buffer_font.features.clone(),
font_fallbacks: settings.buffer_font.fallbacks.clone(), font_fallbacks: settings.buffer_font.fallbacks.clone(),
font_size: rems(0.875).into(), font_size: rems(0.875).into(),
font_weight: settings.buffer_font.weight, font_weight: settings.buffer_font.weight,
line_height: relative(1.3), line_height: relative(1.3),
..Default::default() ..TextStyle::default()
}; };
EditorElement::new( let mut editor_style = EditorStyle {
editor, background: cx.theme().colors().editor_background,
EditorStyle { local_player: cx.theme().players().local(),
background: cx.theme().colors().editor_background, text: text_style,
local_player: cx.theme().players().local(), ..EditorStyle::default()
text: text_style, };
..Default::default() if use_syntax {
}, editor_style.syntax = cx.theme().syntax().clone();
) }
EditorElement::new(editor, editor_style)
} }
} }