diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4d3265f8fa..bda5cda412 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -23,7 +23,6 @@ use gpui::{ fonts::{self, HighlightStyle, TextStyle}, geometry::vector::{vec2f, Vector2F}, impl_actions, impl_internal_actions, - keymap::Binding, platform::CursorStyle, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, @@ -81,7 +80,7 @@ pub struct Scroll(pub Vector2F); #[derive(Clone)] pub struct Select(pub SelectPhase); -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct Input(pub String); #[derive(Clone, Deserialize)] @@ -97,13 +96,22 @@ pub struct SelectToEndOfLine { } #[derive(Clone, Deserialize)] -pub struct ToggleCodeActions(#[serde(default)] pub bool); +pub struct ToggleCodeActions { + #[serde(default)] + pub deployed_from_indicator: bool, +} -#[derive(Clone, Deserialize)] -pub struct ConfirmCompletion(#[serde(default)] pub Option); +#[derive(Clone, Default, Deserialize)] +pub struct ConfirmCompletion { + #[serde(default)] + pub item_ix: Option, +} -#[derive(Clone, Deserialize)] -pub struct ConfirmCodeAction(#[serde(default)] pub Option); +#[derive(Clone, Default, Deserialize)] +pub struct ConfirmCodeAction { + #[serde(default)] + pub item_ix: Option, +} actions!( editor, @@ -185,6 +193,7 @@ actions!( impl_actions!( editor, [ + Input, SelectNext, SelectToBeginningOfLine, SelectToEndOfLine, @@ -194,7 +203,7 @@ impl_actions!( ] ); -impl_internal_actions!(editor, [Scroll, Select, Input]); +impl_internal_actions!(editor, [Scroll, Select]); enum DocumentHighlightRead {} enum DocumentHighlightWrite {} @@ -206,187 +215,6 @@ pub enum Direction { } pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings(vec![ - Binding::new("escape", Cancel, Some("Editor")), - Binding::new("backspace", Backspace, Some("Editor")), - Binding::new("ctrl-h", Backspace, Some("Editor")), - Binding::new("delete", Delete, Some("Editor")), - Binding::new("ctrl-d", Delete, Some("Editor")), - Binding::new("enter", Newline, Some("Editor && mode == full")), - Binding::new( - "alt-enter", - Input("\n".into()), - Some("Editor && mode == auto_height"), - ), - Binding::new( - "enter", - ConfirmCompletion(None), - Some("Editor && showing_completions"), - ), - Binding::new( - "enter", - ConfirmCodeAction(None), - Some("Editor && showing_code_actions"), - ), - Binding::new("enter", ConfirmRename, Some("Editor && renaming")), - Binding::new("tab", Tab, Some("Editor")), - Binding::new("shift-tab", TabPrev, Some("Editor")), - Binding::new( - "tab", - ConfirmCompletion(None), - Some("Editor && showing_completions"), - ), - Binding::new("cmd-[", Outdent, Some("Editor")), - Binding::new("cmd-]", Indent, Some("Editor")), - Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")), - Binding::new("alt-backspace", DeleteToPreviousWordStart, Some("Editor")), - Binding::new("alt-h", DeleteToPreviousWordStart, Some("Editor")), - Binding::new( - "ctrl-alt-backspace", - DeleteToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new("ctrl-alt-h", DeleteToPreviousSubwordStart, Some("Editor")), - Binding::new("alt-delete", DeleteToNextWordEnd, Some("Editor")), - Binding::new("alt-d", DeleteToNextWordEnd, Some("Editor")), - Binding::new("ctrl-alt-delete", DeleteToNextSubwordEnd, Some("Editor")), - Binding::new("ctrl-alt-d", DeleteToNextSubwordEnd, Some("Editor")), - Binding::new("cmd-backspace", DeleteToBeginningOfLine, Some("Editor")), - Binding::new("cmd-delete", DeleteToEndOfLine, Some("Editor")), - Binding::new("ctrl-k", CutToEndOfLine, Some("Editor")), - Binding::new("cmd-shift-D", DuplicateLine, Some("Editor")), - Binding::new("ctrl-cmd-up", MoveLineUp, Some("Editor")), - Binding::new("ctrl-cmd-down", MoveLineDown, Some("Editor")), - Binding::new("cmd-x", Cut, Some("Editor")), - Binding::new("cmd-c", Copy, Some("Editor")), - Binding::new("cmd-v", Paste, Some("Editor")), - Binding::new("cmd-z", Undo, Some("Editor")), - Binding::new("cmd-shift-Z", Redo, Some("Editor")), - Binding::new("up", MoveUp, Some("Editor")), - Binding::new("down", MoveDown, Some("Editor")), - Binding::new("left", MoveLeft, Some("Editor")), - Binding::new("right", MoveRight, Some("Editor")), - Binding::new("ctrl-p", MoveUp, Some("Editor")), - Binding::new("ctrl-n", MoveDown, Some("Editor")), - Binding::new("ctrl-b", MoveLeft, Some("Editor")), - Binding::new("ctrl-f", MoveRight, Some("Editor")), - Binding::new("alt-left", MoveToPreviousWordStart, Some("Editor")), - Binding::new("alt-b", MoveToPreviousWordStart, Some("Editor")), - Binding::new("ctrl-alt-left", MoveToPreviousSubwordStart, Some("Editor")), - Binding::new("ctrl-alt-b", MoveToPreviousSubwordStart, Some("Editor")), - Binding::new("alt-right", MoveToNextWordEnd, Some("Editor")), - Binding::new("alt-f", MoveToNextWordEnd, Some("Editor")), - Binding::new("ctrl-alt-right", MoveToNextSubwordEnd, Some("Editor")), - Binding::new("ctrl-alt-f", MoveToNextSubwordEnd, Some("Editor")), - Binding::new("cmd-left", MoveToBeginningOfLine, Some("Editor")), - Binding::new("ctrl-a", MoveToBeginningOfLine, Some("Editor")), - Binding::new("cmd-right", MoveToEndOfLine, Some("Editor")), - Binding::new("ctrl-e", MoveToEndOfLine, Some("Editor")), - Binding::new("cmd-up", MoveToBeginning, Some("Editor")), - Binding::new("cmd-down", MoveToEnd, Some("Editor")), - Binding::new("shift-up", SelectUp, Some("Editor")), - Binding::new("ctrl-shift-P", SelectUp, Some("Editor")), - Binding::new("shift-down", SelectDown, Some("Editor")), - Binding::new("ctrl-shift-N", SelectDown, Some("Editor")), - Binding::new("shift-left", SelectLeft, Some("Editor")), - Binding::new("ctrl-shift-B", SelectLeft, Some("Editor")), - Binding::new("shift-right", SelectRight, Some("Editor")), - Binding::new("ctrl-shift-F", SelectRight, Some("Editor")), - Binding::new("alt-shift-left", SelectToPreviousWordStart, Some("Editor")), - Binding::new("alt-shift-B", SelectToPreviousWordStart, Some("Editor")), - Binding::new( - "ctrl-alt-shift-left", - SelectToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new( - "ctrl-alt-shift-B", - SelectToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new("alt-shift-right", SelectToNextWordEnd, Some("Editor")), - Binding::new("alt-shift-F", SelectToNextWordEnd, Some("Editor")), - Binding::new( - "cmd-shift-left", - SelectToBeginningOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "ctrl-alt-shift-right", - SelectToNextSubwordEnd, - Some("Editor"), - ), - Binding::new("ctrl-alt-shift-F", SelectToNextSubwordEnd, Some("Editor")), - Binding::new( - "ctrl-shift-A", - SelectToBeginningOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "cmd-shift-right", - SelectToEndOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "ctrl-shift-E", - SelectToEndOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")), - Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")), - Binding::new("cmd-a", SelectAll, Some("Editor")), - Binding::new("cmd-l", SelectLine, Some("Editor")), - Binding::new("cmd-shift-L", SplitSelectionIntoLines, Some("Editor")), - Binding::new("cmd-alt-up", AddSelectionAbove, Some("Editor")), - Binding::new("cmd-ctrl-p", AddSelectionAbove, Some("Editor")), - Binding::new("cmd-alt-down", AddSelectionBelow, Some("Editor")), - Binding::new("cmd-ctrl-n", AddSelectionBelow, Some("Editor")), - Binding::new( - "cmd-d", - SelectNext { - replace_newest: false, - }, - Some("Editor"), - ), - Binding::new( - "cmd-k cmd-d", - SelectNext { - replace_newest: true, - }, - Some("Editor"), - ), - Binding::new("cmd-/", ToggleComments, Some("Editor")), - Binding::new("alt-up", SelectLargerSyntaxNode, Some("Editor")), - Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")), - Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")), - Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")), - Binding::new("cmd-u", UndoSelection, Some("Editor")), - Binding::new("cmd-shift-U", RedoSelection, Some("Editor")), - Binding::new("f8", GoToNextDiagnostic, Some("Editor")), - Binding::new("shift-f8", GoToPrevDiagnostic, Some("Editor")), - Binding::new("f2", Rename, Some("Editor")), - Binding::new("f12", GoToDefinition, Some("Editor")), - Binding::new("alt-shift-f12", FindAllReferences, Some("Editor")), - Binding::new("ctrl-m", MoveToEnclosingBracket, Some("Editor")), - Binding::new("pageup", PageUp, Some("Editor")), - Binding::new("pagedown", PageDown, Some("Editor")), - Binding::new("alt-cmd-[", Fold, Some("Editor")), - Binding::new("alt-cmd-]", UnfoldLines, Some("Editor")), - Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")), - Binding::new("ctrl-space", ShowCompletions, Some("Editor")), - Binding::new("cmd-.", ToggleCodeActions(false), Some("Editor")), - Binding::new("alt-enter", OpenExcerpts, Some("Editor")), - Binding::new("cmd-f10", RestartLanguageServer, Some("Editor")), - ]); - cx.add_action(Editor::open_new); cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx)); cx.add_action(Editor::select); @@ -396,6 +224,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Editor::backspace); cx.add_action(Editor::delete); cx.add_action(Editor::tab); + cx.add_action(Editor::tab_prev); cx.add_action(Editor::indent); cx.add_action(Editor::outdent); cx.add_action(Editor::delete_line); @@ -849,7 +678,9 @@ impl CompletionsMenu { ) .with_cursor_style(CursorStyle::PointingHand) .on_mouse_down(move |cx| { - cx.dispatch_action(ConfirmCompletion(Some(item_ix))); + cx.dispatch_action(ConfirmCompletion { + item_ix: Some(item_ix), + }); }) .boxed(), ); @@ -975,7 +806,9 @@ impl CodeActionsMenu { }) .with_cursor_style(CursorStyle::PointingHand) .on_mouse_down(move |cx| { - cx.dispatch_action(ConfirmCodeAction(Some(item_ix))); + cx.dispatch_action(ConfirmCodeAction { + item_ix: Some(item_ix), + }); }) .boxed(), ); @@ -2473,7 +2306,7 @@ impl Editor { pub fn confirm_completion( &mut self, - ConfirmCompletion(completion_ix): &ConfirmCompletion, + action: &ConfirmCompletion, cx: &mut ViewContext, ) -> Option>> { use language::ToOffset as _; @@ -2486,7 +2319,7 @@ impl Editor { let mat = completions_menu .matches - .get(completion_ix.unwrap_or(completions_menu.selected_item))?; + .get(action.item_ix.unwrap_or(completions_menu.selected_item))?; let buffer_handle = completions_menu.buffer; let completion = completions_menu.completions.get(mat.candidate_id)?; @@ -2576,11 +2409,7 @@ impl Editor { })) } - pub fn toggle_code_actions( - &mut self, - &ToggleCodeActions(deployed_from_indicator): &ToggleCodeActions, - cx: &mut ViewContext, - ) { + pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext) { if matches!( self.context_menu.as_ref(), Some(ContextMenu::CodeActions(_)) @@ -2590,6 +2419,7 @@ impl Editor { return; } + let deployed_from_indicator = action.deployed_from_indicator; let mut task = self.code_actions_task.take(); cx.spawn_weak(|this, mut cx| async move { while let Some(prev_task) = task { @@ -2624,7 +2454,7 @@ impl Editor { pub fn confirm_code_action( workspace: &mut Workspace, - ConfirmCodeAction(action_ix): &ConfirmCodeAction, + action: &ConfirmCodeAction, cx: &mut ViewContext, ) -> Option>> { let editor = workspace.active_item(cx)?.act_as::(cx)?; @@ -2635,7 +2465,7 @@ impl Editor { } else { return None; }; - let action_ix = action_ix.unwrap_or(actions_menu.selected_item); + let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item); let action = actions_menu.actions.get(action_ix)?.clone(); let title = action.lsp_action.title.clone(); let buffer = actions_menu.buffer; @@ -2862,7 +2692,9 @@ impl Editor { .with_cursor_style(CursorStyle::PointingHand) .with_padding(Padding::uniform(3.)) .on_mouse_down(|cx| { - cx.dispatch_action(ToggleCodeActions(true)); + cx.dispatch_action(ToggleCodeActions { + deployed_from_indicator: true, + }); }) .boxed(), ) @@ -4558,7 +4390,7 @@ impl Editor { self.go_to_diagnostic(Direction::Next, cx) } - fn go_to_prev_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext) { + fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext) { self.go_to_diagnostic(Direction::Prev, cx) } @@ -9394,7 +9226,7 @@ mod tests { let apply_additional_edits = editor.update(cx, |editor, cx| { editor.move_down(&MoveDown, cx); let apply_additional_edits = editor - .confirm_completion(&ConfirmCompletion(None), cx) + .confirm_completion(&ConfirmCompletion::default(), cx) .unwrap(); assert_eq!( editor.text(cx), @@ -9477,7 +9309,7 @@ mod tests { let apply_additional_edits = editor.update(cx, |editor, cx| { let apply_additional_edits = editor - .confirm_completion(&ConfirmCompletion(None), cx) + .confirm_completion(&ConfirmCompletion::default(), cx) .unwrap(); assert_eq!( editor.text(cx), diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index f7417f6663..962343a28a 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -10,7 +10,7 @@ use crate::{ AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache, }; pub use action::*; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use collections::btree_map; use keymap::MatchResult; use lazy_static::lazy_static; @@ -870,6 +870,7 @@ impl MutableAppContext { .get(name) .ok_or_else(|| anyhow!("unknown action {}", name))?; callback(argument.unwrap_or("{}")) + .with_context(|| format!("invalid data for action {}", name)) } pub fn add_action(&mut self, handler: F) diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index a94abb8252..1b9e920ff2 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -1,5 +1,5 @@ use crate::Action; -use anyhow::anyhow; +use anyhow::{anyhow, Result}; use std::{ any::Any, collections::{HashMap, HashSet}, @@ -168,20 +168,26 @@ impl Keymap { impl Binding { pub fn new(keystrokes: &str, action: A, context: Option<&str>) -> Self { + Self::load(keystrokes, Box::new(action), context).unwrap() + } + + pub fn load(keystrokes: &str, action: Box, context: Option<&str>) -> Result { let context = if let Some(context) = context { - Some(ContextPredicate::parse(context).unwrap()) + Some(ContextPredicate::parse(context)?) } else { None }; - Self { - keystrokes: keystrokes - .split_whitespace() - .map(|key| Keystroke::parse(key).unwrap()) - .collect(), - action: Box::new(action), + let keystrokes = keystrokes + .split_whitespace() + .map(|key| Keystroke::parse(key)) + .collect::>()?; + + Ok(Self { + keystrokes, + action, context, - } + }) } } diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 5ebe36e824..fa7afa5b2f 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -2419,7 +2419,7 @@ mod tests { .condition(&cx_b, |editor, _| editor.context_menu_visible()) .await; editor_b.update(cx_b, |editor, cx| { - editor.confirm_completion(&ConfirmCompletion(Some(0)), cx); + editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx); assert_eq!(editor.text(cx), "fn main() { a.first_method() }"); }); @@ -3608,7 +3608,12 @@ mod tests { // Toggle code actions and wait for them to display. editor_b.update(cx_b, |editor, cx| { - editor.toggle_code_actions(&ToggleCodeActions(false), cx); + editor.toggle_code_actions( + &ToggleCodeActions { + deployed_from_indicator: false, + }, + cx, + ); }); editor_b .condition(&cx_b, |editor, _| editor.context_menu_visible()) @@ -3619,7 +3624,7 @@ mod tests { // Confirming the code action will trigger a resolve request. let confirm_action = workspace_b .update(cx_b, |workspace, cx| { - Editor::confirm_code_action(workspace, &ConfirmCodeAction(Some(0)), cx) + Editor::confirm_code_action(workspace, &ConfirmCodeAction { item_ix: Some(0) }, cx) }) .unwrap(); fake_language_server.handle_request::( diff --git a/crates/workspace/src/menu.rs b/crates/workspace/src/menu.rs index e2412db741..33de4a677a 100644 --- a/crates/workspace/src/menu.rs +++ b/crates/workspace/src/menu.rs @@ -1,18 +1,4 @@ -use gpui::{actions, keymap::Binding, MutableAppContext}; - -actions!( +gpui::actions!( menu, - [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast,] + [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast] ); - -pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("up", SelectPrev, Some("menu")), - Binding::new("ctrl-p", SelectPrev, Some("menu")), - Binding::new("down", SelectNext, Some("menu")), - Binding::new("ctrl-n", SelectNext, Some("menu")), - Binding::new("cmd-up", SelectFirst, Some("menu")), - Binding::new("cmd-down", SelectLast, Some("menu")), - Binding::new("enter", Confirm, Some("menu")), - ]); -} diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a60e2ff9db..a992897c11 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -8,7 +8,6 @@ use gpui::{ elements::*, geometry::{rect::RectF, vector::vec2f}, impl_actions, impl_internal_actions, - keymap::Binding, platform::{CursorStyle, NavigationDirection}, AppContext, Entity, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -41,14 +40,20 @@ pub struct CloseItem { #[derive(Clone, Deserialize)] pub struct ActivateItem(pub usize); -#[derive(Clone)] -pub struct GoBack(pub Option>); +#[derive(Clone, Deserialize)] +pub struct GoBack { + #[serde(skip_deserializing)] + pub pane: Option>, +} -#[derive(Clone)] -pub struct GoForward(pub Option>); +#[derive(Clone, Deserialize)] +pub struct GoForward { + #[serde(skip_deserializing)] + pub pane: Option>, +} -impl_actions!(pane, [Split]); -impl_internal_actions!(pane, [CloseItem, ActivateItem, GoBack, GoForward]); +impl_actions!(pane, [Split, GoBack, GoForward]); +impl_internal_actions!(pane, [CloseItem, ActivateItem]); const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; @@ -75,7 +80,7 @@ pub fn init(cx: &mut MutableAppContext) { Pane::go_back( workspace, action - .0 + .pane .as_ref() .and_then(|weak_handle| weak_handle.upgrade(cx)), cx, @@ -86,26 +91,13 @@ pub fn init(cx: &mut MutableAppContext) { Pane::go_forward( workspace, action - .0 + .pane .as_ref() .and_then(|weak_handle| weak_handle.upgrade(cx)), cx, ) .detach(); }); - - cx.add_bindings(vec![ - Binding::new("shift-cmd-{", ActivatePrevItem, Some("Pane")), - Binding::new("shift-cmd-}", ActivateNextItem, Some("Pane")), - Binding::new("cmd-w", CloseActiveItem, Some("Pane")), - Binding::new("alt-cmd-w", CloseInactiveItems, Some("Pane")), - Binding::new("cmd-k up", Split(SplitDirection::Up), Some("Pane")), - Binding::new("cmd-k down", Split(SplitDirection::Down), Some("Pane")), - Binding::new("cmd-k left", Split(SplitDirection::Left), Some("Pane")), - Binding::new("cmd-k right", Split(SplitDirection::Right), Some("Pane")), - Binding::new("ctrl--", GoBack(None), Some("Pane")), - Binding::new("shift-ctrl-_", GoForward(None), Some("Pane")), - ]); } pub enum Event { @@ -815,8 +807,8 @@ impl View for Pane { .on_navigate_mouse_down(move |direction, cx| { let this = this.clone(); match direction { - NavigationDirection::Back => cx.dispatch_action(GoBack(Some(this))), - NavigationDirection::Forward => cx.dispatch_action(GoForward(Some(this))), + NavigationDirection::Back => cx.dispatch_action(GoBack { pane: Some(this) }), + NavigationDirection::Forward => cx.dispatch_action(GoForward { pane: Some(this) }), } true diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index d5661ba2c9..a17805822f 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -256,7 +256,6 @@ impl PaneAxis { } #[derive(Clone, Copy, Debug, Deserialize)] -#[serde(rename_all = "snake_case")] pub enum SplitDirection { Up, Down, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 475913d9db..d63626e1d3 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,6 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, impl_internal_actions, json::{self, to_string_pretty, ToJson}, - keymap::Binding, platform::{CursorStyle, WindowOptions}, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, ClipboardItem, Entity, ImageData, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, @@ -32,7 +31,7 @@ pub use pane_group::*; use postage::prelude::Stream; use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, Worktree}; use settings::Settings; -use sidebar::{Side, Sidebar, SidebarItemId, ToggleSidebarItem, ToggleSidebarItemFocus}; +use sidebar::{Side, Sidebar, ToggleSidebarItem, ToggleSidebarItemFocus}; use status_bar::StatusBar; pub use status_bar::StatusItemView; use std::{ @@ -108,7 +107,6 @@ impl_internal_actions!( pub fn init(client: &Arc, cx: &mut MutableAppContext) { pane::init(cx); - menu::init(cx); cx.add_global_action(open); cx.add_global_action(move |action: &OpenPaths, cx: &mut MutableAppContext| { @@ -144,29 +142,6 @@ pub fn init(client: &Arc, cx: &mut MutableAppContext) { cx.add_action(|workspace: &mut Workspace, _: &ActivateNextPane, cx| { workspace.activate_next_pane(cx) }); - cx.add_bindings(vec![ - Binding::new("ctrl-alt-cmd-f", FollowNextCollaborator, None), - Binding::new("cmd-s", Save, None), - Binding::new("cmd-alt-i", DebugElements, None), - Binding::new("cmd-k cmd-left", ActivatePreviousPane, None), - Binding::new("cmd-k cmd-right", ActivateNextPane, None), - Binding::new( - "cmd-shift-!", - ToggleSidebarItem(SidebarItemId { - side: Side::Left, - item_index: 0, - }), - None, - ), - Binding::new( - "cmd-1", - ToggleSidebarItemFocus(SidebarItemId { - side: Side::Left, - item_index: 0, - }), - None, - ), - ]); client.add_view_request_handler(Workspace::handle_follow); client.add_view_message_handler(Workspace::handle_unfollow); diff --git a/crates/zed/assets/keymaps/default.json b/crates/zed/assets/keymaps/default.json new file mode 100644 index 0000000000..1339a5e54f --- /dev/null +++ b/crates/zed/assets/keymaps/default.json @@ -0,0 +1,199 @@ +{ + "": { + "ctrl-alt-cmd-f": "workspace::FollowNextCollaborator", + "cmd-s": "workspace::Save", + "cmd-alt-i": "workspace::DebugElements", + "cmd-k cmd-left": "workspace::ActivatePreviousPane", + "cmd-k cmd-right": "workspace::ActivateNextPane", + "cmd-=": "zed::IncreaseBufferFontSize", + "cmd--": "zed::DecreaseBufferFontSize", + "cmd-,": "zed::OpenSettings" + }, + "menu": { + "up": "menu::SelectPrev", + "ctrl-p": "menu::SelectPrev", + "down": "menu::SelectNext", + "ctrl-n": "menu::SelectNext", + "cmd-up": "menu::SelectFirst", + "cmd-down": "menu::SelectLast", + "enter": "menu::Confirm" + }, + "Pane": { + "shift-cmd-{": "pane::ActivatePrevItem", + "shift-cmd-}": "pane::ActivateNextItem", + "cmd-w": "pane::CloseActiveItem", + "alt-cmd-w": "pane::CloseInactiveItems", + "ctrl--": "pane::GoBack", + "shift-ctrl-_": "pane::GoForward", + "cmd-k up": [ + "pane::Split", + "Up" + ], + "cmd-k down": [ + "pane::Split", + "Down" + ], + "cmd-k left": [ + "pane::Split", + "Left" + ], + "cmd-k right": [ + "pane::Split", + "Right" + ] + }, + "Editor": { + "escape": "editor::Cancel", + "backspace": "editor::Backspace", + "ctrl-h": "editor::Backspace", + "delete": "editor::Delete", + "ctrl-d": "editor::Delete", + "tab": "editor::Tab", + "shift-tab": "editor::TabPrev", + "cmd-[": "editor::Outdent", + "cmd-]": "editor::Indent", + "ctrl-shift-K": "editor::DeleteLine", + "alt-backspace": "editor::DeleteToPreviousWordStart", + "alt-h": "editor::DeleteToPreviousWordStart", + "ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart", + "ctrl-alt-h": "editor::DeleteToPreviousSubwordStart", + "alt-delete": "editor::DeleteToNextWordEnd", + "alt-d": "editor::DeleteToNextWordEnd", + "ctrl-alt-delete": "editor::DeleteToNextSubwordEnd", + "ctrl-alt-d": "editor::DeleteToNextSubwordEnd", + "cmd-backspace": "editor::DeleteToBeginningOfLine", + "cmd-delete": "editor::DeleteToEndOfLine", + "ctrl-k": "editor::CutToEndOfLine", + "cmd-shift-D": "editor::DuplicateLine", + "ctrl-cmd-up": "editor::MoveLineUp", + "ctrl-cmd-down": "editor::MoveLineDown", + "cmd-x": "editor::Cut", + "cmd-c": "editor::Copy", + "cmd-v": "editor::Paste", + "cmd-z": "editor::Undo", + "cmd-shift-Z": "editor::Redo", + "up": "editor::MoveUp", + "down": "editor::MoveDown", + "left": "editor::MoveLeft", + "right": "editor::MoveRight", + "ctrl-p": "editor::MoveUp", + "ctrl-n": "editor::MoveDown", + "ctrl-b": "editor::MoveLeft", + "ctrl-f": "editor::MoveRight", + "alt-left": "editor::MoveToPreviousWordStart", + "alt-b": "editor::MoveToPreviousWordStart", + "ctrl-alt-left": "editor::MoveToPreviousSubwordStart", + "ctrl-alt-b": "editor::MoveToPreviousSubwordStart", + "alt-right": "editor::MoveToNextWordEnd", + "alt-f": "editor::MoveToNextWordEnd", + "ctrl-alt-right": "editor::MoveToNextSubwordEnd", + "ctrl-alt-f": "editor::MoveToNextSubwordEnd", + "cmd-left": "editor::MoveToBeginningOfLine", + "ctrl-a": "editor::MoveToBeginningOfLine", + "cmd-right": "editor::MoveToEndOfLine", + "ctrl-e": "editor::MoveToEndOfLine", + "cmd-up": "editor::MoveToBeginning", + "cmd-down": "editor::MoveToEnd", + "shift-up": "editor::SelectUp", + "ctrl-shift-P": "editor::SelectUp", + "shift-down": "editor::SelectDown", + "ctrl-shift-N": "editor::SelectDown", + "shift-left": "editor::SelectLeft", + "ctrl-shift-B": "editor::SelectLeft", + "shift-right": "editor::SelectRight", + "ctrl-shift-F": "editor::SelectRight", + "alt-shift-left": "editor::SelectToPreviousWordStart", + "alt-shift-B": "editor::SelectToPreviousWordStart", + "ctrl-alt-shift-left": "editor::SelectToPreviousSubwordStart", + "ctrl-alt-shift-B": "editor::SelectToPreviousSubwordStart", + "alt-shift-right": "editor::SelectToNextWordEnd", + "alt-shift-F": "editor::SelectToNextWordEnd", + "ctrl-alt-shift-right": "editor::SelectToNextSubwordEnd", + "cmd-shift-up": "editor::SelectToBeginning", + "cmd-shift-down": "editor::SelectToEnd", + "cmd-a": "editor::SelectAll", + "cmd-l": "editor::SelectLine", + "cmd-shift-L": "editor::SplitSelectionIntoLines", + "cmd-alt-up": "editor::AddSelectionAbove", + "cmd-ctrl-p": "editor::AddSelectionAbove", + "cmd-alt-down": "editor::AddSelectionBelow", + "cmd-ctrl-n": "editor::AddSelectionBelow", + "ctrl-alt-shift-F": "editor::SelectToNextSubwordEnd", + "cmd-shift-left": [ + "editor::SelectToBeginningOfLine", + { + "stop_at_soft_wraps": true + } + ], + "ctrl-shift-A": [ + "editor::SelectToBeginningOfLine", + { + "stop_at_soft_wraps": true + } + ], + "cmd-shift-right": [ + "editor::SelectToEndOfLine", + { + "stop_at_soft_wraps": true + } + ], + "ctrl-shift-E": [ + "editor::SelectToEndOfLine", + { + "stop_at_soft_wraps": true + } + ], + "cmd-d": [ + "editor::SelectNext", + { + "replace_newest": false + } + ], + "cmd-k cmd-d": [ + "editor::SelectNext", + { + "replace_newest": true + } + ], + "cmd-/": "editor::ToggleComments", + "alt-up": "editor::SelectLargerSyntaxNode", + "ctrl-w": "editor::SelectLargerSyntaxNode", + "alt-down": "editor::SelectSmallerSyntaxNode", + "ctrl-shift-W": "editor::SelectSmallerSyntaxNode", + "cmd-u": "editor::UndoSelection", + "cmd-shift-U": "editor::RedoSelection", + "f8": "editor::GoToNextDiagnostic", + "shift-f8": "editor::GoToPrevDiagnostic", + "f2": "editor::Rename", + "f12": "editor::GoToDefinition", + "alt-shift-f12": "editor::FindAllReferences", + "ctrl-m": "editor::MoveToEnclosingBracket", + "pageup": "editor::PageUp", + "pagedown": "editor::PageDown", + "alt-cmd-[": "editor::Fold", + "alt-cmd-]": "editor::UnfoldLines", + "alt-cmd-f": "editor::FoldSelectedRanges", + "ctrl-space": "editor::ShowCompletions", + "cmd-.": "editor::ToggleCodeActions", + "alt-enter": "editor::OpenExcerpts", + "cmd-f10": "editor::RestartLanguageServer" + }, + "Editor && renaming": { + "enter": "editor::ConfirmRename" + }, + "Editor && showing_completions": { + "enter": "editor::ConfirmCompletion" + }, + "Editor && showing_code_actions": { + "enter": "editor::ConfirmCodeAction" + }, + "Editor && mode == full": { + "enter": "editor::Newline" + }, + "Editor && mode == auto_height": { + "alt-enter": [ + "editor::Input", + "\n" + ] + } +} \ No newline at end of file diff --git a/crates/zed/src/keymap_file.rs b/crates/zed/src/keymap_file.rs new file mode 100644 index 0000000000..2eaf1b7ecb --- /dev/null +++ b/crates/zed/src/keymap_file.rs @@ -0,0 +1,38 @@ +use anyhow::Result; +use collections::BTreeMap; +use gpui::{keymap::Binding, MutableAppContext}; +use serde::Deserialize; +use serde_json::value::RawValue; + +#[derive(Deserialize)] +struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue); +type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>; +type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>; + +pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> { + let actions: ActionSetsByContext = serde_json::from_str(content)?; + for (context, actions) in actions { + let context = if context.is_empty() { + None + } else { + Some(context) + }; + cx.add_bindings( + actions + .into_iter() + .map(|(keystroke, action)| { + let action = action.get(); + let action = if action.starts_with('[') { + let ActionWithData(name, data) = serde_json::from_str(action)?; + cx.deserialize_action(name, Some(data.get())) + } else { + let name = serde_json::from_str(action)?; + cx.deserialize_action(name, None) + }?; + Binding::load(keystroke, action, context) + }) + .collect::>>()?, + ) + } + Ok(()) +} diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index abdf68e6ab..bfb1b34256 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -145,8 +145,8 @@ fn main() { build_workspace: &build_workspace, }); journal::init(app_state.clone(), cx); - zed::init(&app_state, cx); theme_selector::init(cx); + zed::init(&app_state, cx); cx.set_menus(menus::menus(&app_state.clone())); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 6465c9b253..bae7b517e9 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,10 +1,12 @@ pub mod assets; +mod keymap_file; pub mod languages; pub mod menus; pub mod settings_file; #[cfg(any(test, feature = "test-support"))] pub mod test; +use assets::Assets; use breadcrumbs::Breadcrumbs; use chat_panel::ChatPanel; pub use client; @@ -14,7 +16,6 @@ pub use editor; use gpui::{ actions, geometry::vector::vec2f, - keymap::Binding, platform::{WindowBounds, WindowOptions}, ModelHandle, ViewContext, }; @@ -104,11 +105,11 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - cx.add_bindings(vec![ - Binding::new("cmd-=", IncreaseBufferFontSize, None), - Binding::new("cmd--", DecreaseBufferFontSize, None), - Binding::new("cmd-,", OpenSettings, None), - ]) + keymap_file::load_keymap( + cx, + std::str::from_utf8(Assets::get("keymaps/default.json").unwrap().data.as_ref()).unwrap(), + ) + .unwrap(); } pub fn build_workspace( @@ -208,9 +209,8 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { #[cfg(test)] mod tests { - use crate::assets::Assets; - use super::*; + use crate::assets::Assets; use editor::{DisplayPoint, Editor}; use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle}; use project::{Fs, ProjectPath};