Cargo.lock 🔗
@@ -1727,6 +1727,7 @@ dependencies = [
"editor",
"gpui",
"postage",
+ "theme",
"workspace",
]
Max Brunsfeld created
Cargo.lock | 1
crates/find/Cargo.toml | 1
crates/find/src/find.rs | 88 ++++++++++++++++++++++++++++--
crates/theme/src/theme.rs | 6 ++
crates/zed/assets/themes/_base.toml | 28 +++++++++
5 files changed, 118 insertions(+), 6 deletions(-)
@@ -1727,6 +1727,7 @@ dependencies = [
"editor",
"gpui",
"postage",
+ "theme",
"workspace",
]
@@ -10,5 +10,6 @@ path = "src/find.rs"
aho-corasick = "0.7"
editor = { path = "../editor" }
gpui = { path = "../gpui" }
+theme = { path = "../theme" }
workspace = { path = "../workspace" }
postage = { version = "0.4.1", features = ["futures-traits"] }
@@ -1,4 +1,4 @@
-use aho_corasick::AhoCorasick;
+use aho_corasick::AhoCorasickBuilder;
use editor::{Editor, EditorSettings};
use gpui::{
action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, View,
@@ -10,6 +10,14 @@ use workspace::{ItemViewHandle, Settings, Toolbar, Workspace};
action!(Deploy);
action!(Cancel);
+action!(ToggleMode, SearchMode);
+
+#[derive(Clone, Copy)]
+pub enum SearchMode {
+ WholeWord,
+ CaseSensitive,
+ Regex,
+}
pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([
@@ -18,12 +26,16 @@ pub fn init(cx: &mut MutableAppContext) {
]);
cx.add_action(FindBar::deploy);
cx.add_action(FindBar::cancel);
+ cx.add_action(FindBar::toggle_mode);
}
struct FindBar {
settings: watch::Receiver<Settings>,
query_editor: ViewHandle<Editor>,
active_editor: Option<ViewHandle<Editor>>,
+ case_sensitive_mode: bool,
+ whole_word_mode: bool,
+ regex_mode: bool,
}
impl Entity for FindBar {
@@ -39,10 +51,25 @@ impl View for FindBar {
cx.focus(&self.query_editor);
}
- fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
- ChildView::new(&self.query_editor)
+ fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+ let theme = &self.settings.borrow().theme.find;
+ Flex::column()
+ .with_child(
+ ChildView::new(&self.query_editor)
+ .contained()
+ .with_style(theme.query.container)
+ .boxed(),
+ )
+ .with_child(
+ Flex::column()
+ .with_child(self.render_mode_button("Aa", SearchMode::CaseSensitive, theme, cx))
+ .with_child(self.render_mode_button("|ab|", SearchMode::WholeWord, theme, cx))
+ .with_child(self.render_mode_button(".*", SearchMode::Regex, theme, cx))
+ .contained()
+ .with_style(theme.mode_button_group)
+ .boxed(),
+ )
.contained()
- .with_style(self.settings.borrow().theme.selector.input_editor.container)
.boxed()
}
}
@@ -67,7 +94,7 @@ impl FindBar {
Arc::new(move |_| {
let settings = settings.borrow();
EditorSettings {
- style: settings.theme.selector.input_editor.as_editor(),
+ style: settings.theme.find.query.as_editor(),
tab_size: settings.tab_size,
soft_wrap: editor::SoftWrap::None,
}
@@ -82,10 +109,37 @@ impl FindBar {
Self {
query_editor,
active_editor: None,
+ case_sensitive_mode: false,
+ whole_word_mode: false,
+ regex_mode: false,
settings,
}
}
+ fn render_mode_button(
+ &self,
+ icon: &str,
+ mode: SearchMode,
+ theme: &theme::Find,
+ cx: &mut RenderContext<Self>,
+ ) -> ElementBox {
+ let is_active = self.is_mode_enabled(mode);
+ MouseEventHandler::new::<Self, _, _, _>(0, cx, |state, _| {
+ let style = match (is_active, state.hovered) {
+ (false, false) => &theme.mode_button,
+ (false, true) => &theme.hovered_mode_button,
+ (true, false) => &theme.active_mode_button,
+ (true, true) => &theme.active_hovered_mode_button,
+ };
+ Label::new(icon.to_string(), style.text.clone())
+ .contained()
+ .with_style(style.container)
+ .boxed()
+ })
+ .on_click(move |cx| cx.dispatch_action(ToggleMode(mode)))
+ .boxed()
+ }
+
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
let settings = workspace.settings();
workspace.active_pane().update(cx, |pane, cx| {
@@ -102,6 +156,25 @@ impl FindBar {
.update(cx, |pane, cx| pane.hide_toolbar(cx));
}
+ fn is_mode_enabled(&self, mode: SearchMode) -> bool {
+ match mode {
+ SearchMode::WholeWord => self.whole_word_mode,
+ SearchMode::CaseSensitive => self.case_sensitive_mode,
+ SearchMode::Regex => self.regex_mode,
+ }
+ }
+
+ fn toggle_mode(&mut self, ToggleMode(mode): &ToggleMode, cx: &mut ViewContext<Self>) {
+ eprintln!("TOGGLE MODE");
+ let value = match mode {
+ SearchMode::WholeWord => &mut self.whole_word_mode,
+ SearchMode::CaseSensitive => &mut self.case_sensitive_mode,
+ SearchMode::Regex => &mut self.regex_mode,
+ };
+ *value = !*value;
+ cx.notify();
+ }
+
fn on_query_editor_event(
&mut self,
_: ViewHandle<Editor>,
@@ -117,7 +190,10 @@ impl FindBar {
return;
}
- let search = AhoCorasick::new_auto_configured(&[search]);
+ let search = AhoCorasickBuilder::new()
+ .auto_configure(&[&search])
+ .ascii_case_insensitive(!self.case_sensitive_mode)
+ .build(&[&search]);
let buffer = editor.buffer().read(cx).snapshot(cx);
let ranges = search
.stream_find_iter(buffer.bytes_in_range(0..buffer.len()))
@@ -90,6 +90,12 @@ pub struct Tab {
#[derive(Clone, Deserialize, Default)]
pub struct Find {
+ pub query: InputEditorStyle,
+ pub mode_button_group: ContainerStyle,
+ pub mode_button: ContainedText,
+ pub active_mode_button: ContainedText,
+ pub hovered_mode_button: ContainedText,
+ pub active_hovered_mode_button: ContainedText,
pub match_background: Color,
}
@@ -321,3 +321,31 @@ tab_summary_spacing = 10
[find]
match_background = "$state.highlighted_line"
+
+[find.mode_button]
+extends = "$text.1"
+
+[find.mode_button_group]
+corner_radius = 6
+border = { width = 1, color = "$border.0" }
+
+[find.active_mode_button]
+extends = "$find.mode_button"
+background = "$surface.2"
+
+[find.hovered_mode_button]
+extends = "$find.mode_button"
+background = "$surface.2"
+
+[find.active_hovered_mode_button]
+extends = "$find.mode_button"
+background = "$surface.2"
+
+[find.query]
+background = "$surface.1"
+corner_radius = 6
+padding = { left = 16, right = 16, top = 7, bottom = 7 }
+text = "$text.0"
+placeholder_text = "$text.2"
+selection = "$selection.host"
+border = { width = 1, color = "$border.0" }