From 57df69710b513174ec7f6404b5d88c772013bf71 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 17 Jan 2025 13:55:25 -0700 Subject: [PATCH] Add emacs mark mode Updates #21927 Closes #8580 Co-Authored-By: Peter --- assets/keymaps/macos/emacs.json | 29 +++++++++++++++++++++++- crates/editor/src/actions.rs | 2 ++ crates/editor/src/editor.rs | 40 ++++++++++++++++++++++++++------- crates/editor/src/element.rs | 2 ++ 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/assets/keymaps/macos/emacs.json b/assets/keymaps/macos/emacs.json index 816e20ad787a6..bf3b27ca4c78e 100755 --- a/assets/keymaps/macos/emacs.json +++ b/assets/keymaps/macos/emacs.json @@ -15,7 +15,8 @@ "ctrl-x b": "tab_switcher::Toggle", // switch-to-buffer "alt-g g": "go_to_line::Toggle", // goto-line "alt-g alt-g": "go_to_line::Toggle", // goto-line - //"ctrl-space": "editor::SetMark", + "ctrl-space": "editor::SetMark", // set-mark + "ctrl-x ctrl-x": "editor::ExchangeMark", // exchange-point-and-mark "ctrl-f": "editor::MoveRight", // forward-char "ctrl-b": "editor::MoveLeft", // backward-char "ctrl-n": "editor::MoveDown", // next-line @@ -55,6 +56,32 @@ "alt-^": "editor::JoinLines" // join-line } }, + { + "context": "selection_mode", + "bindings": { + "right": "editor::SelectRight", + "left": "editor::SelectLeft", + "down": "editor::SelectDown", + "up": "editor::SelectUp", + "home": "editor::SelectToBeginningOfLine", + "end": "editor::SelectToEndOfLine", + "alt-left": "editor::SelectToPreviousWordStart", + "alt-right": "editor::SelectToNextWordEnd", + "pagedown": "editor::SelectPageDown", + "pageup": "editor::SelectPageUp", + "ctrl-f": "editor::SelectRight", + "ctrl-b": "editor::SelectLeft", + "ctrl-n": "editor::SelectDown", + "ctrl-p": "editor::SelectUp", + "ctrl-a": "editor::SelectToBeginningOfLine", + "ctrl-e": "editor::SelectToEndOfLine", + "alt-f": "editor::SelectToNextWordEnd", + "alt-b": "editor::SelectToPreviousSubwordStart", + "alt-<": "editor::SelectToBeginning", + "alt->": "editor::SelectToEnd", + "ctrl-g": "editor::Cancel" + } + }, { "context": "Workspace", "bindings": { diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index 97a4aefa0e0cb..e728a72dce36d 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -377,6 +377,8 @@ gpui::actions!( ToggleInlayHints, ToggleInlineCompletions, ToggleLineNumbers, + ExchangeMark, + SetMark, ToggleRelativeLineNumbers, ToggleSelectionMenu, ToggleSoftWrap, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1212084b067c5..10a89d3a4c41c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -703,6 +703,7 @@ pub struct Editor { next_scroll_position: NextScrollCursorCenterTopBottom, addons: HashMap>, registered_buffers: HashMap, + selection_mark_mode: bool, toggle_fold_multiple_buffers: Task<()>, _scroll_cursor_center_top_bottom_task: Task<()>, } @@ -1361,6 +1362,7 @@ impl Editor { addons: HashMap::default(), registered_buffers: HashMap::default(), _scroll_cursor_center_top_bottom_task: Task::ready(()), + selection_mark_mode: false, toggle_fold_multiple_buffers: Task::ready(()), text_style_refinement: None, }; @@ -1453,13 +1455,8 @@ impl Editor { key_context.add("inline_completion"); } - if !self - .selections - .disjoint - .iter() - .all(|selection| selection.start == selection.end) - { - key_context.add("selection"); + if self.selection_mark_mode { + key_context.add("selection_mode"); } key_context @@ -2474,6 +2471,8 @@ impl Editor { } pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { + self.selection_mark_mode = false; + if self.clear_expanded_diff_hunks(cx) { cx.notify(); return; @@ -10586,6 +10585,32 @@ impl Editor { } } + pub fn set_mark(&mut self, _: &actions::SetMark, cx: &mut ViewContext) { + if self.selection_mark_mode { + self.change_selections(None, cx, |s| { + s.move_with(|_, sel| { + sel.collapse_to(sel.head(), SelectionGoal::None); + }); + }) + } + self.selection_mark_mode = true; + cx.notify(); + } + + pub fn exchange_mark(&mut self, _: &actions::ExchangeMark, cx: &mut ViewContext) { + if self.selection_mark_mode { + self.change_selections(None, cx, |s| { + s.move_with(|_, sel| { + if sel.start != sel.end { + sel.reversed = !sel.reversed + } + }); + }) + } + self.selection_mark_mode = true; + cx.notify(); + } + pub fn toggle_fold(&mut self, _: &actions::ToggleFold, cx: &mut ViewContext) { if self.is_singleton(cx) { let selection = self.selections.newest::(cx); @@ -15198,7 +15223,6 @@ fn check_multiline_range(buffer: &Buffer, range: Range) -> Range { range.start..range.start } } - pub struct KillRing(ClipboardItem); impl Global for KillRing {} diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index bcb7740497802..cb00fd92ba144 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -356,6 +356,8 @@ impl EditorElement { register_action(view, cx, Editor::unfold_all); register_action(view, cx, Editor::unfold_at); register_action(view, cx, Editor::fold_selected_ranges); + register_action(view, cx, Editor::set_mark); + register_action(view, cx, Editor::exchange_mark); register_action(view, cx, Editor::show_completions); register_action(view, cx, Editor::toggle_code_actions); register_action(view, cx, Editor::open_excerpts);