Vim

使用外部程序和过滤器

免责声明:VIM 是单线程的,因此在 VIM 中以前端进程执行其它的程序时会阻止其它的一切。当然你可以使用 VIM 程序接口,如 Lua,并且使用它的多线程支持,但是在那期间, VIM 的处理还是被阻止了。Neovim 添加了任务 API 解决了此问题。

(据说 Bram 正在考虑在 VIM 中也添加任务控制。如果你使用了较新版本的的 VIM ,可以看一下 :helpgrep startjob。)

使用 :! 启动一个新任务。如果你想列出当前工作目录下的所有文件,可以使用 :!ls。 用 | 来将结果通过管道重定向,如::!ls -l | sort | tail -n5

没有使用范围时(译者注:范围就是 :! 之间的内容,. 表示当前行,+4 表示向下偏移 4 行,$ 表示最末行等,多行时用 , 将它们分开,如 .,$ 表示从当前行到末行),:! 会显示在一个可滚动的窗口中(译者注:在 GVim 和在终端里运行的结果稍有不同)。相反的,如果指定了范围,这些行会被过滤。这意味着它们会通过管道被重定向到过滤程序的 stdin,在处理后再通过过滤程序的 stdout 输出,用输出结果替换范围内的文本。例如:为接下来的 5 行文本添加行号,可以使用:

:.,+4!nl -ba -w1 -s' '

由于手动添加范围很麻烦, VIM 提供了一些辅助方法以方便的添加范围。如果需要经常带着范围的话,你可以在可见模式中先选择,然后再按 : (译者注:选中后再按 ! 更方便)。还可以使用 ! 来取用一个 motion 的范围,如 !ipsort (译者注:原文为 !ip!sort ,但经过实验发现该命令执行报错,可能是因为 VIM 版本的原因造成的,新版本使用 ip 选择当前段落后自动在命令后添加了 ! ,按照作者的写法来看,可能之前的版本没有自动添加 ! )可以将当前段落的所有行按字母表顺序进行排序。

一个使用过滤器比较好的案例是Go 语言。它的缩进语法非常个性,甚至还专门提供了一个名为 gofmt 的过滤器来对 Go 语言的源文件进行正确的缩进。Go 语言的插件通常会提供一个名为 :Fmt 的函数,这个函数就是执行了 :%!gofmt 来对整个文件进行缩进。

人们常用 :r !prog 将 prog 程序的插入放到当前行的下面,这对于脚本来说是很不错的选择,但是在使用的过程中我发现 !!ls 更加方便,它会用输出结果替换当前行的内容。(译者注:前面命令中的 prog 只是个占位符,在实际使用中需要替换成其它的程序,如 :r !ls,这就与后面的 !!ls 相对应了,两者唯一的不同是第一个命令不会覆盖当前行内容,但是第二个命令会)

帮助文档:

:h filter
:h :read!