免责声明: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!