Toggle buffer search options via the keyboard
This commit is contained in:
parent
fcd99c865e
commit
a835dcefa2
4 changed files with 90 additions and 35 deletions
|
@ -15,7 +15,7 @@
|
||||||
"shift-cmd-}": "pane::ActivateNextItem",
|
"shift-cmd-}": "pane::ActivateNextItem",
|
||||||
"cmd-w": "pane::CloseActiveItem",
|
"cmd-w": "pane::CloseActiveItem",
|
||||||
"cmd-shift-W": "workspace::CloseWindow",
|
"cmd-shift-W": "workspace::CloseWindow",
|
||||||
"alt-cmd-w": "pane::CloseInactiveItems",
|
"cmd-k alt-cmd-w": "pane::CloseInactiveItems",
|
||||||
"cmd-s": "workspace::Save",
|
"cmd-s": "workspace::Save",
|
||||||
"cmd-shift-S": "workspace::SaveAs",
|
"cmd-shift-S": "workspace::SaveAs",
|
||||||
"cmd-=": "zed::IncreaseBufferFontSize",
|
"cmd-=": "zed::IncreaseBufferFontSize",
|
||||||
|
@ -146,7 +146,25 @@
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"cmd-f": "project_search::ToggleFocus",
|
"cmd-f": "project_search::ToggleFocus",
|
||||||
"cmd-g": "search::SelectNextMatch",
|
"cmd-g": "search::SelectNextMatch",
|
||||||
"cmd-shift-G": "search::SelectPrevMatch"
|
"cmd-shift-G": "search::SelectPrevMatch",
|
||||||
|
"alt-cmd-c": [
|
||||||
|
"search::ToggleSearchOption",
|
||||||
|
{
|
||||||
|
"option": "CaseSensitive"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"alt-cmd-w": [
|
||||||
|
"search::ToggleSearchOption",
|
||||||
|
{
|
||||||
|
"option": "WholeWord"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"alt-cmd-r": [
|
||||||
|
"search::ToggleSearchOption",
|
||||||
|
{
|
||||||
|
"option": "Regex"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
active_match_index, match_index_for_direction, query_suggestion_for_editor, Direction,
|
active_match_index, match_index_for_direction, query_suggestion_for_editor, Direction,
|
||||||
SearchOption, SelectNextMatch, SelectPrevMatch,
|
SearchOption, SelectNextMatch, SelectPrevMatch, ToggleSearchOption,
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{Anchor, Autoscroll, Editor};
|
use editor::{Anchor, Autoscroll, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, impl_actions, impl_internal_actions, platform::CursorStyle, AppContext,
|
actions, elements::*, impl_actions, platform::CursorStyle, AppContext, Entity,
|
||||||
Entity, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
||||||
WeakViewHandle,
|
WeakViewHandle,
|
||||||
};
|
};
|
||||||
use language::OffsetRangeExt;
|
use language::OffsetRangeExt;
|
||||||
|
@ -21,12 +21,8 @@ pub struct Deploy {
|
||||||
pub focus: bool,
|
pub focus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub struct ToggleSearchOption(pub SearchOption);
|
|
||||||
|
|
||||||
actions!(buffer_search, [Dismiss, FocusEditor]);
|
actions!(buffer_search, [Dismiss, FocusEditor]);
|
||||||
impl_actions!(buffer_search, [Deploy]);
|
impl_actions!(buffer_search, [Deploy]);
|
||||||
impl_internal_actions!(buffer_search, [ToggleSearchOption]);
|
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
UpdateLocation,
|
UpdateLocation,
|
||||||
|
@ -36,7 +32,21 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(BufferSearchBar::deploy);
|
cx.add_action(BufferSearchBar::deploy);
|
||||||
cx.add_action(BufferSearchBar::dismiss);
|
cx.add_action(BufferSearchBar::dismiss);
|
||||||
cx.add_action(BufferSearchBar::focus_editor);
|
cx.add_action(BufferSearchBar::focus_editor);
|
||||||
cx.add_action(BufferSearchBar::toggle_search_option);
|
cx.add_action(
|
||||||
|
|pane: &mut Pane,
|
||||||
|
ToggleSearchOption { option }: &ToggleSearchOption,
|
||||||
|
cx: &mut ViewContext<Pane>| {
|
||||||
|
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||||
|
if search_bar.update(cx, |search_bar, cx| search_bar.show(false, false, cx)) {
|
||||||
|
search_bar.update(cx, |search_bar, cx| {
|
||||||
|
search_bar.toggle_search_option(*option, cx);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cx.propagate_action();
|
||||||
|
},
|
||||||
|
);
|
||||||
cx.add_action(BufferSearchBar::select_next_match);
|
cx.add_action(BufferSearchBar::select_next_match);
|
||||||
cx.add_action(BufferSearchBar::select_prev_match);
|
cx.add_action(BufferSearchBar::select_prev_match);
|
||||||
cx.add_action(BufferSearchBar::select_next_match_on_pane);
|
cx.add_action(BufferSearchBar::select_next_match_on_pane);
|
||||||
|
@ -215,17 +225,19 @@ impl BufferSearchBar {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, focus: bool, cx: &mut ViewContext<Self>) -> bool {
|
fn show(&mut self, focus: bool, suggest_query: bool, cx: &mut ViewContext<Self>) -> bool {
|
||||||
let editor = if let Some(editor) = self.active_editor.clone() {
|
let editor = if let Some(editor) = self.active_editor.clone() {
|
||||||
editor
|
editor
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if suggest_query {
|
||||||
let text = query_suggestion_for_editor(&editor, cx);
|
let text = query_suggestion_for_editor(&editor, cx);
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
self.set_query(&text, cx);
|
self.set_query(&text, cx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if focus {
|
if focus {
|
||||||
let query_editor = self.query_editor.clone();
|
let query_editor = self.query_editor.clone();
|
||||||
|
@ -253,11 +265,12 @@ impl BufferSearchBar {
|
||||||
fn render_search_option(
|
fn render_search_option(
|
||||||
&self,
|
&self,
|
||||||
icon: &str,
|
icon: &str,
|
||||||
search_option: SearchOption,
|
option: SearchOption,
|
||||||
cx: &mut RenderContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
let is_active = self.is_search_option_enabled(search_option);
|
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
|
||||||
MouseEventHandler::new::<Self, _, _>(search_option as usize, cx, |state, cx| {
|
let is_active = self.is_search_option_enabled(option);
|
||||||
|
MouseEventHandler::new::<Self, _, _>(option as usize, cx, |state, cx| {
|
||||||
let style = &cx
|
let style = &cx
|
||||||
.global::<Settings>()
|
.global::<Settings>()
|
||||||
.theme
|
.theme
|
||||||
|
@ -269,8 +282,15 @@ impl BufferSearchBar {
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(search_option)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption { option }))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.with_tooltip::<Self, _>(
|
||||||
|
option as usize,
|
||||||
|
format!("Toggle {}", option.label()),
|
||||||
|
Some(Box::new(ToggleSearchOption { option })),
|
||||||
|
tooltip_style,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +323,7 @@ impl BufferSearchBar {
|
||||||
|
|
||||||
fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext<Pane>) {
|
fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext<Pane>) {
|
||||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||||
if search_bar.update(cx, |search_bar, cx| search_bar.show(action.focus, cx)) {
|
if search_bar.update(cx, |search_bar, cx| search_bar.show(action.focus, true, cx)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,11 +354,7 @@ impl BufferSearchBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_search_option(
|
fn toggle_search_option(&mut self, search_option: SearchOption, cx: &mut ViewContext<Self>) {
|
||||||
&mut self,
|
|
||||||
ToggleSearchOption(search_option): &ToggleSearchOption,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) {
|
|
||||||
let value = match search_option {
|
let value = match search_option {
|
||||||
SearchOption::WholeWord => &mut self.whole_word,
|
SearchOption::WholeWord => &mut self.whole_word,
|
||||||
SearchOption::CaseSensitive => &mut self.case_sensitive,
|
SearchOption::CaseSensitive => &mut self.case_sensitive,
|
||||||
|
@ -591,7 +607,7 @@ mod tests {
|
||||||
let search_bar = cx.add_view(Default::default(), |cx| {
|
let search_bar = cx.add_view(Default::default(), |cx| {
|
||||||
let mut search_bar = BufferSearchBar::new(cx);
|
let mut search_bar = BufferSearchBar::new(cx);
|
||||||
search_bar.set_active_pane_item(Some(&editor), cx);
|
search_bar.set_active_pane_item(Some(&editor), cx);
|
||||||
search_bar.show(false, cx);
|
search_bar.show(false, true, cx);
|
||||||
search_bar
|
search_bar
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -619,7 +635,7 @@ mod tests {
|
||||||
|
|
||||||
// Switch to a case sensitive search.
|
// Switch to a case sensitive search.
|
||||||
search_bar.update(cx, |search_bar, cx| {
|
search_bar.update(cx, |search_bar, cx| {
|
||||||
search_bar.toggle_search_option(&ToggleSearchOption(SearchOption::CaseSensitive), cx);
|
search_bar.toggle_search_option(SearchOption::CaseSensitive, cx);
|
||||||
});
|
});
|
||||||
editor.next_notification(&cx).await;
|
editor.next_notification(&cx).await;
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
@ -676,7 +692,7 @@ mod tests {
|
||||||
|
|
||||||
// Switch to a whole word search.
|
// Switch to a whole word search.
|
||||||
search_bar.update(cx, |search_bar, cx| {
|
search_bar.update(cx, |search_bar, cx| {
|
||||||
search_bar.toggle_search_option(&ToggleSearchOption(SearchOption::WholeWord), cx);
|
search_bar.toggle_search_option(SearchOption::WholeWord, cx);
|
||||||
});
|
});
|
||||||
editor.next_notification(&cx).await;
|
editor.next_notification(&cx).await;
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
|
|
@ -655,7 +655,7 @@ impl ProjectSearchBar {
|
||||||
|
|
||||||
fn toggle_search_option(
|
fn toggle_search_option(
|
||||||
&mut self,
|
&mut self,
|
||||||
ToggleSearchOption(option): &ToggleSearchOption,
|
ToggleSearchOption { option }: &ToggleSearchOption,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(search_view) = self.active_project_search.as_ref() {
|
if let Some(search_view) = self.active_project_search.as_ref() {
|
||||||
|
@ -705,8 +705,9 @@ impl ProjectSearchBar {
|
||||||
option: SearchOption,
|
option: SearchOption,
|
||||||
cx: &mut RenderContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
|
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
|
||||||
let is_active = self.is_option_enabled(option, cx);
|
let is_active = self.is_option_enabled(option, cx);
|
||||||
MouseEventHandler::new::<ProjectSearchBar, _, _>(option as usize, cx, |state, cx| {
|
MouseEventHandler::new::<Self, _, _>(option as usize, cx, |state, cx| {
|
||||||
let style = &cx
|
let style = &cx
|
||||||
.global::<Settings>()
|
.global::<Settings>()
|
||||||
.theme
|
.theme
|
||||||
|
@ -718,8 +719,15 @@ impl ProjectSearchBar {
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(option)))
|
.on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption { option }))
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.with_tooltip::<Self, _>(
|
||||||
|
option as usize,
|
||||||
|
format!("Toggle {}", option.label()),
|
||||||
|
Some(Box::new(ToggleSearchOption { option })),
|
||||||
|
tooltip_style,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
pub use buffer_search::BufferSearchBar;
|
pub use buffer_search::BufferSearchBar;
|
||||||
use editor::{display_map::ToDisplayPoint, Anchor, Bias, Editor, MultiBufferSnapshot};
|
use editor::{display_map::ToDisplayPoint, Anchor, Bias, Editor, MultiBufferSnapshot};
|
||||||
use gpui::{actions, impl_internal_actions, MutableAppContext, ViewHandle};
|
use gpui::{actions, impl_actions, MutableAppContext, ViewHandle};
|
||||||
pub use project_search::{ProjectSearchBar, ProjectSearchView};
|
pub use project_search::{ProjectSearchBar, ProjectSearchView};
|
||||||
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Ordering},
|
cmp::{self, Ordering},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
|
@ -15,19 +16,31 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
project_search::init(cx);
|
project_search::init(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Deserialize)]
|
||||||
pub struct ToggleSearchOption(pub SearchOption);
|
pub struct ToggleSearchOption {
|
||||||
|
pub option: SearchOption,
|
||||||
|
}
|
||||||
|
|
||||||
actions!(search, [SelectNextMatch, SelectPrevMatch]);
|
actions!(search, [SelectNextMatch, SelectPrevMatch]);
|
||||||
impl_internal_actions!(search, [ToggleSearchOption]);
|
impl_actions!(search, [ToggleSearchOption]);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq, Deserialize)]
|
||||||
pub enum SearchOption {
|
pub enum SearchOption {
|
||||||
WholeWord,
|
WholeWord,
|
||||||
CaseSensitive,
|
CaseSensitive,
|
||||||
Regex,
|
Regex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SearchOption {
|
||||||
|
pub fn label(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
SearchOption::WholeWord => "Match Whole Word",
|
||||||
|
SearchOption::CaseSensitive => "Match Case",
|
||||||
|
SearchOption::Regex => "Use Regular Expression",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Prev,
|
Prev,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue