Merge pull request #786 from zed-industries/load-keymaps
Allow key bindings to be customized via a JSON file
This commit is contained in:
commit
25e1e3d2df
74 changed files with 1092 additions and 729 deletions
|
@ -20,6 +20,7 @@ workspace = { path = "../workspace" }
|
|||
anyhow = "1.0"
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { path = "../editor", features = ["test-support"] }
|
||||
|
|
|
@ -1,55 +1,46 @@
|
|||
use crate::{active_match_index, match_index_for_direction, Direction, SearchOption, SelectMatch};
|
||||
use crate::{
|
||||
active_match_index, match_index_for_direction, Direction, SearchOption, SelectNextMatch,
|
||||
SelectPrevMatch,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor};
|
||||
use gpui::{
|
||||
actions, elements::*, impl_actions, keymap::Binding, platform::CursorStyle, AppContext, Entity,
|
||||
MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
actions, elements::*, impl_actions, impl_internal_actions, platform::CursorStyle, AppContext,
|
||||
Entity, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle,
|
||||
};
|
||||
use language::OffsetRangeExt;
|
||||
use project::search::SearchQuery;
|
||||
use serde::Deserialize;
|
||||
use settings::Settings;
|
||||
use std::ops::Range;
|
||||
use workspace::{ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Deploy(pub bool);
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct Deploy {
|
||||
pub focus: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ToggleSearchOption(pub SearchOption);
|
||||
|
||||
actions!(buffer_search, [Dismiss, FocusEditor]);
|
||||
impl_actions!(buffer_search, [Deploy, ToggleSearchOption]);
|
||||
impl_actions!(buffer_search, [Deploy]);
|
||||
impl_internal_actions!(buffer_search, [ToggleSearchOption]);
|
||||
|
||||
pub enum Event {
|
||||
UpdateLocation,
|
||||
}
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_bindings([
|
||||
Binding::new("cmd-f", Deploy(true), Some("Editor && mode == full")),
|
||||
Binding::new("cmd-e", Deploy(false), Some("Editor && mode == full")),
|
||||
Binding::new("escape", Dismiss, Some("BufferSearchBar")),
|
||||
Binding::new("cmd-f", FocusEditor, Some("BufferSearchBar")),
|
||||
Binding::new(
|
||||
"enter",
|
||||
SelectMatch(Direction::Next),
|
||||
Some("BufferSearchBar"),
|
||||
),
|
||||
Binding::new(
|
||||
"shift-enter",
|
||||
SelectMatch(Direction::Prev),
|
||||
Some("BufferSearchBar"),
|
||||
),
|
||||
Binding::new("cmd-g", SelectMatch(Direction::Next), Some("Pane")),
|
||||
Binding::new("cmd-shift-G", SelectMatch(Direction::Prev), Some("Pane")),
|
||||
]);
|
||||
cx.add_action(BufferSearchBar::deploy);
|
||||
cx.add_action(BufferSearchBar::dismiss);
|
||||
cx.add_action(BufferSearchBar::focus_editor);
|
||||
cx.add_action(BufferSearchBar::toggle_search_option);
|
||||
cx.add_action(BufferSearchBar::select_match);
|
||||
cx.add_action(BufferSearchBar::select_match_on_pane);
|
||||
cx.add_action(BufferSearchBar::select_next_match);
|
||||
cx.add_action(BufferSearchBar::select_prev_match);
|
||||
cx.add_action(BufferSearchBar::select_next_match_on_pane);
|
||||
cx.add_action(BufferSearchBar::select_prev_match_on_pane);
|
||||
}
|
||||
|
||||
pub struct BufferSearchBar {
|
||||
|
@ -325,14 +316,17 @@ impl BufferSearchBar {
|
|||
.with_style(style.container)
|
||||
.boxed()
|
||||
})
|
||||
.on_click(move |cx| cx.dispatch_action(SelectMatch(direction)))
|
||||
.on_click(move |cx| match direction {
|
||||
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
||||
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn deploy(pane: &mut Pane, Deploy(focus): &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 search_bar.update(cx, |search_bar, cx| search_bar.show(*focus, cx)) {
|
||||
if search_bar.update(cx, |search_bar, cx| search_bar.show(action.focus, cx)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +362,15 @@ impl BufferSearchBar {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
fn select_match(&mut self, &SelectMatch(direction): &SelectMatch, cx: &mut ViewContext<Self>) {
|
||||
fn select_next_match(&mut self, _: &SelectNextMatch, cx: &mut ViewContext<Self>) {
|
||||
self.select_match(Direction::Next, cx);
|
||||
}
|
||||
|
||||
fn select_prev_match(&mut self, _: &SelectPrevMatch, cx: &mut ViewContext<Self>) {
|
||||
self.select_match(Direction::Prev, cx);
|
||||
}
|
||||
|
||||
fn select_match(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
|
||||
if let Some(index) = self.active_match_index {
|
||||
if let Some(editor) = self.active_editor.as_ref() {
|
||||
editor.update(cx, |editor, cx| {
|
||||
|
@ -389,9 +391,23 @@ impl BufferSearchBar {
|
|||
}
|
||||
}
|
||||
|
||||
fn select_match_on_pane(pane: &mut Pane, action: &SelectMatch, cx: &mut ViewContext<Pane>) {
|
||||
fn select_next_match_on_pane(
|
||||
pane: &mut Pane,
|
||||
action: &SelectNextMatch,
|
||||
cx: &mut ViewContext<Pane>,
|
||||
) {
|
||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, |search_bar, cx| search_bar.select_match(action, cx));
|
||||
search_bar.update(cx, |bar, cx| bar.select_next_match(action, cx));
|
||||
}
|
||||
}
|
||||
|
||||
fn select_prev_match_on_pane(
|
||||
pane: &mut Pane,
|
||||
action: &SelectPrevMatch,
|
||||
cx: &mut ViewContext<Pane>,
|
||||
) {
|
||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, |bar, cx| bar.select_prev_match(action, cx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -699,7 +715,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(0));
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
|
||||
|
@ -710,7 +726,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
|
||||
|
@ -721,7 +737,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
|
||||
|
@ -732,7 +748,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
|
||||
|
@ -743,7 +759,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
|
||||
|
@ -754,7 +770,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
|
||||
|
@ -765,7 +781,7 @@ mod tests {
|
|||
});
|
||||
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
|
||||
|
@ -782,7 +798,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(1));
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
|
||||
|
@ -799,7 +815,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(1));
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
|
||||
|
@ -816,7 +832,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(2));
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
|
||||
|
@ -833,7 +849,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(2));
|
||||
search_bar.select_match(&SelectMatch(Direction::Next), cx);
|
||||
search_bar.select_next_match(&SelectNextMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
|
||||
|
@ -850,7 +866,7 @@ mod tests {
|
|||
});
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
assert_eq!(search_bar.active_match_index, Some(0));
|
||||
search_bar.select_match(&SelectMatch(Direction::Prev), cx);
|
||||
search_bar.select_prev_match(&SelectPrevMatch, cx);
|
||||
assert_eq!(
|
||||
editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
|
||||
[DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{
|
||||
active_match_index, match_index_for_direction, Direction, SearchOption, SelectMatch,
|
||||
ToggleSearchOption,
|
||||
active_match_index, match_index_for_direction, Direction, SearchOption, SelectNextMatch,
|
||||
SelectPrevMatch, ToggleSearchOption,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll};
|
||||
use gpui::{
|
||||
actions, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity,
|
||||
ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View,
|
||||
ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||
actions, elements::*, platform::CursorStyle, AppContext, ElementBox, Entity, ModelContext,
|
||||
ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext,
|
||||
ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||
};
|
||||
use project::{search::SearchQuery, Project};
|
||||
use settings::Settings;
|
||||
|
@ -28,20 +28,12 @@ struct ActiveSearches(HashMap<WeakModelHandle<Project>, WeakViewHandle<ProjectSe
|
|||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.set_global(ActiveSearches::default());
|
||||
cx.add_bindings([
|
||||
Binding::new("cmd-shift-F", ToggleFocus, Some("Pane")),
|
||||
Binding::new("cmd-f", ToggleFocus, Some("Pane")),
|
||||
Binding::new("cmd-shift-F", Deploy, Some("Workspace")),
|
||||
Binding::new("enter", Search, Some("ProjectSearchBar")),
|
||||
Binding::new("cmd-enter", SearchInNew, Some("ProjectSearchBar")),
|
||||
Binding::new("cmd-g", SelectMatch(Direction::Next), Some("Pane")),
|
||||
Binding::new("cmd-shift-G", SelectMatch(Direction::Prev), Some("Pane")),
|
||||
]);
|
||||
cx.add_action(ProjectSearchView::deploy);
|
||||
cx.add_action(ProjectSearchBar::search);
|
||||
cx.add_action(ProjectSearchBar::search_in_new);
|
||||
cx.add_action(ProjectSearchBar::toggle_search_option);
|
||||
cx.add_action(ProjectSearchBar::select_match);
|
||||
cx.add_action(ProjectSearchBar::select_next_match);
|
||||
cx.add_action(ProjectSearchBar::select_prev_match);
|
||||
cx.add_action(ProjectSearchBar::toggle_focus);
|
||||
cx.capture_action(ProjectSearchBar::tab);
|
||||
}
|
||||
|
@ -561,18 +553,23 @@ impl ProjectSearchBar {
|
|||
}
|
||||
}
|
||||
|
||||
fn select_match(
|
||||
pane: &mut Pane,
|
||||
&SelectMatch(direction): &SelectMatch,
|
||||
cx: &mut ViewContext<Pane>,
|
||||
) {
|
||||
fn select_next_match(pane: &mut Pane, _: &SelectNextMatch, cx: &mut ViewContext<Pane>) {
|
||||
if let Some(search_view) = pane
|
||||
.active_item()
|
||||
.and_then(|item| item.downcast::<ProjectSearchView>())
|
||||
{
|
||||
search_view.update(cx, |search_view, cx| {
|
||||
search_view.select_match(direction, cx);
|
||||
});
|
||||
search_view.update(cx, |view, cx| view.select_match(Direction::Next, cx));
|
||||
} else {
|
||||
cx.propagate_action();
|
||||
}
|
||||
}
|
||||
|
||||
fn select_prev_match(pane: &mut Pane, _: &SelectPrevMatch, cx: &mut ViewContext<Pane>) {
|
||||
if let Some(search_view) = pane
|
||||
.active_item()
|
||||
.and_then(|item| item.downcast::<ProjectSearchView>())
|
||||
{
|
||||
search_view.update(cx, |view, cx| view.select_match(Direction::Prev, cx));
|
||||
} else {
|
||||
cx.propagate_action();
|
||||
}
|
||||
|
@ -651,7 +648,10 @@ impl ProjectSearchBar {
|
|||
.with_style(style.container)
|
||||
.boxed()
|
||||
})
|
||||
.on_click(move |cx| cx.dispatch_action(SelectMatch(direction)))
|
||||
.on_click(move |cx| match direction {
|
||||
Direction::Prev => cx.dispatch_action(SelectPrevMatch),
|
||||
Direction::Next => cx.dispatch_action(SelectNextMatch),
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.boxed()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub use buffer_search::BufferSearchBar;
|
||||
use editor::{Anchor, MultiBufferSnapshot};
|
||||
use gpui::{impl_actions, MutableAppContext};
|
||||
use gpui::{actions, impl_internal_actions, MutableAppContext};
|
||||
pub use project_search::{ProjectSearchBar, ProjectSearchView};
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
|
@ -18,10 +18,8 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
#[derive(Clone)]
|
||||
pub struct ToggleSearchOption(pub SearchOption);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SelectMatch(pub Direction);
|
||||
|
||||
impl_actions!(search, [ToggleSearchOption, SelectMatch]);
|
||||
actions!(search, [SelectNextMatch, SelectPrevMatch]);
|
||||
impl_internal_actions!(search, [ToggleSearchOption]);
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum SearchOption {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue