给 Vim 插件添加上异步调用的功能
条评论一些 Vim 插件可能因为计算密集或者是访问网络资源导致命令调用特别慢, 进而导致 Vim 的操作界面被 hang 住, 时不时地 hang 一下还是很影响流畅度和编码心情的 ):
还好在 neovim/vim8 中添加了对异步调用的支持, 我们可以利用 job 机制让耗时的操作在后台执行, 然后通过 callback 机制把处理结束后的结果输出. 加上异步操作后, 各种操作都如丝般润滑, 再也不用担心卡顿了 (:
下面我就以插件 vim-youdao-translater 为例来介绍如何给插件添加上异步调用的功能.
vim-youdao-translater 介绍
这个插件是可以在 Vim 中调用有道词典在线版来翻译英文单词, 官方 repo 库 中有详细的使用介绍.
但这个插件最开始不是异步调用方式, 因为需要访问有道的网络 api , 经常会在翻译的时候会出现卡顿的情况. 我便提交了 Pull Request , 在 neovim/vim8 里把翻译过程变成了异步调用. 可以通过 vim-plug 的方式安装异步调用的版本:
Plug 'https://github.com/ianva/vim-youdao-translater.git', {'branch': 'dev-async'} |
安装完成后我们便可以通过 :Ydc
翻译光标所在位置的单词了.
如何添加异步调用
我添加的这个异步调用是通过 neovim/vim8 的 job 机制来实现的, 它的功能和 system
函数类似, 用来执行外部程序, 但不同于 system
调用, 使用 job 执行程序的时候不会等待程序结束时再返回, 而是直接返回, 同时可以在启动 job 的时候增加回调函数来处理外部程序执行的结果.
启动 job 的函数为 jobstart
(neovim) 或 job_start
(vim8), 可以通过 :help jobstart(
或 :help job_start(
来查看它们的详细使用文档.
具体到 youdao-translater 这个插件, 我们需要通过 jobstart 等来执行一个 python 脚本以执行翻译的操作. 先上代码吧:
let s:translator_file = expand('<sfile>:p:h') . "/../youdao.py" |
这里调用 jobstart
的时候是用面向对象的方式来写的, s:translator.on_stdout
是对 stdout 内容的回调函数, 可以看出我们只是简单地调用 echo
把 python 脚本输出的翻译结果打印了出来.
调用 job_start
时的工作机制类似, 只不过是使用了不同的回调函数, 因为 neovim he vim8 的回调函数的参数是不一样的. 函数 ydt#VimOutCallback
的实现如下所示:
function! ydt#VimOutCallback(chan, msg) |
这里函数之所以起了这样一个名字, 是因为用到了 vim 的 autoload 机制, 上面的函数是保存在文件 autoload/ydt.vim
中的, 所以函数名需要以 ydt#
开头.
Vim 的 autoload 机制可以提高 Vim 的启动速度, 因为 autoload 目录下的脚本不会在启动时被加载, 它们只有在有关函数被用到时才会找到对应的文件, 然后把整个文件都加载进来.
当实现了上面的异步调用接口之后, 我们便可以实现对应的函数调用和命令了:
function! s:YoudaoCursorTranslate() |
- 本文链接:https://hiberabyss.github.io/2018/05/03/add-async-support-for-vim-plugin/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!