原文出处: Elliot Williams 译文出处:明明如月
文本编辑编程
Vim的神秘之处在于它普通模式时使用一种介于自然语言和编程语言中间的语言。
它包含动词(方法)、形容词(修饰语)、和名词(对象)。输入c命令代表“编辑”某些文本。但是仅仅输入一个c不起作用,因为它还需要一个对象。但如果你输入caw(“修改一个单词”),光标所选中的单词将被删除,Vim进入插入模式,等待你键入单词的替换词,通过按Esc键(退出键)就可以返回普通模式。如果你想编辑整句,输入cas来删除它然后然后输入新句子即可。想改变C函数括号内的所有参数吗?ci)“改变括号内的内容”. (ca)删除整体,括号和所有。数字也同样适用。通过c5w命令可以修改后面的5个单词。就Vim的语法是模块化且可拓展的角度而言,它还是挺容易学的。
以上那些只是雕虫小技。.命令才是亮点。编辑动作的阶段性重复构成了一个单元。所以如果你仅仅想把一个单词改为“Hackaday”后返回到普通模式,就把光标移动到那个单词上键入cawHackaday后再按.键就可将其修改为“Hackaday”。将移动命令也加入其中,w命令将光标移动到下一个单词的开头。现在如果交换.和w那么文档中所有单词都会变成“Hackaday”。只需要按两个键。试想一下如果杰克·尼克尔逊在《闪灵》中用Vim和.命令写作,那该多高效啊。
虽然听起来好像不是特别实用,但是想想有多少次你需要把所有“foo()”方法替换为“getFooInstantanceMethod()”方法就不难理解了。
当然了在Vim中那只是很“普通”的搜索和替换方法,但是其实大多数情况下你没必要那样做。为啥呢?因为/foo搜索“foo”而且caw将修改光标选中的单词。
通过;可以实现搜索的可重复性。在搜索和替换部分(几乎)同时是任意编辑动作的情况下,交替使用; 和.与搜索和替换是等价的。
不需要输入“y”和“n”来对每个匹配的单词进行修改确认,你只需要找到需要的地方输入.即可。
关于vim的讨论非常热闹,以至于在 StackOverflow上,它已经成为一个经典的热门话题,在另一方面,文本编辑经常视为一贯重复性行为。Vim却将这些动作作为单一的单元,使得复现和将它们链接在一起非常容易。如果你是一个程序员,这很像编程里的活动 — 将整个任务拆分成多个方法并运行。如果你理解编程,你就更容易理解Vim。
可视模式和命令模式
在你通往精通Vim的路上,你会接触到更多模式。可视模式下你可以先选择文本的区域然后再使用命令来操作它。偶尔用用挺好的,因为可视模式下选择区域很难转换成普通方法,所以不要像我学习的时候那样用的那么频繁。然而有很多针对可视模式有用的插件。
命令模式是Vim的主要模式。它本质上像ed这种原始的行编辑器。:17,25d在不移动鼠标情况下删除17到25行。:-3t.复制当行的前面三行。:v/foobar/s/thang/thing/g 将不含有“foobar”的文档里所有“thang”替换为 “foobar”。在这里你也可以使用所有存储的正则表达式。
另外,如全局搜索、替换、删除或者复制整行文字这样的简单的操作在命令行下非常容易。%s/one/two/gc把所有的“one”替换成 “two”,每个搜索和替换需要用户确认。(%代表整篇文章。这里你也可以使用行数范围。当然:e命令功能是打开一个文件编辑, :wq 的功能是保存当前文件并退出。你不需要记住太多的命令行模式的命令,但是有些命令超实用。
寄存器和宏
接下来将介绍寄存器。像编程语言的变量那样,Vim 在寄存器中存储文本(或命令)。你可以从寄存器剪切或者粘贴数据,前十个主要是一个剪切缓冲区。寄存器是存储你剪切但不确定是否扔掉的文本的好地方。“zdi} 将删除所有方法括号内的所有代码,保存在“z”寄存器中。你可以在任何时候通过“zp将其粘贴回来。
你也可以像宏一样记录和回放寄存器中的Vim的命令序列。毕竟Vim命令大多数情况下都仅仅是文字。q用来开始和停止宏的录制,qw将一个宏录制到“w”寄存器中。
在此之后你可以用@w来重复运行。宏像其编写者那样强大。我只用一些宏,但是只要我用过的都会频繁使用。
例如,有一个宏我一天用无数次。我用Markdown写Hackaday文章然后将其编译成HTML语言发表。在Markdown中超链接的用法类似这样:[link text]( https://www.example.com )。
S]f]a(“+pa)用“[]”将当前选中的文本括在里面。添加一个左圆括号,退出插入模式,粘贴粘贴板中的内容,添加一个右圆括号,返回到普通模式。但是现在,我复制浏览器中一个超链接,选择文本然后在Vim中键入@l 这样获得了链接到该网址的Markdown超链接。
插件
想其他任何的编辑器一样,Vim也拥有难以置信的可拓展性。如果有任何不能制作成宏的特性,用户通常都可以为此编写插件。依我看来,Vimscript 没Lisp那样好编写,所以我就把拓展的编写留个其他用户吧。有人已经写了一个几乎你所需的所有模块。但是在刚开始的时候不要过度使用插件。即使你是刚学习Vim,它也会使你的工作量减轻很多。
如果你经不住诱惑安装了一些插件,我建议你一次只装一个,直到能给非常熟练的使用后再安装另外的插件。我建议依次安装和学习如下插件:vim-sensible, vim-airline, vim-abolish, ctrlp.vim, UltiSnips, vim-surround, vim-easy-align。
VIM最佳命令
如果你在用Vim,但是没充分使用如下的命令,说明你还没用好它。
l I和 A 分别插入文本到行首或尾部。
l m设置标记然后通过“`就可以跳回到此标记位置。 这对轻松在长篇文章中跳转非常有效。
l g; 跳转到上次编辑位置。就是说“在去其他地方之前,先返回之前编辑的地方”。这非常有用。但这还不是全部–它追踪编辑历史以便可以复现前5此编辑。g,返回前一个编辑历史。
l CTRL-] 跳转到鼠标所在函数的定义位置,CTRL-t跳回。CTRL-t可以使你会一直返回,直到返回到开始位置。(为了使其生效你需要一个标签文件。) 这几乎达到像eclipse这种IDE价值的一半,却没他们那样造成屏幕凌乱。
l 一个IDE的另外一半是长变量或者方法名的tab完成功能。在Vim中用CTRL-n和 CTRL-p 来预选列表中上滚和下滚。如果你使用的是标签文件或者如果你在Vim中其他文件定义了标签,它将对变量名和方法名自动完成。
l gg=G跳转到文档顶部(gg) 自动缩进(=) 直到到达文档末尾 (G)。这使得你打开和关闭的大括号排成一行,很容易找到你忘记配对的大括号。
l U撤销最后一个命令。CTRL-r重做。:earlier 2m 恢复到两分钟前的状态。如果你不再进行撤销,继续编辑然后想重做之前的一些改动,就可以考虑用这个命令。g+ 和g- 则在恢复树种上下切换。它变得更加复杂。
l /和f 都是搜索命令,这两个命令在符合命令中起着至关重要的作用。df,从当前光标位置上的字符一直删除到遇到逗号(包括逗号)。d/foo 一直删除直到第一次匹配“foo”的位置。如果你喜欢,你可以用这来代替其他动作。
l :r 读取一个文件。:!在shell中运行命令。:r! 粘贴命令的结果输出到文档中。:r!ls whatever*比输入文件名更快。在此我并不打算介绍UNIXy中怎样通过shell脚本运行文本。
无处不在的VI
一旦你习惯于Vim的移动命令,你会乐在其中。当然了你也可以直接使用鼠标,但如果你能熟练使用Vim移动命令,你将很少用鼠标了。手一直在键盘上比时不时腾出手来操作鼠标操作要会更快很多。铁杆Vim用户会重新映射Escape 键(返回到普通模式)到其他更加方便的功能。我设置的是 Caps Lock键,在我左手小手指下面。
(我其实是通过xcapse插件映射它和Control键复合键使用。)
是的,这确实有点极端,但是比 现在已经不存在的避免Emacs导致腕管综合征的键盘设计 强多了。
如果你在Unix使用Bash shell,set -o vi 这种用法来读取行的方法几乎和vi一样。你的浏览器也可以Vim化,火狐浏览器、cVim或vimium中有Vimperator 和Pentadactyl 插件。谷歌浏览器中有ViChrome插件 。如果你想合二为一,qutebrowser是目前最好的原生Vim风格网页浏览器,而且还将会更加完善。
你若搜索 “vi keybindings”你会发现它不仅支持Visual Studio、Eclipse 还支持Emacs。
为什么Emacs里有Vi模拟模式,但Vim中却没Emacs的模拟模式呢?
稍加思索你就会明白,编辑器之战已经有了结果。
想用惯Vim需要花费一些时日。程序员想要擅长Vim,需要要摆正心态勤加练习。从1994到20011年间我用Emacs写代码、写我的学位论文、我所代课的学生的论文和学术论文。从2011年起我就开始用Vim来编写更多代码、写书、写邮件和我在Hackaday上的文章。
我仍然在不断提高,五六年间每天使用Vim 6到8小时,每月将自己总结的技巧写在指令表中。虽然Vim像任何值其他值得深入探索的东西一样,用起来有点难,但是却非常值得。不要轻信任何人告诉你他们“懂”Vim。:wq.
资源
There’s really too much to say about Vim. Here’s a short list of great resources:
关于Vim要说的实在是太多了,这里提供一些相关极有价值的参考资源:
如果你刚开始用输入 :help tutor