いかにしてぼくがnvimを使うようになったか。また、現在のNeovimの様子
前半は、詩です。
Neovim情報がお求めでしたら下から読みましょう。
その昔
自分のGitHubのプロフィールを参考にするとJoined on Jan 10, 2014
とあるので、その頃からプログラミングを始めたらしい。
github.com/zchee
それまでの10年ぐらいはWindowsだったのもあって、コードは書いたことがなかった。ブラウジングのみの生活。
その後、WordPressのテーマをひたすらいじくる仕事についたのがきっかけで、ここでMacを初めて使うことになる。
ターミナルなんてものには触ったことがなく、正直人間がGUI以外で何かをすることは異常なのではないか、と思っていた…
初めのエディタは、フロントエンドの皆さんにはおなじみSublime Text。
プラグインが豊富で、エディタのテーマも豊富で、本業のデザイナーがデザインしたAtomからポートされたかの有名なSeti_UI、そのフォークのSeti_UXなどが多くあった。フロントエンド界隈ではちょうど流行っていた時期のはず。
WordPressもだけど、エコシステムすごいぞ!と思いながら使わせていただいてた。
半年後
調子にのって入れすぎたパッケージたちのおかげで、STがとんでもなく重くなってしまった。
補完はおろか文章もまともに打てない。
そして、現在のバッファには必要ないプラグインも読み込んでいることに気づき、VimでいうNeoBundleLazyするプラグインはないのかと探していて見つけたのが
STPackageBundler/package-bundler
setting.jsonを動的に書き換えて、現在のバッファに対応するプラグイン以外を全てignoreするという力技のプラグイン。
しかし開発者vimを使うようになったらしく、開発が止まっていて動かなかった。
Vimなんて使いやがって、とこの時は思ってた。
どうにかして動かしたかったので、ついにHTMLよりはプログラミング言語っぽい、Pythonを触りはじめる。
なんとか直せて初めてのPRを送ってみたところ、開発してないからorgにしてコミット権あげるよと元開発者のchadrien氏に提案されて、改めてOSSを肌で感じた。
https://github.com/STPackageBundler/package-bundler/commits/master
そのあとpackage_control_channelのコミッターにこれエラー吐くよと指摘されたのは内緒。
Railsやりたい
誰にでもある一度はウェブサービス作ってみたい病になり、Rails4を知りRubyを勉強し始めてみる。
Railsやれば仕事には困らないらしいという情報はかなりインパクトあった。
エディタはRubyMineにスイッチする。ついにIDEデビュー
ある程度やってみて、GitHubユーザー認証部分のあたりの実装でつまづき気づいた。
Rubyはなんかすごい黒魔術っぽいぞ…
Octokit、RDoc読んでも全くわからないし…
諦めよう…
巷でGoが流行ってる
このアドベントカレンダーを見てるみなさんはお気づきだと思うが、Goはその3まである。
異常な流行りようである。
C言語を一度も触ったこともないので、おそるおそる適当にコードを見てみると…
すごい読みやすい!なにが起きてるか動かす前に分かる!
なのに超速いらしいぞ!
これはGoやるしかない!
Go!Go!
ちょうど同時期に知った、Dockerを簡単にサーバーにデプロイするDocker Machineがどうにもしっかり動かず、それではと練習を兼ねてPRを少しづつ送り始めた。
ついにVim
Go書くのに公式IDEないことに気づき、IntelliJのGoプラグインも試すもしっくりこないところで、実はGo書くのにVimが一番いいらしいという自分の常識では考えられなかった記事をちらほら見かける。
いや静的言語こそIDEでしょ、と半信半疑でVim界を覗くと…
なるほど、ターミナルと親和性が高くて、簡単にカスタムできて、アイデアを思いついたことに実装できないことはない、という素晴らしい特徴を知り、一気に虜になってしまった。
そして、NeovimというVimをフォークしてモダンに作り直すプロジェクトがあるらしい。
Msgpack-RPCで非同期処理を実現し、ノンブロッキングでユーザーの邪魔をしない。他にも内部にターミナル実装を持ちなんかすごい。やばいかっこいい。
幸いPure Vimを使ったことがないので、NeovimにないVimの実装なんか全然気にならない。
というわけで元のVimを全く知らないでNeovimを使い始めた。
後のVimconfで聞いたら、珍しいパターンとのことだった。
そしてNeovimへ
ちょうどNeovimを使い始めたぐらいに、@Shougoさんが作るRPCを使ったNeovim専用の非同期補完プラグイン、
Shougo/deoplete.nvim
も実用段階になっていたのもあって(ありがたい)、いまのところ自分の思考速度では特にNeovimに不満はない。
ちなみに言語そのものを開発するようになるともはや補完も必要ないらしい。ついにはシンタックスハイライトもいらないらしい。
Hacking with Andrew and Brad: tip.golang.org
https://www.youtube.com/watch?v=1rZ-JorHJEY
なんという速さや…何度見ても感動する
そしてBrad氏が自分も使ってるKINESIS Advantageを使っていることにも感動。
ということで、Go言語デビューを機にVim界にもデビューさせてもらったのでした。
今は
- zchee/docker-machine-driver-xhyve
- xhyve HypervisorをDocker Machineで動かす
- zchee/dispatch
- Apple Grand Central Dispatch binding for Go (Now private)
- zchee/deoplete-go
- deopleteにgocodeの返り値を返す
- zchee/h2o-proxy
- H2Oで自動reverse proxyする
などやってます。
お待たせしましたNeovim関連
現状、なんかすごそうだけど良さが分からない、というのをよく見かけるのでその辺りを。
なお、Vimが劣っているとか、Vimが悪いということではありません。参考程度にご覧下さい。
そしてついこの前Vimを使い始めました関係で、間違いが生じる可能性ありますがご了承を…
Neovimコア実装
msgpack-rpc
https://neovim.io/
にもある程度載っていますが、ユーザーからのNeovimの一番の特徴は、msgpack-rpc
を使った非同期プログラミングがVimでも可能になったという点じゃないでしょうか。
今まではvimproc#system
を呼んだり、YouCompleteMeのようなcppなどでのサーバー実装、あとはvimにもサーバー機能があったでしょうか、とにかく方法が限られていたようです。
しかしmsgpack-rpcを使うことによって、非同期に関数を呼べることはもちろん、バッファなどのNeovimの状態取得、編集などもユーザーに影響を与えずに可能になっています。
大まかにはこんな感じ
https://github.com/neovim/neovim/blob/master/src/nvim/event/queue.c
そして、プラグイン作者はどの言語でもプラグインを書けるようになったのも大きい点で、現在はVimでもよく使われるPythonを使って通信する
neovim/python-client
が主流ですが、他にも
- rogual/neovim-dot-app
- OS X向け、Objective-C++メインのGUI実装
- neovim/node-client
- 公式サポートのNode.jsクライアント
- myitcv/neovim
- Neovimを
--embed
起動によって自身を内包して通信する、Neovimコントリビューターが実装したGo言語クライアント
- Neovimを
など、開発が止まっているものも中にはありますが、クライアントの実装は増えてきています。
https://github.com/neovim/neovim/wiki/Related-projects
ただ、プラグインとしての実装はまだ少なく、
- Shougo/deoplete.nvim
- Pythonで実装された非同期補完。速いです。
- critiqjo/lldb.nvim
- Python実装のLLDBフロントエンド。綺麗です。
- Floobits/floobits-neovim
- Python実装の、リアルタイムコラボレーションプログラミングを代表的なエディタで可能にするNeovim版
- fatih/vim-go
- Neovimが内部に持つ、msgpack不要のjob-control(Libuvで?)を使って、GoTestなど非同期で実行可能になるPR
- benekastah/neomake
- これもjob-controlを使い非同期を実現する、scrooloose/syntastic, tpope/vim-dispatchの代替
などが代表的なものです。まだまだ数が少ない…
しかし、vimscriptは書けなくても、msgpackは完全に把握していて余裕というfluentd界隈の皆さんや、純粋にC++でboostとかstd::thread
使って究極までチューニングできる方々、またはGo言語をも凌駕しC言語に匹敵すると噂のNim、ついにオープンソースになったSwiftなどでVimを操作する…
かなり夢がありませんか。
お仕事で使われてる言語で書けるのです。
と現状プラグインユーザーである側からすると増えて欲しいなという願いも込め、次です。
なおそのうち頑張って絶対なにか作ります。
Built-in terminar emulator
Neovimは内部にターミナルエミュレータを実装しています。
VimShellのように、Neovimの中にターミナルを立ち上げることができます。
Emacs running in Neovim
https://www.youtube.com/watch?v=xZbMVj9XSUo
デモなのでEmacsを起動できて嬉しい点は思いつかないですが、これも使いようによっては強力な機能になりそうな気はします。
とりあえずNeovimからでなくても(終了しなくても)良くなる、というのは普段Vimをそういう使い方をしてる方には良いのでは。
ただこの機能をうまく使ったようなプラグインはあまりなく、
kassio/neoterm
ぐらいでしょうか。
ちなみにたぶんこれを使って実現してます。
neovim/libvterm
Support truecolor and bracketed paste
256色を超え、truecolor、すなわちCSSのようにRGBで色を表現できるようになっています。
ですのでVimのguiと同じく、カラースキームがとても綺麗に細く装飾可能です。
ちょっと脱線。
truecolorは、論議はあるもののOS XとLinuxでは表現可能になっているツールが幾つかあります。
iTermもサポート済みです。詳しくは
https://gist.github.com/XVilka/8346728
をご覧ください。
ただバグがある、のは承知の上でどうぞ。
tmux truecolor
tmuxは現在サポートしていないのですが、可能にするパッチが以前存在していました。
そのパッチが適応できなくなる変更がtmuxに入り、一時期HEADビルドできない時がありました。
そのパッチをどうにか…!と思ってC言語知らないながらも頑張って書き換え、パッチできるようにして公開したのですが、これは後方互換性をなくしてしまうような実装で、安易に公開してしまったことをある方には謝らなくてはなりません…
ともあれ、以前からあったパッチとぼくが書き換えたものをベースに、sunaku氏が後方互換性を保つような形で実装中です。
https://github.com/tmux/tmux/pull/112
tmuxがこの前UTF-8周りに手を入れた事で、そのままビルドすると色がおかしくなりますのでご注意を。
しかしそのUTF-8周りの変更でGRID_FLAG_EXTENDED
フラグが新たに入り、それを使ってくれとnicm氏は言っています。
vim truecolor
vimもtruecolorに対応するフォークがあります。
しかし何が起きても知りません。
https://bitbucket.org/ZyX_I/vim
実装したのはロシアのPythonハッカー、ZyX_I氏。
Neovim, vim, Zsh, powerlineと名だたるプロジェクトのコントリビューターです。NeovimにShadaという実装をしたのもこの方です。
ちなみにYandexに勤めているようです。確かインタビュー記事かなんかありました。
zpython
もう一つZyX_I氏のもので、もうtruecolor関係ないですが、ZshからPythonバイナリを呼ばず、Zsh ModuleとしてPythonをバインディングしたものがあります。
https://bitbucket.org/ZyX_I/zpythonzmodload libzpython
すると、zpython
というコマンドが増えてZshからPython関数をそのまま呼べます。
zpython 'import sys; print(sys.version_info)'# return
sys.version_info(major=3, minor=6, micro=0, releaselevel='alpha', serial=0)
あらかじめZshを自前でビルドする必要があります。
またOS Xでそのままビルドすると、zsh部分でsymbolがないぞとビルドできないので、以下のように-undefined dynamic_lookup
を追加します。Python3系でもビルドできます。PyPyは試してません。
mkdir build &&cd build
LDFLAGS="-undefined dynamic_lookup" cmake .. -DZSH_REPOSITORY="/Users/zchee/src/zsh/zsh" -DPYTHON_INCLUDE_DIR="-I/usr/local/Frameworks/Python.framework/Versions/2.7/include/python2.7" -DPYTHON_LIBRARY="/usr/local/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib"
現行Powerlineではzpythonがあれば使うようになっており、以前試した時はpowerline_daemon
から呼ぶよりめちゃ早くなりました。
ん…書いてて思いつきましたが、zpyhonからmsgpack呼んでNeovimに渡して…とかなんかすごそう…
速いかどうか分かりませんが…
おわりに
もはや脱線したまま終わってしまいましたが、知見、ということで。
ここ最近のNeovimやターミナル周りの話でした。
次はDockerのアドベントカレンダーでお会いしましょう!