Detailed changes
@@ -385,6 +385,7 @@
"g u": ["vim::PushOperator", "Lowercase"],
"g shift-u": ["vim::PushOperator", "Uppercase"],
"g ~": ["vim::PushOperator", "OppositeCase"],
+ "\"": ["vim::PushOperator", "Register"],
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem",
// tree-sitter related commands
@@ -399,6 +400,7 @@
{
"context": "Editor && vim_mode == visual && vim_operator == none && !VimWaiting",
"bindings": {
+ "\"": ["vim::PushOperator", "Register"],
// tree-sitter related commands
"[ x": "editor::SelectLargerSyntaxNode",
"] x": "editor::SelectSmallerSyntaxNode"
@@ -1502,7 +1502,7 @@ struct ActiveDiagnosticGroup {
is_valid: bool,
}
-#[derive(Serialize, Deserialize)]
+#[derive(Serialize, Deserialize, Clone)]
pub struct ClipboardSelection {
pub len: usize,
pub is_entire_line: bool,
@@ -356,7 +356,7 @@ fn is_identifier_char(c: char) -> bool {
}
fn is_vim_operator_char(c: char) -> bool {
- c == '>' || c == '<' || c == '~'
+ c == '>' || c == '<' || c == '~' || c == '"'
}
fn skip_whitespace(source: &str) -> &str {
@@ -39,9 +39,17 @@ impl ModeIndicator {
fn current_operators_description(&self, vim: &Vim) -> String {
vim.state()
- .operator_stack
- .iter()
- .map(|item| item.id())
+ .pre_count
+ .map(|count| format!("{}", count))
+ .into_iter()
+ .chain(vim.state().selected_register.map(|reg| format!("\"{reg}")))
+ .chain(
+ vim.state()
+ .operator_stack
+ .iter()
+ .map(|item| item.id().to_string()),
+ )
+ .chain(vim.state().post_count.map(|count| format!("{}", count)))
.collect::<Vec<_>>()
.join("")
}
@@ -10,7 +10,11 @@ use serde::Deserialize;
use settings::Settings;
use workspace::Workspace;
-use crate::{state::Mode, utils::copy_selections_content, UseSystemClipboard, Vim, VimSettings};
+use crate::{
+ state::Mode,
+ utils::{copy_selections_content, SYSTEM_CLIPBOARD},
+ UseSystemClipboard, Vim, VimSettings,
+};
#[derive(Clone, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
@@ -29,7 +33,7 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>
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.") {
+ if let Some(last_state) = vim.workspace_state.registers.get(&SYSTEM_CLIPBOARD) {
last_state != item.text()
} else {
true
@@ -46,33 +50,36 @@ fn paste(_: &mut Workspace, action: &Paste, cx: &mut ViewContext<Workspace>) {
editor.transact(cx, |editor, cx| {
editor.set_clip_at_line_ends(false, cx);
- 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,
- )
+ let (clipboard_text, clipboard_selections): (String, Option<_>) = if let Some(
+ register,
+ ) =
+ vim.update_state(|state| state.selected_register.take())
+ {
+ (
+ vim.read_register(register, Some(editor), cx)
+ .unwrap_or_default(),
+ None,
+ )
+ } else 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.read_register('"', None, cx).unwrap_or_default(), 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 {
- 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)
- }
- };
+ ("".into(), None)
+ }
+ };
if clipboard_text.is_empty() {
return;
@@ -606,4 +613,119 @@ mod test {
three
"});
}
+
+ #[gpui::test]
+ async fn test_numbered_registers(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.update_global(|store: &mut SettingsStore, cx| {
+ store.update_user_settings::<VimSettings>(cx, |s| {
+ s.use_system_clipboard = Some(UseSystemClipboard::Never)
+ });
+ });
+
+ cx.set_shared_state(indoc! {"
+ The quick brown
+ fox jˇumps over
+ the lazy dog"})
+ .await;
+ cx.simulate_shared_keystrokes("y y \" 0 p").await;
+ cx.shared_register('0').await.assert_eq("fox jumps over\n");
+ cx.shared_register('"').await.assert_eq("fox jumps over\n");
+
+ cx.shared_state().await.assert_eq(indoc! {"
+ The quick brown
+ fox jumps over
+ ˇfox jumps over
+ the lazy dog"});
+ cx.simulate_shared_keystrokes("k k d d").await;
+ cx.shared_register('0').await.assert_eq("fox jumps over\n");
+ cx.shared_register('1').await.assert_eq("The quick brown\n");
+ cx.shared_register('"').await.assert_eq("The quick brown\n");
+
+ cx.simulate_shared_keystrokes("d d shift-g d d").await;
+ cx.shared_register('0').await.assert_eq("fox jumps over\n");
+ cx.shared_register('3').await.assert_eq("The quick brown\n");
+ cx.shared_register('2').await.assert_eq("fox jumps over\n");
+ cx.shared_register('1').await.assert_eq("the lazy dog\n");
+
+ cx.shared_state().await.assert_eq(indoc! {"
+ ˇfox jumps over"});
+
+ cx.simulate_shared_keystrokes("d d \" 3 p p \" 1 p").await;
+ cx.set_shared_state(indoc! {"
+ The quick brown
+ fox jumps over
+ ˇthe lazy dog"})
+ .await;
+ }
+
+ #[gpui::test]
+ async fn test_named_registers(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.update_global(|store: &mut SettingsStore, cx| {
+ store.update_user_settings::<VimSettings>(cx, |s| {
+ s.use_system_clipboard = Some(UseSystemClipboard::Never)
+ });
+ });
+
+ cx.set_shared_state(indoc! {"
+ The quick brown
+ fox jˇumps over
+ the lazy dog"})
+ .await;
+ cx.simulate_shared_keystrokes("\" a d a w").await;
+ cx.shared_register('a').await.assert_eq("jumps ");
+ cx.simulate_shared_keystrokes("\" shift-a d i w").await;
+ cx.shared_register('a').await.assert_eq("jumps over");
+ cx.simulate_shared_keystrokes("\" a p").await;
+ cx.shared_state().await.assert_eq(indoc! {"
+ The quick brown
+ fox jumps oveˇr
+ the lazy dog"});
+ cx.simulate_shared_keystrokes("\" a d a w").await;
+ cx.shared_register('a').await.assert_eq(" over");
+ }
+
+ #[gpui::test]
+ async fn test_special_registers(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.update_global(|store: &mut SettingsStore, cx| {
+ store.update_user_settings::<VimSettings>(cx, |s| {
+ s.use_system_clipboard = Some(UseSystemClipboard::Never)
+ });
+ });
+
+ cx.set_shared_state(indoc! {"
+ The quick brown
+ fox jˇumps over
+ the lazy dog"})
+ .await;
+ cx.simulate_shared_keystrokes("d i w").await;
+ cx.shared_register('-').await.assert_eq("jumps");
+ cx.simulate_shared_keystrokes("\" _ d d").await;
+ cx.shared_register('_').await.assert_eq("");
+
+ cx.shared_state().await.assert_eq(indoc! {"
+ The quick brown
+ the ˇlazy dog"});
+ cx.simulate_shared_keystrokes("\" \" d ^").await;
+ cx.shared_register('0').await.assert_eq("the ");
+ cx.shared_register('"').await.assert_eq("the ");
+
+ cx.simulate_shared_keystrokes("^ \" + d $").await;
+ cx.shared_clipboard().await.assert_eq("lazy dog");
+ cx.shared_register('"').await.assert_eq("lazy dog");
+
+ // not testing nvim as it doesn't have a filename
+ cx.simulate_keystrokes("\" % p");
+ cx.assert_state(
+ indoc! {"
+ The quick brown
+ dir/file.rˇs"},
+ Mode::Normal,
+ );
+ }
}
@@ -63,10 +63,10 @@ pub enum Operator {
Jump { line: bool },
Indent,
Outdent,
-
Lowercase,
Uppercase,
OppositeCase,
+ Register,
}
#[derive(Default, Clone)]
@@ -89,6 +89,8 @@ pub struct EditorState {
pub current_tx: Option<TransactionId>,
pub current_anchor: Option<Selection<Anchor>>,
pub undo_modes: HashMap<TransactionId, Mode>,
+
+ pub selected_register: Option<char>,
}
#[derive(Default, Clone, Debug)]
@@ -123,7 +125,7 @@ pub struct WorkspaceState {
pub recorded_actions: Vec<ReplayableAction>,
pub recorded_selection: RecordedSelection,
- pub registers: HashMap<String, String>,
+ pub registers: HashMap<char, String>,
}
#[derive(Debug)]
@@ -277,6 +279,7 @@ impl Operator {
Operator::Uppercase => "gU",
Operator::Lowercase => "gu",
Operator::OppositeCase => "g~",
+ Operator::Register => "\"",
}
}
@@ -287,6 +290,7 @@ impl Operator {
| Operator::Mark
| Operator::Jump { .. }
| Operator::FindBackward { .. }
+ | Operator::Register
| Operator::Replace
| Operator::AddSurrounds { target: Some(_) }
| Operator::ChangeSurrounds { .. }
@@ -10,7 +10,7 @@ use language::language_settings::{AllLanguageSettings, SoftWrap};
use util::test::marked_text_offsets;
use super::{neovim_connection::NeovimConnection, VimTestContext};
-use crate::state::Mode;
+use crate::{state::Mode, Vim};
pub struct NeovimBackedTestContext {
cx: VimTestContext,
@@ -94,6 +94,7 @@ impl SharedState {
}
pub struct SharedClipboard {
+ register: char,
neovim: String,
editor: String,
state: SharedState,
@@ -120,15 +121,17 @@ impl SharedClipboard {
{}
# currently expected:
{}
- # neovim clipboard:
+ # neovim register \"{}:
{}
- # zed clipboard:
+ # zed register \"{}:
{}"},
message,
self.state.initial,
self.state.recent_keystrokes,
expected,
+ self.register,
self.neovim,
+ self.register,
self.editor
)
}
@@ -241,12 +244,30 @@ impl NeovimBackedTestContext {
#[must_use]
pub async fn shared_clipboard(&mut self) -> SharedClipboard {
SharedClipboard {
+ register: '"',
state: self.shared_state().await,
neovim: self.neovim.read_register('"').await,
editor: self.read_from_clipboard().unwrap().text().clone(),
}
}
+ #[must_use]
+ pub async fn shared_register(&mut self, register: char) -> SharedClipboard {
+ SharedClipboard {
+ register: register,
+ state: self.shared_state().await,
+ neovim: self.neovim.read_register(register).await,
+ editor: self.update(|cx| {
+ Vim::read(cx)
+ .workspace_state
+ .registers
+ .get(®ister)
+ .cloned()
+ .unwrap_or_default()
+ }),
+ }
+ }
+
#[must_use]
pub async fn shared_state(&mut self) -> SharedState {
let (mode, marked_text) = self.neovim.state().await;
@@ -1,12 +1,13 @@
use std::time::Duration;
use editor::{ClipboardSelection, Editor};
-use gpui::{ClipboardItem, ViewContext};
+use gpui::ViewContext;
use language::{CharKind, Point};
use multi_buffer::MultiBufferRow;
-use settings::Settings;
-use crate::{state::Mode, UseSystemClipboard, Vim, VimSettings};
+use crate::{state::Mode, Vim};
+
+pub const SYSTEM_CLIPBOARD: char = '\0';
pub struct HighlightOnYank;
@@ -102,21 +103,8 @@ fn copy_selections_content_internal(
}
}
- 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);
+ vim.write_registers(is_yank, linewise, text, clipboard_selections, cx);
+
if !is_yank || vim.state().mode == Mode::Visual {
return;
}
@@ -23,11 +23,11 @@ use collections::HashMap;
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
use editor::{
movement::{self, FindRange},
- Anchor, Bias, Editor, EditorEvent, EditorMode, ToPoint,
+ Anchor, Bias, ClipboardSelection, Editor, EditorEvent, EditorMode, ToPoint,
};
use gpui::{
- actions, impl_actions, Action, AppContext, EntityId, FocusableView, Global, KeystrokeEvent,
- Subscription, UpdateGlobal, View, ViewContext, WeakView, WindowContext,
+ actions, impl_actions, Action, AppContext, ClipboardItem, EntityId, FocusableView, Global,
+ KeystrokeEvent, Subscription, UpdateGlobal, View, ViewContext, WeakView, WindowContext,
};
use language::{CursorShape, Point, SelectionGoal, TransactionId};
pub use mode_indicator::ModeIndicator;
@@ -45,6 +45,7 @@ use state::{EditorState, Mode, Operator, RecordedSelection, WorkspaceState};
use std::{ops::Range, sync::Arc};
use surrounds::{add_surrounds, change_surrounds, delete_surrounds};
use ui::BorrowAppContext;
+use utils::SYSTEM_CLIPBOARD;
use visual::{visual_block_motion, visual_replace};
use workspace::{self, Workspace};
@@ -70,6 +71,9 @@ pub struct PushOperator(pub Operator);
#[derive(Clone, Deserialize, PartialEq)]
struct Number(usize);
+#[derive(Clone, Deserialize, PartialEq)]
+struct SelectRegister(String);
+
actions!(
vim,
[
@@ -86,7 +90,7 @@ actions!(
// in the workspace namespace so it's not filtered out when vim is disabled.
actions!(workspace, [ToggleVimMode]);
-impl_actions!(vim, [SwitchMode, PushOperator, Number]);
+impl_actions!(vim, [SwitchMode, PushOperator, Number, SelectRegister]);
/// Initializes the `vim` crate.
pub fn init(cx: &mut AppContext) {
@@ -129,7 +133,6 @@ fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
workspace.register_action(|_: &mut Workspace, n: &Number, cx: _| {
Vim::update(cx, |vim, cx| vim.push_count_digit(n.0, cx));
});
-
workspace.register_action(|_: &mut Workspace, _: &Tab, cx| {
Vim::active_editor_input_ignored(" ".into(), cx)
});
@@ -202,7 +205,8 @@ fn observe_keystrokes(keystroke_event: &KeystrokeEvent, cx: &mut WindowContext)
| Operator::ChangeSurrounds { .. }
| Operator::DeleteSurrounds
| Operator::Mark
- | Operator::Jump { .. },
+ | Operator::Jump { .. }
+ | Operator::Register,
) => {}
Some(_) => {
vim.clear_operator(cx);
@@ -531,6 +535,138 @@ impl Vim {
count
}
+ fn select_register(&mut self, register: Arc<str>, cx: &mut WindowContext) {
+ self.update_state(|state| {
+ if register.chars().count() == 1 {
+ state
+ .selected_register
+ .replace(register.chars().next().unwrap());
+ }
+ state.operator_stack.clear();
+ });
+ self.sync_vim_settings(cx);
+ }
+
+ fn write_registers(
+ &mut self,
+ is_yank: bool,
+ linewise: bool,
+ text: String,
+ clipboard_selections: Vec<ClipboardSelection>,
+ cx: &mut ViewContext<Editor>,
+ ) {
+ self.workspace_state.registers.insert('"', text.clone());
+ if let Some(register) = self.update_state(|vim| vim.selected_register.take()) {
+ let lower = register.to_lowercase().next().unwrap_or(register);
+ if lower != register {
+ let current = self.workspace_state.registers.entry(lower).or_default();
+ *current += &text;
+ } else {
+ match lower {
+ '_' | ':' | '.' | '%' | '#' | '=' | '/' => {}
+ '+' => {
+ cx.write_to_clipboard(
+ ClipboardItem::new(text.clone()).with_metadata(clipboard_selections),
+ );
+ }
+ '*' => {
+ #[cfg(target_os = "linux")]
+ cx.write_to_primary(
+ ClipboardItem::new(text.clone()).with_metadata(clipboard_selections),
+ );
+ #[cfg(not(target_os = "linux"))]
+ cx.write_to_clipboard(
+ ClipboardItem::new(text.clone()).with_metadata(clipboard_selections),
+ );
+ }
+ '"' => {
+ self.workspace_state.registers.insert('0', text.clone());
+ self.workspace_state.registers.insert('"', text);
+ }
+ _ => {
+ self.workspace_state.registers.insert(lower, text);
+ }
+ }
+ }
+ } else {
+ 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.clone()),
+ );
+ self.workspace_state
+ .registers
+ .insert(SYSTEM_CLIPBOARD, text.clone());
+ } else {
+ self.workspace_state.registers.insert(
+ SYSTEM_CLIPBOARD,
+ cx.read_from_clipboard()
+ .map(|item| item.text().clone())
+ .unwrap_or_default(),
+ );
+ }
+
+ if is_yank {
+ self.workspace_state.registers.insert('0', text);
+ } else {
+ if !text.contains('\n') {
+ self.workspace_state.registers.insert('-', text.clone());
+ }
+ if linewise || text.contains('\n') {
+ let mut content = text;
+ for i in '1'..'8' {
+ if let Some(moved) = self.workspace_state.registers.insert(i, content) {
+ content = moved;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fn read_register(
+ &mut self,
+ register: char,
+ editor: Option<&mut Editor>,
+ cx: &mut WindowContext,
+ ) -> Option<String> {
+ let lower = register.to_lowercase().next().unwrap_or(register);
+ match lower {
+ '_' | ':' | '.' | '#' | '=' | '/' => None,
+ '+' => cx.read_from_clipboard().map(|item| item.text().clone()),
+ '*' => {
+ #[cfg(target_os = "linux")]
+ {
+ cx.read_from_primary().map(|item| item.text().clone())
+ }
+ #[cfg(not(target_os = "linux"))]
+ {
+ cx.read_from_clipboard().map(|item| item.text().clone())
+ }
+ }
+ '%' => editor.and_then(|editor| {
+ let selection = editor.selections.newest::<Point>(cx);
+ if let Some((_, buffer, _)) = editor
+ .buffer()
+ .read(cx)
+ .excerpt_containing(selection.head(), cx)
+ {
+ buffer
+ .read(cx)
+ .file()
+ .map(|file| file.path().to_string_lossy().to_string())
+ } else {
+ None
+ }
+ }),
+ _ => self.workspace_state.registers.get(&lower).cloned(),
+ }
+ }
+
fn push_operator(&mut self, operator: Operator, cx: &mut WindowContext) {
if matches!(
operator,
@@ -573,7 +709,10 @@ impl Vim {
fn clear_operator(&mut self, cx: &mut WindowContext) {
self.take_count(cx);
- self.update_state(|state| state.operator_stack.clear());
+ self.update_state(|state| {
+ state.selected_register.take();
+ state.operator_stack.clear()
+ });
self.sync_vim_settings(cx);
}
@@ -741,6 +880,9 @@ impl Vim {
Some(Operator::Mark) => Vim::update(cx, |vim, cx| {
normal::mark::create_mark(vim, text, false, cx)
}),
+ Some(Operator::Register) => Vim::update(cx, |vim, cx| {
+ vim.select_register(text, cx);
+ }),
Some(Operator::Jump { line }) => normal::mark::jump(text, line, cx),
_ => match Vim::read(cx).state().mode {
Mode::Replace => multi_replace(text, cx),
@@ -0,0 +1,26 @@
+{"Put":{"state":"The quick brown\nfox jˇumps over\nthe lazy dog"}}
+{"Key":"\""}
+{"Key":"a"}
+{"Key":"d"}
+{"Key":"a"}
+{"Key":"w"}
+{"Get":{"state":"The quick brown\nfox ˇover\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"a","value":"jumps "}}
+{"Key":"\""}
+{"Key":"shift-a"}
+{"Key":"d"}
+{"Key":"i"}
+{"Key":"w"}
+{"Get":{"state":"The quick brown\nfoxˇ \nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"a","value":"jumps over"}}
+{"Key":"\""}
+{"Key":"a"}
+{"Key":"p"}
+{"Get":{"state":"The quick brown\nfox jumps oveˇr\nthe lazy dog","mode":"Normal"}}
+{"Key":"\""}
+{"Key":"a"}
+{"Key":"d"}
+{"Key":"a"}
+{"Key":"w"}
+{"Get":{"state":"The quick brown\nfox jumpˇs\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"a","value":" over"}}
@@ -0,0 +1,45 @@
+{"Put":{"state":"The quick brown\nfox jˇumps over\nthe lazy dog"}}
+{"Key":"y"}
+{"Key":"y"}
+{"Key":"\""}
+{"Key":"0"}
+{"Key":"p"}
+{"Get":{"state":"The quick brown\nfox jumps over\nˇfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"0","value":"fox jumps over\n"}}
+{"Get":{"state":"The quick brown\nfox jumps over\nˇfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"\"","value":"fox jumps over\n"}}
+{"Get":{"state":"The quick brown\nfox jumps over\nˇfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"Key":"k"}
+{"Key":"k"}
+{"Key":"d"}
+{"Key":"d"}
+{"Get":{"state":"ˇfox jumps over\nfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"0","value":"fox jumps over\n"}}
+{"Get":{"state":"ˇfox jumps over\nfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"1","value":"The quick brown\n"}}
+{"Get":{"state":"ˇfox jumps over\nfox jumps over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"\"","value":"The quick brown\n"}}
+{"Key":"d"}
+{"Key":"d"}
+{"Key":"shift-g"}
+{"Key":"d"}
+{"Key":"d"}
+{"Get":{"state":"ˇfox jumps over","mode":"Normal"}}
+{"ReadRegister":{"name":"0","value":"fox jumps over\n"}}
+{"Get":{"state":"ˇfox jumps over","mode":"Normal"}}
+{"ReadRegister":{"name":"3","value":"The quick brown\n"}}
+{"Get":{"state":"ˇfox jumps over","mode":"Normal"}}
+{"ReadRegister":{"name":"2","value":"fox jumps over\n"}}
+{"Get":{"state":"ˇfox jumps over","mode":"Normal"}}
+{"ReadRegister":{"name":"1","value":"the lazy dog\n"}}
+{"Get":{"state":"ˇfox jumps over","mode":"Normal"}}
+{"Key":"d"}
+{"Key":"d"}
+{"Key":"\""}
+{"Key":"3"}
+{"Key":"p"}
+{"Key":"p"}
+{"Key":"\""}
+{"Key":"1"}
+{"Key":"p"}
+{"Put":{"state":"The quick brown\nfox jumps over\nˇthe lazy dog"}}
@@ -0,0 +1,30 @@
+{"Put":{"state":"The quick brown\nfox jˇumps over\nthe lazy dog"}}
+{"Key":"d"}
+{"Key":"i"}
+{"Key":"w"}
+{"Get":{"state":"The quick brown\nfox ˇ over\nthe lazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"-","value":"jumps"}}
+{"Key":"\""}
+{"Key":"_"}
+{"Key":"d"}
+{"Key":"d"}
+{"Get":{"state":"The quick brown\nthe ˇlazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"_","value":""}}
+{"Get":{"state":"The quick brown\nthe ˇlazy dog","mode":"Normal"}}
+{"Key":"\""}
+{"Key":"\""}
+{"Key":"d"}
+{"Key":"^"}
+{"Get":{"state":"The quick brown\nˇlazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"0","value":"the "}}
+{"Get":{"state":"The quick brown\nˇlazy dog","mode":"Normal"}}
+{"ReadRegister":{"name":"\"","value":"the "}}
+{"Key":"^"}
+{"Key":"\""}
+{"Key":"+"}
+{"Key":"d"}
+{"Key":"$"}
+{"Get":{"state":"The quick brown\nˇ","mode":"Normal"}}
+{"ReadRegister":{"name":"\"","value":"lazy dog"}}
+{"Get":{"state":"The quick brown\nˇ","mode":"Normal"}}
+{"ReadRegister":{"name":"\"","value":"lazy dog"}}
@@ -215,9 +215,9 @@ Some vim settings are available to modify the default vim behavior:
```json
{
"vim": {
- // "always": use system clipboard
- // "never": don't use system clipboard
- // "on_yank": use system clipboard for yank operations
+ // "always": use system clipboard when no register is specified
+ // "never": don't use system clipboard unless "+ or "* is specified
+ // "on_yank": use system clipboard for yank operations when no register is specified
"use_system_clipboard": "always",
// Lets `f` and `t` motions extend across multiple lines
"use_multiline_find": true