NeoVim の job control API メモ

次世代の Vim をコミュニティベースで開発していくプロジェクトとして発足した NeoVim について,あまりキャッチアップできていなかったので少し試してみたメモ.

インストール

  1. make deps で依存しているライブラリのビルド
  2. cmake でビルド用 Makefile 生成
  3. make install でビルド&インストール

という流れっぽい.Mac だと Homebrew 用の neovim.rb が添付されているので,それを使えば良い.brew tap しても良いけれど,おそらく neovim リポジトリ全体を clone してきてしまうので,neovim.rb を適当にコピーしてきて brew install ./neovim.rb --HEAD とかで入れるのが良さそう.

起動

コマンドは nvim .起動してみると ~/.vimrc は読まれず,どうやら ~/.nvimrc が必要らしい.動かない部分もあるけれど,Vim としては割りと普通に動く.

job control API

NeoVim のステータスを見ると,どうやら別プロセスを起動してそのプロセスとやりとりする job control API が既に実装済みとのことだったので試してみる. この APIVim 本家の vim_dev のほうで議論されていた job API のパッチを改善する形で NeoVim に実装されているっぽい.

jobstart()

jobstart({tag}, {shell command}, {arguments for shell command})

第1引数で,その job の識別用のタグを与える.第2引数で別プロセスで実行するシェルコマンドを指定し,引数を付けたい場合は第3引数で文字列のリストで指定する. 戻り値は job 固有の id (整数値).

jobstop()

jobstop({id})

id を指定してジョブを終了する.

jobwrite()

jobwrite({id}, {str})

第1引数で指定した job の stdin へ第2引数で指定した文字列を入力する.

JobActivity autocmd イベント

autocmd JobActivity {tag pattern} {command}

起動した子プロセスからの出力を,JobActivity イベントで受け取ることが出来る.{tag pattern} には出力を受け取る job のタグのパターンを指定できる.(e.g. * ならすべての job の出力を受け取る)

v:job_data

JobActivity イベント時に子プロセスの出力が入っている変数.3要素のリストで,第1要素には job の id,第2要素にはどの出力か(stdoutstderr),第3要素には出力の中身がそれぞれ入る.

サンプルスクリプト

試しに下のようなスクリプトを書いて :source で実行してみる

let g:id = jobstart('top-command-1',  'ping',  ['localhost'])
autocmd JobActivity top-command-* call append(line('$'), 'from server: ' . string(v:job_data))

現在のバッファに localhost への ping の出力が毎秒ごとに書き込まれる.call jobstop(g:id) で終了できる.

  • 出力例
from server: [1, 'stdout', 'PING localhost (127.0.0.1): 56 data bytes64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.086 ms']
from server: [1, 'stdout', '64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.164 ms']
from server: [1, 'stdout', '64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.174 ms']
from server: [1, 'stdout', '64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.133 ms']
from server: [1, 'stdout', '64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.143 ms']
from server: [1, 'exit']

感想

グローバルな設定値である updatetime をいじってタイマーに使っている現状よりは遥かに良いけれど,まだ色々機能が足りていないっぽい(例えば起動中の job 一覧を表示する関数とか).