首发于Vim

Vim 内置终端调教记

周末有空,写篇短文帮大家提高 vim/nvim 中的工作效率。

Vim/NeoVim 的内置终端都发布了差不多两年了,但是大家还是习惯用 vim+tmux 的组合,宁肯在 tmux 里分割 split 也不肯使用 vim 的内置终端?

有没有办法让内嵌终端变得更好用一些呢?让它真的能帮到我们优化自己的工作流,提高操作的效率呢?学习了一圈 emacs / vscode 等编辑器的内嵌终端,我写了个 200 行的小脚本,对 vim/nvim 的内嵌终端进行一些简单的调教:vim-terminal-help

这个小脚本对三个小地方进行了一些改进:

第一:提供一个 ALT+= 的快捷键可以像 vscode 的 CTRL+backtick 一样用来打开/关闭终端窗口,不用每次输入 :terminal ,同时新终端会把 shell 的工作目录初始化成你上面正在编辑的文件所在的目录,因为你大部分时候临时想搞点什么一般都是针对你当前正在编辑的文件来操作,那么初始化成当前文件的目录就避免了你每次打开终端再 cd 一半天:

按 ALT+= 在正下方打开终端,路径自动帮你定位到上面文件所在目录

所以工作流程就是你编辑着当前文档,突然想搞点啥然后 ALT+= 在正下方打开终端,敲几行命令,运行完了就再 ALT+= 把它收起来,整个流程十分顺畅。多次 ALT+= 不会无止境的打开新终端,只会复用已有的,而如果你再终端里输入了 exit 结束了 shell 进程,那么再次按 ALT+= 才会创建一个新的终端。

第二:初始化了一组快捷键 ALT+SHIFT+hjkl 用来在终端窗口和其他窗口之间跳转,很多 vim 用户过去都习惯设置 CTRL+hjkl 来做窗口跳转,普通窗口没问题,但是终端窗口下面,CTRL+hjkl 本身就是各种终端程序高频使用的组合键,你外面 tnoremap 覆盖掉了,里面你想运行个 fzf 都没有办法用 CTRL+j/k 在 fzf 里面上下移动光标了。因此这个小脚本鼓励大家使用新的 ALT+SHIFT+hjkl 来做窗口切换,这几个键在终端内相对用的少一些。

第三:在终端内提供一个名叫 drop 的命令,当你在终端中突然想编辑某个文件,直接 drop xxx 命令就能通知到外层的 vim 来打开该文件了,因为 vim 的当前目录和终端内 shell 的当前目录经常不一致,你在内嵌终端里 cd 到了 xcode 种很深的一层目录,这时想让外层的 vim 打开一个文件有多麻烦?先要切换会终端的 normal 模式去,然后在 vim 种输入常常的::e .... 后面接长长的一串路径名(因为二者当前路径不同)。所以这个 drop 命令(兼容 win/linux, vim/neovim)存在的意义就是让你能在终端内以最快捷的方式让 vim 打开一个文件。

--

我平时会用 vscode 来编辑 markdown,vscode 的 CTRL+backtick 切换内嵌终端的功能确实很顺手,我用的很多,用来运行命令行工具编译/发布 markdown。而同样终端下的 emacs 的用户也基本都在用内置的各种终端,而很少用外面的 tmux。 所以从道理上来讲 vim/nvim 的内嵌终端应该是可以更好用一点的,不至于像现在这样很少被人用。

就像苹果的 airpod 耳机,其实无线耳机技术上并没有什么新的东西,其他品牌的无线耳机好多年前就有了,但是用的人真的不多,而 airpod 做的其实也很简单,就是持续在不同的细节地方改进用户体验,然后把续航时间大大增长,最终量变积累形程质变,今天 airpod 如此受人欢迎。基于前面的经验,我想,或许,我们可以通过改进内置终端的各处体验,最终真的让他真的变得好用,变得能够帮到大家。

我自己用了一段时间后发现,当然不能完替 tmux 操作,但代替了不少之前需要 vim+tmux 协同的工作,的确感觉到比以前的方便。就像以前我在 Windows 下从来不用 GVim 内置终端的,现在也开始用了,比如正在写 python 代码,发现需要安装个包,以前是要打开 windows 菜单,然后运行 cmd ,然后再 pip install,打断太多了。现在同样的事情我就倾向于 ALT+= 打开内置终端(我配置的是 powershell),然后 pip install 一个包,完事就 ALT+= 收起来,比以前顺畅太多,全键盘操作,工作流根本不会中断。

所以用了一段时间,又根据朋友的反馈做了一些调整优化,归纳成个小脚本共享出来。

skywind3000/vim-terminal-help

--

补充:评论区说不知道内置终端如何滚屏,原来很多人还不知道内置终端也分 normal/insert 两种模式,正常终端操作,输入文字是 insert 模式,在 insert 模式中按 <c-\><c-N> 就可以切换到终端 normal 模式了,然后你可以像 vim buffer 一样正常的 hjkl 漫游,正常的滚屏,复制内容。弄完了以后再按 i/a 回到 insert 模式中接着输入终端命令。

另外从 vim 寄存器到 终端粘贴内容的操作因为 vim/nvim 不一样,vim 的终端粘贴是在终端 insert 模式下按 termkey + " + 寄存器 ,termkey 在这个脚本里是 <c-_> ,而 neovim 的终端是可以直接在 normal 模式下像普通 vim buffer 一样粘贴。

觉得有点麻烦?没关系啊,自定义按键即可,内嵌终端最方面的就是可以用 tnoremap 修改按键,比如你嫌弃 <c-\><c-n> 切换 normal 模式麻烦,你大可以定义成 ALT+q:

tnoremap <m-q> <c-\><c-n>

当心覆盖了内部软件的常用快捷键的话,可以改成 ALT+SHIFT+q:

tnoremap <m-Q> <c-\><c-n>

为了方便,所以最新版的脚本中我增加了一个 ALT+- 的映射,可以让你再终端里按 ALT 和减号就粘贴 0 号寄存器了,vim/nvim 兼容。

编辑于 2020-01-11

文章被以下专栏收录

    写一些从想法到脚本实现的详细过程,我希望更多的用户可以自己写脚本