Add option to either use system clipboard or vim clipboard (#7936)
Release Notes: - vim: Added a setting to control default clipboard behaviour. `{"vim": {"use_system_clipboard": "never"}}` disables writing to the clipboard. `"on_yank"` writes to the system clipboard only on yank, and `"always"` preserves the current behavior. ([#4390 ](https://github.com/zed-industries/zed/issues/4390)) --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
c6826a61a0
commit
5c4f3c0cea
18 changed files with 453 additions and 116 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -10903,6 +10903,7 @@ dependencies = [
|
|||
"project",
|
||||
"regex",
|
||||
"release_channel",
|
||||
"schemars",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
|
|
@ -101,8 +101,14 @@
|
|||
"ctrl-o": "pane::GoBack",
|
||||
"ctrl-i": "pane::GoForward",
|
||||
"ctrl-]": "editor::GoToDefinition",
|
||||
"escape": ["vim::SwitchMode", "Normal"],
|
||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
||||
"escape": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
"ctrl-[": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
"v": "vim::ToggleVisual",
|
||||
"shift-v": "vim::ToggleVisualLine",
|
||||
"ctrl-v": "vim::ToggleVisualBlock",
|
||||
|
@ -235,36 +241,123 @@
|
|||
}
|
||||
],
|
||||
// Count support
|
||||
"1": ["vim::Number", 1],
|
||||
"2": ["vim::Number", 2],
|
||||
"3": ["vim::Number", 3],
|
||||
"4": ["vim::Number", 4],
|
||||
"5": ["vim::Number", 5],
|
||||
"6": ["vim::Number", 6],
|
||||
"7": ["vim::Number", 7],
|
||||
"8": ["vim::Number", 8],
|
||||
"9": ["vim::Number", 9],
|
||||
"1": [
|
||||
"vim::Number",
|
||||
1
|
||||
],
|
||||
"2": [
|
||||
"vim::Number",
|
||||
2
|
||||
],
|
||||
"3": [
|
||||
"vim::Number",
|
||||
3
|
||||
],
|
||||
"4": [
|
||||
"vim::Number",
|
||||
4
|
||||
],
|
||||
"5": [
|
||||
"vim::Number",
|
||||
5
|
||||
],
|
||||
"6": [
|
||||
"vim::Number",
|
||||
6
|
||||
],
|
||||
"7": [
|
||||
"vim::Number",
|
||||
7
|
||||
],
|
||||
"8": [
|
||||
"vim::Number",
|
||||
8
|
||||
],
|
||||
"9": [
|
||||
"vim::Number",
|
||||
9
|
||||
],
|
||||
// window related commands (ctrl-w X)
|
||||
"ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
|
||||
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
|
||||
"ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
|
||||
"ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
||||
"ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
||||
"ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
||||
"ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
||||
"ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
|
||||
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
|
||||
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
|
||||
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
|
||||
"ctrl-w left": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Left"
|
||||
],
|
||||
"ctrl-w right": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Right"
|
||||
],
|
||||
"ctrl-w up": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w down": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Down"
|
||||
],
|
||||
"ctrl-w h": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Left"
|
||||
],
|
||||
"ctrl-w l": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Right"
|
||||
],
|
||||
"ctrl-w k": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w j": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Down"
|
||||
],
|
||||
"ctrl-w ctrl-h": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Left"
|
||||
],
|
||||
"ctrl-w ctrl-l": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Right"
|
||||
],
|
||||
"ctrl-w ctrl-k": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w ctrl-j": [
|
||||
"workspace::ActivatePaneInDirection",
|
||||
"Down"
|
||||
],
|
||||
"ctrl-w shift-left": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Left"
|
||||
],
|
||||
"ctrl-w shift-right": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Right"
|
||||
],
|
||||
"ctrl-w shift-up": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w shift-down": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Down"
|
||||
],
|
||||
"ctrl-w shift-h": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Left"
|
||||
],
|
||||
"ctrl-w shift-l": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Right"
|
||||
],
|
||||
"ctrl-w shift-k": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w shift-j": [
|
||||
"workspace::SwapPaneInDirection",
|
||||
"Down"
|
||||
],
|
||||
"ctrl-w g t": "pane::ActivateNextItem",
|
||||
"ctrl-w ctrl-g t": "pane::ActivateNextItem",
|
||||
"ctrl-w g shift-t": "pane::ActivatePrevItem",
|
||||
|
@ -286,8 +379,14 @@
|
|||
"ctrl-w ctrl-q": "pane::CloseAllItems",
|
||||
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-w n": ["workspace::NewFileInDirection", "Up"],
|
||||
"ctrl-w ctrl-n": ["workspace::NewFileInDirection", "Up"],
|
||||
"ctrl-w n": [
|
||||
"workspace::NewFileInDirection",
|
||||
"Up"
|
||||
],
|
||||
"ctrl-w ctrl-n": [
|
||||
"workspace::NewFileInDirection",
|
||||
"Up"
|
||||
],
|
||||
"-": "pane::RevealInProjectPanel"
|
||||
}
|
||||
},
|
||||
|
@ -303,12 +402,21 @@
|
|||
"context": "Editor && vim_mode == normal && vim_operator == none && !VimWaiting",
|
||||
"bindings": {
|
||||
".": "vim::Repeat",
|
||||
"c": ["vim::PushOperator", "Change"],
|
||||
"c": [
|
||||
"vim::PushOperator",
|
||||
"Change"
|
||||
],
|
||||
"shift-c": "vim::ChangeToEndOfLine",
|
||||
"d": ["vim::PushOperator", "Delete"],
|
||||
"d": [
|
||||
"vim::PushOperator",
|
||||
"Delete"
|
||||
],
|
||||
"shift-d": "vim::DeleteToEndOfLine",
|
||||
"shift-j": "vim::JoinLines",
|
||||
"y": ["vim::PushOperator", "Yank"],
|
||||
"y": [
|
||||
"vim::PushOperator",
|
||||
"Yank"
|
||||
],
|
||||
"shift-y": "vim::YankLine",
|
||||
"i": "vim::InsertBefore",
|
||||
"shift-i": "vim::InsertFirstNonWhitespace",
|
||||
|
@ -339,7 +447,10 @@
|
|||
],
|
||||
"*": "vim::MoveToNext",
|
||||
"#": "vim::MoveToPrev",
|
||||
"r": ["vim::PushOperator", "Replace"],
|
||||
"r": [
|
||||
"vim::PushOperator",
|
||||
"Replace"
|
||||
],
|
||||
"s": "vim::Substitute",
|
||||
"shift-s": "vim::SubstituteLine",
|
||||
"> >": "editor::Indent",
|
||||
|
@ -351,7 +462,10 @@
|
|||
{
|
||||
"context": "Editor && VimCount",
|
||||
"bindings": {
|
||||
"0": ["vim::Number", 0]
|
||||
"0": [
|
||||
"vim::Number",
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -454,10 +568,22 @@
|
|||
"shift-i": "vim::InsertBefore",
|
||||
"shift-a": "vim::InsertAfter",
|
||||
"shift-j": "vim::JoinLines",
|
||||
"r": ["vim::PushOperator", "Replace"],
|
||||
"ctrl-c": ["vim::SwitchMode", "Normal"],
|
||||
"escape": ["vim::SwitchMode", "Normal"],
|
||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
||||
"r": [
|
||||
"vim::PushOperator",
|
||||
"Replace"
|
||||
],
|
||||
"ctrl-c": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
"escape": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
"ctrl-[": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
">": "editor::Indent",
|
||||
"<": "editor::Outdent",
|
||||
"i": [
|
||||
|
@ -498,8 +624,14 @@
|
|||
"bindings": {
|
||||
"tab": "vim::Tab",
|
||||
"enter": "vim::Enter",
|
||||
"escape": ["vim::SwitchMode", "Normal"],
|
||||
"ctrl-[": ["vim::SwitchMode", "Normal"]
|
||||
"escape": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
],
|
||||
"ctrl-[": [
|
||||
"vim::SwitchMode",
|
||||
"Normal"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -331,7 +331,9 @@
|
|||
"copilot": {
|
||||
// The set of glob patterns for which copilot should be disabled
|
||||
// in any matching file.
|
||||
"disabled_globs": [".env"]
|
||||
"disabled_globs": [
|
||||
".env"
|
||||
]
|
||||
},
|
||||
// Settings specific to journaling
|
||||
"journal": {
|
||||
|
@ -440,7 +442,12 @@
|
|||
// Default directories to search for virtual environments, relative
|
||||
// to the current working directory. We recommend overriding this
|
||||
// in your project's settings, rather than globally.
|
||||
"directories": [".env", "env", ".venv", "venv"],
|
||||
"directories": [
|
||||
".env",
|
||||
"env",
|
||||
".venv",
|
||||
"venv"
|
||||
],
|
||||
// Can also be 'csh', 'fish', and `nushell`
|
||||
"activate_script": "default"
|
||||
}
|
||||
|
@ -555,6 +562,10 @@
|
|||
// }
|
||||
// }
|
||||
},
|
||||
// Vim settings
|
||||
"vim": {
|
||||
"use_system_clipboard": "always"
|
||||
},
|
||||
// The server to connect to. If the environment variable
|
||||
// ZED_SERVER_URL is set, it will override this setting.
|
||||
"server_url": "https://zed.dev",
|
||||
|
|
|
@ -39,6 +39,7 @@ tokio = { version = "1.15", "optional" = true }
|
|||
ui.workspace = true
|
||||
workspace.workspace = true
|
||||
zed_actions.workspace = true
|
||||
schemars.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
|
|
|
@ -15,7 +15,7 @@ fn normal_before(_: &mut Workspace, action: &NormalBefore, cx: &mut ViewContext<
|
|||
let count = vim.take_count(cx).unwrap_or(1);
|
||||
vim.stop_recording_immediately(action.boxed_clone());
|
||||
if count <= 1 || vim.workspace_state.replaying {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.cancel(&Default::default(), cx);
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_cursors_with(|map, mut cursor, _| {
|
||||
|
|
|
@ -119,7 +119,7 @@ pub(crate) fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace
|
|||
times -= 1;
|
||||
}
|
||||
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
for _ in 0..times {
|
||||
editor.join_lines(&Default::default(), cx)
|
||||
|
@ -182,7 +182,7 @@ pub(crate) fn move_cursor(
|
|||
times: Option<usize>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_cursors_with(|map, cursor, goal| {
|
||||
|
@ -198,7 +198,7 @@ fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext<Workspa
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.start_recording(cx);
|
||||
vim.switch_mode(Mode::Insert, false, cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_cursors_with(|map, cursor, _| (right(map, cursor, 1), SelectionGoal::None));
|
||||
});
|
||||
|
@ -221,7 +221,7 @@ fn insert_first_non_whitespace(
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.start_recording(cx);
|
||||
vim.switch_mode(Mode::Insert, false, cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_cursors_with(|map, cursor, _| {
|
||||
(
|
||||
|
@ -238,7 +238,7 @@ fn insert_end_of_line(_: &mut Workspace, _: &InsertEndOfLine, cx: &mut ViewConte
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.start_recording(cx);
|
||||
vim.switch_mode(Mode::Insert, false, cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_cursors_with(|map, cursor, _| {
|
||||
(next_line_end(map, cursor, 1), SelectionGoal::None)
|
||||
|
@ -252,7 +252,7 @@ fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContex
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.start_recording(cx);
|
||||
vim.switch_mode(Mode::Insert, false, cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
let (map, old_selections) = editor.selections.all_display(cx);
|
||||
let selection_start_rows: HashSet<u32> = old_selections
|
||||
|
@ -285,7 +285,7 @@ fn insert_line_below(_: &mut Workspace, _: &InsertLineBelow, cx: &mut ViewContex
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.start_recording(cx);
|
||||
vim.switch_mode(Mode::Insert, false, cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
let (map, old_selections) = editor.selections.all_display(cx);
|
||||
|
@ -330,7 +330,7 @@ fn yank_line(_: &mut Workspace, _: &YankLine, cx: &mut ViewContext<Workspace>) {
|
|||
pub(crate) fn normal_replace(text: Arc<str>, cx: &mut WindowContext) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.stop_recording();
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
let (map, display_selections) = editor.selections.all_display(cx);
|
||||
|
|
|
@ -40,7 +40,7 @@ where
|
|||
Vim::update(cx, |vim, cx| {
|
||||
vim.record_current_action(cx);
|
||||
let count = vim.take_count(cx).unwrap_or(1) as u32;
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let mut ranges = Vec::new();
|
||||
let mut cursor_positions = Vec::new();
|
||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn change_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
|
|||
| Motion::Backspace
|
||||
| Motion::StartOfLine { .. }
|
||||
);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
// We are swapping to insert mode anyway. Just set the line end clipping behavior now
|
||||
|
@ -45,7 +45,7 @@ pub fn change_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
|
|||
};
|
||||
});
|
||||
});
|
||||
copy_selections_content(editor, motion.linewise(), cx);
|
||||
copy_selections_content(vim, editor, motion.linewise(), cx);
|
||||
editor.insert("", cx);
|
||||
});
|
||||
});
|
||||
|
@ -59,7 +59,7 @@ pub fn change_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
|
|||
|
||||
pub fn change_object(vim: &mut Vim, object: Object, around: bool, cx: &mut WindowContext) {
|
||||
let mut objects_found = false;
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
// We are swapping to insert mode anyway. Just set the line end clipping behavior now
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
|
@ -69,7 +69,7 @@ pub fn change_object(vim: &mut Vim, object: Object, around: bool, cx: &mut Windo
|
|||
});
|
||||
});
|
||||
if objects_found {
|
||||
copy_selections_content(editor, false, cx);
|
||||
copy_selections_content(vim, editor, false, cx);
|
||||
editor.insert("", cx);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ use language::Point;
|
|||
|
||||
pub fn delete_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &mut WindowContext) {
|
||||
vim.stop_recording();
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
|
@ -39,7 +39,7 @@ pub fn delete_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
|
|||
}
|
||||
});
|
||||
});
|
||||
copy_selections_content(editor, motion.linewise(), cx);
|
||||
copy_selections_content(vim, editor, motion.linewise(), cx);
|
||||
editor.insert("", cx);
|
||||
|
||||
// Fixup cursor position after the deletion
|
||||
|
@ -62,7 +62,7 @@ pub fn delete_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
|
|||
|
||||
pub fn delete_object(vim: &mut Vim, object: Object, around: bool, cx: &mut WindowContext) {
|
||||
vim.stop_recording();
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
// Emulates behavior in vim where if we expanded backwards to include a newline
|
||||
|
@ -98,7 +98,7 @@ pub fn delete_object(vim: &mut Vim, object: Object, around: bool, cx: &mut Windo
|
|||
}
|
||||
});
|
||||
});
|
||||
copy_selections_content(editor, false, cx);
|
||||
copy_selections_content(vim, editor, false, cx);
|
||||
editor.insert("", cx);
|
||||
|
||||
// Fixup cursor position after the deletion
|
||||
|
|
|
@ -44,7 +44,7 @@ pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
|
|||
}
|
||||
|
||||
fn increment(vim: &mut Vim, mut delta: i32, step: i32, cx: &mut WindowContext) {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let mut edits = Vec::new();
|
||||
let mut new_anchors = Vec::new();
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use std::{borrow::Cow, cmp};
|
||||
use std::cmp;
|
||||
|
||||
use editor::{
|
||||
display_map::ToDisplayPoint, movement, scroll::Autoscroll, ClipboardSelection, DisplayPoint,
|
||||
};
|
||||
use gpui::{impl_actions, ViewContext};
|
||||
use gpui::{impl_actions, AppContext, ViewContext};
|
||||
use language::{Bias, SelectionGoal};
|
||||
use serde::Deserialize;
|
||||
use settings::Settings;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::{state::Mode, utils::copy_selections_content, Vim};
|
||||
use crate::{state::Mode, utils::copy_selections_content, UseSystemClipboard, Vim, VimSettings};
|
||||
|
||||
#[derive(Clone, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -25,34 +26,60 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>
|
|||
workspace.register_action(paste);
|
||||
}
|
||||
|
||||
fn system_clipboard_is_newer(vim: &Vim, cx: &mut AppContext) -> bool {
|
||||
cx.read_from_clipboard().is_some_and(|item| {
|
||||
if let Some(last_state) = vim.workspace_state.registers.get(".system.") {
|
||||
last_state != item.text()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn paste(_: &mut Workspace, action: &Paste, cx: &mut ViewContext<Workspace>) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.record_current_action(cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
|
||||
let Some(item) = cx.read_from_clipboard() else {
|
||||
return;
|
||||
};
|
||||
let clipboard_text = Cow::Borrowed(item.text());
|
||||
let (clipboard_text, clipboard_selections): (String, Option<_>) =
|
||||
if VimSettings::get_global(cx).use_system_clipboard == UseSystemClipboard::Never
|
||||
|| VimSettings::get_global(cx).use_system_clipboard
|
||||
== UseSystemClipboard::OnYank
|
||||
&& !system_clipboard_is_newer(vim, cx)
|
||||
{
|
||||
(
|
||||
vim.workspace_state
|
||||
.registers
|
||||
.get("\"")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "".to_string()),
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
if let Some(item) = cx.read_from_clipboard() {
|
||||
let clipboard_selections = item
|
||||
.metadata::<Vec<ClipboardSelection>>()
|
||||
.filter(|clipboard_selections| {
|
||||
clipboard_selections.len() > 1
|
||||
&& vim.state().mode != Mode::VisualLine
|
||||
});
|
||||
(item.text().clone(), clipboard_selections)
|
||||
} else {
|
||||
("".into(), None)
|
||||
}
|
||||
};
|
||||
|
||||
if clipboard_text.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if !action.preserve_clipboard && vim.state().mode.is_visual() {
|
||||
copy_selections_content(editor, vim.state().mode == Mode::VisualLine, cx);
|
||||
copy_selections_content(vim, editor, vim.state().mode == Mode::VisualLine, cx);
|
||||
}
|
||||
|
||||
// if we are copying from multi-cursor (of visual block mode), we want
|
||||
// to
|
||||
let clipboard_selections =
|
||||
item.metadata::<Vec<ClipboardSelection>>()
|
||||
.filter(|clipboard_selections| {
|
||||
clipboard_selections.len() > 1 && vim.state().mode != Mode::VisualLine
|
||||
});
|
||||
|
||||
let (display_map, current_selections) = editor.selections.all_adjusted_display(cx);
|
||||
|
||||
// unlike zed, if you have a multi-cursor selection from vim block mode,
|
||||
|
@ -201,8 +228,11 @@ mod test {
|
|||
use crate::{
|
||||
state::Mode,
|
||||
test::{NeovimBackedTestContext, VimTestContext},
|
||||
UseSystemClipboard, VimSettings,
|
||||
};
|
||||
use gpui::ClipboardItem;
|
||||
use indoc::indoc;
|
||||
use settings::SettingsStore;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_paste(cx: &mut gpui::TestAppContext) {
|
||||
|
@ -291,6 +321,103 @@ mod test {
|
|||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_yank_system_clipboard_never(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings::<VimSettings>(cx, |s| {
|
||||
s.use_system_clipboard = Some(UseSystemClipboard::Never)
|
||||
});
|
||||
});
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox jˇumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes(["v", "i", "w", "y"]);
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox ˇjumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystroke("p");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox jjumpˇsumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
assert_eq!(cx.read_from_clipboard(), None);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_yank_system_clipboard_on_yank(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings::<VimSettings>(cx, |s| {
|
||||
s.use_system_clipboard = Some(UseSystemClipboard::OnYank)
|
||||
});
|
||||
});
|
||||
|
||||
// copy in visual mode
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox jˇumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes(["v", "i", "w", "y"]);
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox ˇjumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystroke("p");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
fox jjumpˇsumps over
|
||||
the lazy dog"},
|
||||
Mode::Normal,
|
||||
);
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard().map(|item| item.text().clone()),
|
||||
Some("jumps".into())
|
||||
);
|
||||
cx.simulate_keystrokes(["d", "d", "p"]);
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
the lazy dog
|
||||
ˇfox jjumpsumps over"},
|
||||
Mode::Normal,
|
||||
);
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard().map(|item| item.text().clone()),
|
||||
Some("jumps".into())
|
||||
);
|
||||
cx.write_to_clipboard(ClipboardItem::new("test-copy".to_string()));
|
||||
cx.simulate_keystroke("shift-p");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The quick brown
|
||||
the lazy dog
|
||||
test-copˇyfox jjumpsumps over"},
|
||||
Mode::Normal,
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_paste_visual(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
|
|
@ -52,7 +52,7 @@ fn scroll(
|
|||
) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
let amount = by(vim.take_count(cx).map(|c| c as f32));
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
scroll_editor(editor, move_cursor, &amount, cx)
|
||||
});
|
||||
})
|
||||
|
|
|
@ -29,7 +29,7 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>
|
|||
}
|
||||
|
||||
pub fn substitute(vim: &mut Vim, count: Option<usize>, line_mode: bool, cx: &mut WindowContext) {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
|
@ -72,7 +72,7 @@ pub fn substitute(vim: &mut Vim, count: Option<usize>, line_mode: bool, cx: &mut
|
|||
}
|
||||
})
|
||||
});
|
||||
copy_selections_content(editor, line_mode, cx);
|
||||
copy_selections_content(vim, editor, line_mode, cx);
|
||||
let selections = editor.selections.all::<Point>(cx).into_iter();
|
||||
let edits = selections.map(|selection| (selection.start..selection.end, ""));
|
||||
editor.edit(edits, cx);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{motion::Motion, object::Object, utils::copy_and_flash_selections_content, Vim};
|
||||
use crate::{motion::Motion, object::Object, utils::yank_selections_content, Vim};
|
||||
use collections::HashMap;
|
||||
use gpui::WindowContext;
|
||||
|
||||
pub fn yank_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &mut WindowContext) {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
|
@ -15,7 +15,7 @@ pub fn yank_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &mut
|
|||
motion.expand_selection(map, selection, times, true, &text_layout_details);
|
||||
});
|
||||
});
|
||||
copy_and_flash_selections_content(editor, motion.linewise(), cx);
|
||||
yank_selections_content(vim, editor, motion.linewise(), cx);
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.move_with(|_, selection| {
|
||||
let (head, goal) = original_positions.remove(&selection.id).unwrap();
|
||||
|
@ -27,7 +27,7 @@ pub fn yank_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &mut
|
|||
}
|
||||
|
||||
pub fn yank_object(vim: &mut Vim, object: Object, around: bool, cx: &mut WindowContext) {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
let mut original_positions: HashMap<_, _> = Default::default();
|
||||
|
@ -38,7 +38,7 @@ pub fn yank_object(vim: &mut Vim, object: Object, around: bool, cx: &mut WindowC
|
|||
original_positions.insert(selection.id, original_position);
|
||||
});
|
||||
});
|
||||
copy_and_flash_selections_content(editor, false, cx);
|
||||
yank_selections_content(vim, editor, false, cx);
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.move_with(|_, selection| {
|
||||
let (head, goal) = original_positions.remove(&selection.id).unwrap();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::{Action, KeyContext};
|
||||
use language::CursorShape;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -86,6 +87,8 @@ pub struct WorkspaceState {
|
|||
pub recorded_count: Option<usize>,
|
||||
pub recorded_actions: Vec<ReplayableAction>,
|
||||
pub recorded_selection: RecordedSelection,
|
||||
|
||||
pub registers: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -3,25 +3,35 @@ use std::time::Duration;
|
|||
use editor::{ClipboardSelection, Editor};
|
||||
use gpui::{ClipboardItem, ViewContext};
|
||||
use language::{CharKind, Point};
|
||||
use settings::Settings;
|
||||
|
||||
use crate::{state::Mode, UseSystemClipboard, Vim, VimSettings};
|
||||
|
||||
pub struct HighlightOnYank;
|
||||
|
||||
pub fn copy_and_flash_selections_content(
|
||||
pub fn yank_selections_content(
|
||||
vim: &mut Vim,
|
||||
editor: &mut Editor,
|
||||
linewise: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
copy_selections_content_internal(editor, linewise, true, cx);
|
||||
copy_selections_content_internal(vim, editor, linewise, true, cx);
|
||||
}
|
||||
|
||||
pub fn copy_selections_content(editor: &mut Editor, linewise: bool, cx: &mut ViewContext<Editor>) {
|
||||
copy_selections_content_internal(editor, linewise, false, cx);
|
||||
pub fn copy_selections_content(
|
||||
vim: &mut Vim,
|
||||
editor: &mut Editor,
|
||||
linewise: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
copy_selections_content_internal(vim, editor, linewise, false, cx);
|
||||
}
|
||||
|
||||
fn copy_selections_content_internal(
|
||||
vim: &mut Vim,
|
||||
editor: &mut Editor,
|
||||
linewise: bool,
|
||||
highlight: bool,
|
||||
is_yank: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
let selections = editor.selections.all_adjusted(cx);
|
||||
|
@ -73,8 +83,22 @@ fn copy_selections_content_internal(
|
|||
}
|
||||
}
|
||||
|
||||
cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
|
||||
if !highlight {
|
||||
let setting = VimSettings::get_global(cx).use_system_clipboard;
|
||||
if setting == UseSystemClipboard::Always || setting == UseSystemClipboard::OnYank && is_yank {
|
||||
cx.write_to_clipboard(ClipboardItem::new(text.clone()).with_metadata(clipboard_selections));
|
||||
vim.workspace_state
|
||||
.registers
|
||||
.insert(".system.".to_string(), text.clone());
|
||||
} else {
|
||||
vim.workspace_state.registers.insert(
|
||||
".system.".to_string(),
|
||||
cx.read_from_clipboard()
|
||||
.map(|item| item.text().clone())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
vim.workspace_state.registers.insert("\"".to_string(), text);
|
||||
if !is_yank || vim.state().mode == Mode::Visual {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,9 @@ use language::{CursorShape, Point, Selection, SelectionGoal};
|
|||
pub use mode_indicator::ModeIndicator;
|
||||
use motion::Motion;
|
||||
use normal::normal_replace;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use settings::{update_settings_file, Settings, SettingsStore};
|
||||
use state::{EditorState, Mode, Operator, RecordedSelection, WorkspaceState};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
@ -70,6 +72,7 @@ impl_actions!(vim, [SwitchMode, PushOperator, Number]);
|
|||
pub fn init(cx: &mut AppContext) {
|
||||
cx.set_global(Vim::default());
|
||||
VimModeSetting::register(cx);
|
||||
VimSettings::register(cx);
|
||||
|
||||
editor_events::init(cx);
|
||||
|
||||
|
@ -261,12 +264,12 @@ impl Vim {
|
|||
}
|
||||
|
||||
fn update_active_editor<S>(
|
||||
&self,
|
||||
&mut self,
|
||||
cx: &mut WindowContext,
|
||||
update: impl FnOnce(&mut Editor, &mut ViewContext<Editor>) -> S,
|
||||
update: impl FnOnce(&mut Vim, &mut Editor, &mut ViewContext<Editor>) -> S,
|
||||
) -> Option<S> {
|
||||
let editor = self.active_editor.clone()?.upgrade()?;
|
||||
Some(editor.update(cx, update))
|
||||
Some(editor.update(cx, |editor, cx| update(self, editor, cx)))
|
||||
}
|
||||
|
||||
/// When doing an action that modifies the buffer, we start recording so that `.`
|
||||
|
@ -365,7 +368,7 @@ impl Vim {
|
|||
}
|
||||
|
||||
// Adjust selections
|
||||
self.update_active_editor(cx, |editor, cx| {
|
||||
self.update_active_editor(cx, |_, editor, cx| {
|
||||
if last_mode != Mode::VisualBlock && last_mode.is_visual() && mode == Mode::VisualBlock
|
||||
{
|
||||
visual_block_motion(true, editor, cx, |_, point, goal| Some((point, goal)))
|
||||
|
@ -565,10 +568,9 @@ impl Vim {
|
|||
ret
|
||||
}
|
||||
|
||||
fn sync_vim_settings(&self, cx: &mut WindowContext) {
|
||||
let state = self.state();
|
||||
|
||||
self.update_active_editor(cx, |editor, cx| {
|
||||
fn sync_vim_settings(&mut self, cx: &mut WindowContext) {
|
||||
self.update_active_editor(cx, |vim, editor, cx| {
|
||||
let state = vim.state();
|
||||
editor.set_cursor_shape(state.cursor_shape(), cx);
|
||||
editor.set_clip_at_line_ends(state.clip_at_line_ends(), cx);
|
||||
editor.set_collapse_matches(true);
|
||||
|
@ -612,6 +614,42 @@ impl Settings for VimModeSetting {
|
|||
}
|
||||
}
|
||||
|
||||
/// Controls the soft-wrapping behavior in the editor.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum UseSystemClipboard {
|
||||
Never,
|
||||
Always,
|
||||
OnYank,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct VimSettings {
|
||||
// all vim uses vim clipboard
|
||||
// vim always uses system cliupbaord
|
||||
// some magic where yy is system and dd is not.
|
||||
pub use_system_clipboard: UseSystemClipboard,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
struct VimSettingsContent {
|
||||
pub use_system_clipboard: Option<UseSystemClipboard>,
|
||||
}
|
||||
|
||||
impl Settings for VimSettings {
|
||||
const KEY: Option<&'static str> = Some("vim");
|
||||
|
||||
type FileContent = VimSettingsContent;
|
||||
|
||||
fn load(
|
||||
default_value: &Self::FileContent,
|
||||
user_values: &[&Self::FileContent],
|
||||
_: &mut AppContext,
|
||||
) -> Result<Self> {
|
||||
Self::load_via_json_merge(default_value, user_values)
|
||||
}
|
||||
}
|
||||
|
||||
fn local_selections_changed(
|
||||
newest: Selection<usize>,
|
||||
is_multicursor: bool,
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
motion::{start_of_line, Motion},
|
||||
object::Object,
|
||||
state::{Mode, Operator},
|
||||
utils::copy_selections_content,
|
||||
utils::{copy_selections_content, yank_selections_content},
|
||||
Vim,
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,7 @@ pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
|
|||
|
||||
pub fn visual_motion(motion: Motion, times: Option<usize>, cx: &mut WindowContext) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let text_layout_details = editor.text_layout_details(cx);
|
||||
if vim.state().mode == Mode::VisualBlock
|
||||
&& !matches!(
|
||||
|
@ -251,7 +251,7 @@ pub fn visual_object(object: Object, cx: &mut WindowContext) {
|
|||
vim.switch_mode(target_mode, true, cx);
|
||||
}
|
||||
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
let mut head = selection.head();
|
||||
|
@ -298,7 +298,7 @@ fn toggle_mode(mode: Mode, cx: &mut ViewContext<Workspace>) {
|
|||
|
||||
pub fn other_end(_: &mut Workspace, _: &OtherEnd, cx: &mut ViewContext<Workspace>) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.move_with(|_, selection| {
|
||||
selection.reversed = !selection.reversed;
|
||||
|
@ -311,7 +311,7 @@ pub fn other_end(_: &mut Workspace, _: &OtherEnd, cx: &mut ViewContext<Workspace
|
|||
pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspace>) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.record_current_action(cx);
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let mut original_columns: HashMap<_, _> = Default::default();
|
||||
let line_mode = editor.selections.line_mode;
|
||||
|
||||
|
@ -328,7 +328,7 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspac
|
|||
selection.goal = SelectionGoal::None;
|
||||
});
|
||||
});
|
||||
copy_selections_content(editor, line_mode, cx);
|
||||
copy_selections_content(vim, editor, line_mode, cx);
|
||||
editor.insert("", cx);
|
||||
|
||||
// Fixup cursor position after the deletion
|
||||
|
@ -355,9 +355,9 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspac
|
|||
|
||||
pub fn yank(_: &mut Workspace, _: &VisualYank, cx: &mut ViewContext<Workspace>) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |vim, editor, cx| {
|
||||
let line_mode = editor.selections.line_mode;
|
||||
copy_selections_content(editor, line_mode, cx);
|
||||
yank_selections_content(vim, editor, line_mode, cx);
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
if line_mode {
|
||||
|
@ -377,7 +377,7 @@ pub fn yank(_: &mut Workspace, _: &VisualYank, cx: &mut ViewContext<Workspace>)
|
|||
pub(crate) fn visual_replace(text: Arc<str>, cx: &mut WindowContext) {
|
||||
Vim::update(cx, |vim, cx| {
|
||||
vim.stop_recording();
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
let (display_map, selections) = editor.selections.all_adjusted_display(cx);
|
||||
|
||||
|
@ -426,7 +426,7 @@ pub fn select_next(
|
|||
let count =
|
||||
vim.take_count(cx)
|
||||
.unwrap_or_else(|| if vim.state().mode.is_visual() { 1 } else { 2 });
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
for _ in 0..count {
|
||||
match editor.select_next(&Default::default(), cx) {
|
||||
Err(a) => return Err(a),
|
||||
|
@ -448,7 +448,7 @@ pub fn select_previous(
|
|||
let count =
|
||||
vim.take_count(cx)
|
||||
.unwrap_or_else(|| if vim.state().mode.is_visual() { 1 } else { 2 });
|
||||
vim.update_active_editor(cx, |editor, cx| {
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
for _ in 0..count {
|
||||
match editor.select_previous(&Default::default(), cx) {
|
||||
Err(a) => return Err(a),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue