vim server 入門
vim server mode
あまり知られてないのですが、vim には server として動作し、外部から入力を受けるモードが存在します。純粋なエディタとしてだけではなく、外部からの指示で特定のファイルを開いたり、用意してる関数を実行したりってことが出来るのです。
僕も今までまったく使った事がなくて、vimscriptを単体のファイルとして実行したいなと漠然と調べていた際に見つけました。有効活用してる例ってあるのかな。。
下ごしらえ
vim server を使用するためには、そのバイナリが +clientserver というフラグ付きでconfigureされている必要があります。そして多くの場合この機能はデフォルトではありません。コンパイルオプションを調べるにはvimの起動後に
:version
でずらっと表示されます。
:version VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Nov 11 2008 17:20:43) Included patches: 1-22 Compiled by _www@b77.apple.com Normal version without GUI. Features included (+) or not (-): -arabic +autocmd -balloon_eval -browse +builtin_terms +byte_offset +cindent -clientserver -clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments +cryptv +cscope +cursorshape +dialog_con +diff +digraphs -dnd -ebcdic -emacs_tags +eval +ex_extra +extra_search -farsi +file_in_path +find_in_path +float +folding -footer +fork() -gettext -hangul_input +iconv +insert_expand +jumplist -keymap -langmap +libcall +linebreak +lispindent +listcmds +localmap +menu +mksession +modify_fname +mouse -mouseshape -mouse_dec -mouse_gpm -mouse_jsbterm -mouse_netterm -mouse_sysmouse +mouse_xterm +multi_byte +multi_lang -mzscheme -netbeans_intg -osfiletype +path_extra -perl +postscript +printer -profile -python +quickfix +reltime -rightleft -ruby +scrollbind -signs +smartindent -sniff +statusline -sun_workshop +syntax +tag_binary +tag_old_static -tag_any_white -tcl +terminfo +termresponse +textobjects +title -toolbar +user_commands +vertsplit +virtualedit +visual +visualextra +viminfo +vreplace +wildignore +wildmenu +windows +writebackup -X11 -xfontset -xim -xsmp -xterm_clipboard -xterm_save system vimrc file: "$VIM/vimrc" user vimrc file: "$HOME/.vimrc" user exrc file: "$HOME/.exrc" fall-back for $VIM: "/usr/share/vim" Compilation: gcc -c -I. -D_FORTIFY_SOURCE=0 -Iproto -DHAVE_CONFIG_H -arch i386 -arch ppc -g -Os -pipe -mdynamic-no-pic -arch i386 -arch ppc -pipe Linking: gcc -arch i386 -arch ppc -o vim -lm -lncurses -liconv
このように -clientserver と出た場合には vim server 関連の機能が組み込まれていないので、コンパイルし直す必要があります。最新版のソースを取ってきてconfigure にはお好みのもの(--enable-multibyteとか)を入れつつ、+clientserver を付けます。
$ wget ftp://ftp.vim.org/pub/vim/unix/vim-7.2.tar.bz2 $ tar jxvf vim-7.2.tar.bz2 $ cd vim72/ $ ./configure +clientserver $ make $ make install
基本的な使い方
起動
まずはサーバを立ち上げます。方法は簡単で、そのサーバを識別する文字列を付けてvimを起動するだけです。
$ vim --servername FOO
これで FOO という名前で認識されるサーバが立ち上がります。とはいえ見た目には普通にvimが立ち上がったように見えますが、
:echo v:servername
とするとFOOと表示され、servernameとして設定されていることがわかります。
このservernameはちょっと注意が必要な点があり、与えた名前が upper case に変換される(foo, Foo, FoO のどれでもFOOになる)という点と、同じ名前で2個立ち上げようとすると、2個めはFOO2となる点です。特に後者は結構直感に反する動きな気もしなくはないですね。
以下のコマンドで起動中のサーバ一覧を得る事が出来ます。
$ vim --serverlist FOO
--remote
このFOOサーバに何か仕事をさせるにはいくつかの方法があり、例えば特定のファイルを開かせる場合には --remote を使用します。
$ perl -v > /tmp/perl.txt $ vim --servername FOO --remote /tmp/perl.txt
こうすると、すでに起動中のvim(FOO)の中にいきなり/tmp/perl.txtが開かれます。なかなかテキストだと伝わりにくいのですが、特定のttyに開かれたvimの内部状態を外側から変更するっていうのは見た目にキャッチーです。
ここで --remote の代わりに --remote-wait を使用すると、開いたファイルが展開されているバッファがなくなるまで(:q とか :bd とか)クライアント側は待つようになります。
--remote-expr
また、ファイルを開くだけでなく、--remote-expr を使うと特定の式を送り込んで、その評価結果をstdoutから受け取ることが出来ます。
たとえばさっきファイルを送り込んだサーバから特定の行を取り出したりする場合は以下のような感じです。
$ vim --servername FOO --remote-expr 'getline(6,9)' Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit. Complete documentation for Perl, including FAQ lists, should be found on
計算も出来ちゃいます。
$ vim --servername FOO --remote-expr '60 * 60 * 24' 86400
--remote-send
vim の通常コマンドやvimscript関数の実行等を行う事も出来ます。--remote-send でコマンドをそのまま送りつけます。
例えば立ち上げたFOOサーバを終了させる時は以下のようにします。
$ vim --servername FOO --remote-send '<C-\><C-N>:q!<CR>'
ただしこの場合実行結果の出力を受け取る事はできません。vimscript内でechoしたとしてもそれはstdoutに出る訳ではないのです。
VimRemote::Agent
というわけで、これを使って色々な事をやってみようと思っていて、--remote-* みたいなコマンドをつらつら書くのも大変なので、Perlのコマンドwrapperを書いてみました。
こんな感じで使えます。
use VimRemote::Agent; my $agent = VimRemote::Agent->new(); # check compile option if (!$agent->has('clientserver')) { die "configure vim with +clientserver flag"; } # get running server list my @server_name = $agent->serverlist(); # start new server my $server_name = 'NEWSVR'; if (!$agent->start_server($server_name)) { die "starting server $server_name failed."; } # calc on remote server my $result = $agent->remote_expr($server_name, '1 + 1'); print $result; # 2 # send ex command to remote server $agent->remote_send('e /tmp/hoge.txt'); # shutdown server $agent->shutdown_server($server_name);
git repo:
http://github.com/bonar/vimremote-agent/tree/master
中身はvimコマンドを叩きまくっているのをそれっぽく見せてるだけなので、無理矢理感が隠しきれてない感じになっています。
注意点
- 実装されていないコマンド(*-wait, *-tab 系)がたくさんあります
- -t な環境で make test すると gvim が一杯立ち上がります
- mac os x 以外の環境でtestしてないので多分通らないです
本当はXSでかっこ良く操作したかったのですが、if_xcmdsrv.c とかを観た感じちょっと僕の実力では難しそうですね。。OS毎に実装も違うだろうし。。
まとめ
エラそうに書きましたが、基本 :help remote に全部書いてあります。どういう局面で役に立つのか、それが一番悩ましいのですが、
- IRCサーバとかが作れる
- システムログとかをvim server に送るようにして、みんなでそれを共有できる
- vnewして右側がlogtailになっている的なものとか
- 頑張れば遠隔操作とかが出来るようになって、外科手術をみんなで観る的な公開コーディングが出来るかも
みたいな夢が広がります。なんでそれをvimで、っていうのは、言わない約束じゃないですか。