Skip to content

Commit

Permalink
Add emacs mark mode (#23297)
Browse files Browse the repository at this point in the history
Updates #21927
Replaces #22904
Closes #8580

Adds actions (default keybinds with emacs keymap):
- editor::SetMark (`ctrl-space` and `ctrl-@`)
- editor::ExchangeMark (`ctrl-x ctrl-x`)

Co-Authored-By: Peter <[email protected]>

Release Notes:

- Add Emacs mark mode (`ctrl-space` / `ctrl-@` to set mark; `ctrl-x
ctrl-x` to swap mark/cursor)
- Breaking change: `selection` keyboard context has been replaced with
`selection_mode`

---------

Co-authored-by: Peter <[email protected]>
  • Loading branch information
ConradIrwin and notpeter authored Jan 21, 2025
1 parent c4542ca commit 94189e1
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 10 deletions.
32 changes: 31 additions & 1 deletion assets/keymaps/linux/emacs.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"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-@": "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
Expand All @@ -24,6 +26,8 @@
"end": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"ctrl-a": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
"ctrl-e": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"alt-f": "editor::MoveToNextSubwordEnd", // forward-word
"alt-b": "editor::MoveToPreviousSubwordStart", // backward-word
"alt-u": "editor::ConvertToUpperCase", // upcase-word
Expand Down Expand Up @@ -55,6 +59,32 @@
"alt-^": "editor::JoinLines" // join-line
}
},
{
"context": "Editor && selection_mode", // region selection
"bindings": {
"right": "editor::SelectRight",
"left": "editor::SelectLeft",
"down": "editor::SelectDown",
"up": "editor::SelectUp",
"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",
"home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }],
"end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }],
"ctrl-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }],
"ctrl-e": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }],
"alt-f": "editor::SelectToNextWordEnd",
"alt-b": "editor::SelectToPreviousSubwordStart",
"alt-<": "editor::SelectToBeginning",
"alt->": "editor::SelectToEnd",
"ctrl-g": "editor::Cancel"
}
},
{
"context": "Workspace",
"bindings": {
Expand Down
32 changes: 31 additions & 1 deletion assets/keymaps/macos/emacs.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"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-@": "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
Expand All @@ -24,6 +26,8 @@
"end": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"ctrl-a": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
"ctrl-e": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
"alt-f": "editor::MoveToNextSubwordEnd", // forward-word
"alt-b": "editor::MoveToPreviousSubwordStart", // backward-word
"alt-u": "editor::ConvertToUpperCase", // upcase-word
Expand Down Expand Up @@ -55,6 +59,32 @@
"alt-^": "editor::JoinLines" // join-line
}
},
{
"context": "Editor && selection_mode", // region selection
"bindings": {
"right": "editor::SelectRight",
"left": "editor::SelectLeft",
"down": "editor::SelectDown",
"up": "editor::SelectUp",
"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",
"home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }],
"end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }],
"ctrl-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }],
"ctrl-e": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }],
"alt-f": "editor::SelectToNextWordEnd",
"alt-b": "editor::SelectToPreviousSubwordStart",
"alt-<": "editor::SelectToBeginning",
"alt->": "editor::SelectToEnd",
"ctrl-g": "editor::Cancel"
}
},
{
"context": "Workspace",
"bindings": {
Expand Down
2 changes: 2 additions & 0 deletions crates/editor/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ gpui::actions!(
ToggleInlayHints,
ToggleInlineCompletions,
ToggleLineNumbers,
ExchangeMark,
SetMark,
ToggleRelativeLineNumbers,
ToggleSelectionMenu,
ToggleSoftWrap,
Expand Down
40 changes: 32 additions & 8 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ pub struct Editor {
next_scroll_position: NextScrollCursorCenterTopBottom,
addons: HashMap<TypeId, Box<dyn Addon>>,
registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
selection_mark_mode: bool,
toggle_fold_multiple_buffers: Task<()>,
_scroll_cursor_center_top_bottom_task: Task<()>,
}
Expand Down Expand Up @@ -1364,6 +1365,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,
};
Expand Down Expand Up @@ -1456,13 +1458,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
Expand Down Expand Up @@ -2477,6 +2474,8 @@ impl Editor {
}

pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
self.selection_mark_mode = false;

if self.clear_expanded_diff_hunks(cx) {
cx.notify();
return;
Expand Down Expand Up @@ -10622,6 +10621,32 @@ impl Editor {
}
}

pub fn set_mark(&mut self, _: &actions::SetMark, cx: &mut ViewContext<Self>) {
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<Self>) {
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<Self>) {
if self.is_singleton(cx) {
let selection = self.selections.newest::<Point>(cx);
Expand Down Expand Up @@ -15234,7 +15259,6 @@ fn check_multiline_range(buffer: &Buffer, range: Range<usize>) -> Range<usize> {
range.start..range.start
}
}

pub struct KillRing(ClipboardItem);
impl Global for KillRing {}

Expand Down
2 changes: 2 additions & 0 deletions crates/editor/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 94189e1

Please sign in to comment.