Add emacs mark mode (#23297)
Updates #21927 Replaces https://github.com/zed-industries/zed/pull/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 <peter@zed.dev> 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 <peter@zed.dev>
This commit is contained in:
parent
c4542ca731
commit
94189e1784
5 changed files with 98 additions and 10 deletions
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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": {
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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": {
|
||||
|
|
|
@ -377,6 +377,8 @@ gpui::actions!(
|
|||
ToggleInlayHints,
|
||||
ToggleInlineCompletions,
|
||||
ToggleLineNumbers,
|
||||
ExchangeMark,
|
||||
SetMark,
|
||||
ToggleRelativeLineNumbers,
|
||||
ToggleSelectionMenu,
|
||||
ToggleSoftWrap,
|
||||
|
|
|
@ -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<()>,
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue