@@ -6,6 +6,7 @@ use crate::{
ToggleCaseSensitive, ToggleRegex, ToggleReplace, ToggleSelection, ToggleWholeWord,
};
use any_vec::AnyVec;
+use anyhow::Context as _;
use collections::HashMap;
use editor::{
actions::{Tab, TabPrev},
@@ -14,9 +15,10 @@ use editor::{
use futures::channel::oneshot;
use gpui::{
actions, div, impl_actions, Action, App, ClickEvent, Context, Entity, EventEmitter,
- FocusHandle, Focusable, Hsla, InteractiveElement as _, IntoElement, KeyContext,
- ParentElement as _, Render, ScrollHandle, Styled, Subscription, Task, TextStyle, Window,
+ FocusHandle, Focusable, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _,
+ Render, ScrollHandle, Styled, Subscription, Task, TextStyle, Window,
};
+use language::{Language, LanguageRegistry};
use project::{
search::SearchQuery,
search_history::{SearchHistory, SearchHistoryCursor},
@@ -108,41 +110,48 @@ pub struct BufferSearchBar {
scroll_handle: ScrollHandle,
editor_scroll_handle: ScrollHandle,
editor_needed_width: Pixels,
+ regex_language: Option<Arc<Language>>,
}
impl BufferSearchBar {
fn render_text_input(
&self,
editor: &Entity<Editor>,
- color: Hsla,
-
+ color_override: Option<Color>,
cx: &mut Context<Self>,
) -> impl IntoElement {
+ let (color, use_syntax) = if editor.read(cx).read_only(cx) {
+ (cx.theme().colors().text_disabled, false)
+ } else {
+ match color_override {
+ Some(color_override) => (color_override.color(cx), false),
+ None => (cx.theme().colors().text, true),
+ }
+ };
+
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
- color: if editor.read(cx).read_only(cx) {
- cx.theme().colors().text_disabled
- } else {
- color
- },
+ color,
font_family: settings.buffer_font.family.clone(),
font_features: settings.buffer_font.features.clone(),
font_fallbacks: settings.buffer_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.buffer_font.weight,
line_height: relative(1.3),
- ..Default::default()
+ ..TextStyle::default()
};
- EditorElement::new(
- editor,
- EditorStyle {
- background: cx.theme().colors().editor_background,
- local_player: cx.theme().players().local(),
- text: text_style,
- ..Default::default()
- },
- )
+ let mut editor_style = EditorStyle {
+ background: cx.theme().colors().editor_background,
+ local_player: cx.theme().players().local(),
+ text: text_style,
+ ..EditorStyle::default()
+ };
+ if use_syntax {
+ editor_style.syntax = cx.theme().syntax().clone();
+ }
+
+ EditorElement::new(editor, editor_style)
}
pub fn query_editor_focused(&self) -> bool {
@@ -179,7 +188,7 @@ impl Render for BufferSearchBar {
editor.set_placeholder_text("Replace withβ¦", cx);
});
- let mut text_color = Color::Default;
+ let mut color_override = None;
let match_text = self
.active_searchable_item
.as_ref()
@@ -195,7 +204,7 @@ impl Render for BufferSearchBar {
if let Some(match_ix) = self.active_match_index {
Some(format!("{}/{}", match_ix + 1, matches_count))
} else {
- text_color = Color::Error; // No matches found
+ color_override = Some(Color::Error); // No matches found
None
}
})
@@ -239,7 +248,7 @@ impl Render for BufferSearchBar {
input_base_styles()
.id("editor-scroll")
.track_scroll(&self.editor_scroll_handle)
- .child(self.render_text_input(&self.query_editor, text_color.color(cx), cx))
+ .child(self.render_text_input(&self.query_editor, color_override, cx))
.when(!hide_inline_icons, |div| {
div.child(
h_flex()
@@ -412,7 +421,7 @@ impl Render for BufferSearchBar {
.gap_2()
.child(input_base_styles().child(self.render_text_input(
&self.replacement_editor,
- cx.theme().colors().text,
+ None,
cx,
)))
.child(
@@ -652,7 +661,11 @@ impl BufferSearchBar {
}))
}
- pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
+ pub fn new(
+ languages: Option<Arc<LanguageRegistry>>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Self {
let query_editor = cx.new(|cx| Editor::single_line(window, cx));
cx.subscribe_in(&query_editor, window, Self::on_query_editor_event)
.detach();
@@ -661,6 +674,32 @@ impl BufferSearchBar {
.detach();
let search_options = SearchOptions::from_settings(&EditorSettings::get_global(cx).search);
+ if let Some(languages) = languages {
+ let query_buffer = query_editor
+ .read(cx)
+ .buffer()
+ .read(cx)
+ .as_singleton()
+ .expect("query editor should be backed by a singleton buffer");
+ query_buffer.update(cx, |query_buffer, _| {
+ query_buffer.set_language_registry(languages.clone());
+ });
+
+ cx.spawn(|buffer_search_bar, mut cx| async move {
+ let regex_language = languages
+ .language_for_name("regex")
+ .await
+ .context("loading regex language")?;
+ buffer_search_bar
+ .update(&mut cx, |buffer_search_bar, cx| {
+ buffer_search_bar.regex_language = Some(regex_language);
+ buffer_search_bar.adjust_query_regex_language(cx);
+ })
+ .ok();
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
+ }
Self {
query_editor,
@@ -688,6 +727,7 @@ impl BufferSearchBar {
scroll_handle: ScrollHandle::new(),
editor_scroll_handle: ScrollHandle::new(),
editor_needed_width: px(0.),
+ regex_language: None,
}
}
@@ -910,6 +950,7 @@ impl BufferSearchBar {
self.search_options.toggle(search_option);
self.default_options = self.search_options;
drop(self.update_matches(false, window, cx));
+ self.adjust_query_regex_language(cx);
cx.notify();
}
@@ -1429,6 +1470,28 @@ impl BufferSearchBar {
}
}
}
+
+ 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);
+ })
+ }
+ }
}
#[cfg(test)]
@@ -1482,7 +1545,7 @@ mod tests {
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 search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar
@@ -1851,7 +1914,7 @@ mod tests {
});
let search_bar = window.build_entity(cx, |window, cx| {
- let mut search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar
@@ -2059,7 +2122,7 @@ mod tests {
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 search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar
@@ -2133,7 +2196,7 @@ mod tests {
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 search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar
@@ -2513,7 +2576,7 @@ mod tests {
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 search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar
@@ -2596,7 +2659,7 @@ mod tests {
});
let search_bar = cx.new_window_entity(|window, cx| {
- let mut search_bar = BufferSearchBar::new(window, cx);
+ let mut search_bar = BufferSearchBar::new(None, window, cx);
search_bar.set_active_pane_item(Some(&editor), window, cx);
search_bar.show(window, cx);
search_bar