在visual mode下d和x的区别

为什么我按d和x的效果都是cut? 我想要的是按d就是删除,没有复制的功能。

Vim 的正常行为 d 就是剪切,x 才是删除。

但我用的spacemacs的visual mode好像不是这样的,d和x都是剪切。

自己改改呗,反正也不麻烦。

确实,d 和 x 效果都是一样的。不过说到“剪切”,它在 normal mode 下也是“剪切”啊。你咋就没疑问呢?

事实上,Vim、Emacs 等上古编辑器对于“删除”操作都是淡化处理的,尤其是整行、整段的“删除”,它默认你的数据都是很宝贝的。如果你只是不小心输错字母,想“真正删除”,那按退格键就好了嘛。

所以,当按 d 或 x 的时候,除非你明确告诉编辑器要彻底抛弃这段文本,否则“删除”的文本只是被放到默认剪贴板/寄存器。怎么告诉它你要彻底抛弃文本?使用 "_d 命令,"_ 表示援引“黑洞”寄存器。想了解更多寄存器,自己搜索一下相关知识。

学习到了,多谢!

也可以自己脑袋里计数器记好了,我要贴的那段,是在n次删除之前删的,然后用n+1号寄存器把它贴出来。这样手上速度快了,但是脑袋负担很大 :cry:

没事记这个干啥…… Vim 下有个插件 YankRing,默认保存 100 条记录,重启后记录也还在。

那样还要调个小窗口出来选一下吧,会慢一点点,不过要是用helm/ivy筛选一下应该还不错,咦然后evil的registers底层就是kill ring吧,那我是不是该试试下次用ivy-killring啥的来粘贴【发现了新大陆】

emacs 下我记得有个 helm killring,搜索历史记录然后粘贴什么的。那段折腾 spacemacs 的日子里我用的就是这个。

删掉 Evil,皈依原生 Emacs 吧

这两个键不区分 normal/visual,绑定的方法不变:

 x  evil-delete-char
 d  evil-delete

再看 evil-delete-char 的定义:

(evil-define-operator evil-delete-char (beg end type register)
  "Delete next character."
  :motion evil-forward-char
  (interactive "<R><x>")
  (evil-delete beg end type register))

就是 evil-delete 的一个特例嘛。所以这两个键都是删除,区别在于删除的范围不同,visual 只不过是把删除范围可视化了。

在 vi 的世界,删除的内容都要放到 " 寄存器,而 " 寄存器正是你下次粘贴的来源,这就是你的困扰。

你可以重载 evil-delete-char/evil-delete-char 来改变这个行为,把删除内容丢掉,或者放到一个不常用的寄存器。

vim 下默认寄存器是 +*" 则表示“引用”某寄存器。

另外,vim 还有一堆普通寄存器:a, b, c, d … 1, 2, 3… 等。

以及一些特殊寄存器,比如 / 表示上一个搜索字符串,: 上一个执行的命令,_ “黑洞”寄存器 …… 等等。

应用举例:"ayy 把当前行复制到 a 寄存器(而不是默认的 + 寄存器),"bpb 寄存器的内容粘贴出来。这些寄存器的值都可以输入 :registers 命令查看。

" 确实表示“引用”某寄存器,当 " 表示“引用”的的时候,只有 Normal 模式(vim的模式)才对应的是"键,在其它模式下对应 C-r(在屏幕上表现形式为 ")。也就是不管 Vim 在什么模式,想要使用寄存器,必须先按出那个不是 " 字符的 " 作为前缀:

Vim 模式   按键
--------  ---------------------------------------
NORMAL    "{register_name}
COMMAND   <C-r>{register_name}
INSERT    <C-r>{register_name}

" 也确实是寄存器名,可以通过 :reg " 查看其内容。但是这个名字很奇怪,叫做无名寄存器(unnamed register),就像小时候老觉得有个叫“佚名”的人很厉害,说了很多名言警句、写了很多书。实际上这个无名更厉害一些,因为不管删除/复制有没有指定寄存器名,内容都会到 ":

步骤↓    释义
------  ----------------------------------------
"ayy    复制当前行到寄存器 a
:reg a  查看寄存器 a 的内容
:reg "  查看寄存器 " 的内容(跟寄存器 a 的内容一致)

* 这两个寄存器是用来跟系统剪切板共享数据的:

"+p   粘贴系统剪贴板的内内容

有些效果可能在 evil-mode 体现不出来,可以到 vim 上验证。

刚翻了下 Vim 手册,发现寄存器总共被划分为 10 种!:open_mouth: 不过一直以来我对它的简化理解(普通寄存器和特殊寄存器),其实倒也没什么大问题。

通常 " 指的是引用,不过 " 本身也是一种特殊寄存器,其内容总是与最后一个被操作过的寄存器相同。譬如:"ayy 复制当前行到 a,然后""p ,把最近一次更新过的寄存器( a )的内容粘贴出来。

需要说明的是,如果你的 Vim 没有编译 clipboard 选项," 会被当作默认寄存器。这时 Vim 内部的绝大部分操作包括删除、复制等都要经过 " 寄存器。不过一般我们并不直接引用它,直接按 p 就可以了嘛。从这点上来说," 寄存器可是低调地默默幕后工作的大功臣。除非你像上面例子一样,把重要数据放到某寄存器,然后忘了寄存器叫什么名字来着?

而如果需要与系统剪切板共享数据,则是通过 +* 寄存器。譬如从网页上复制一段文字, +* 的内容已更新,"寄存器还是保持原样。

至于寄存器的其它知识, @twlz0ne 说的比较完整,我就不再重复了。