dein.vim でのプラグインの更新チェックを爆速にする

先日、Vimプラグインマネージャである dein.vim に、プラグインの更新チェックを劇的に高速にする変更が取り込まれた。使うには設定が必要なので、その方法を紹介する。

dein.vim を最新版にする

言うまでもないが、まずは dein.vim を最新版にする。

:call dein#update('dein.vim')

GitHub の Personal Access Token を生成する

この機能を使うには、GitHub の Personal Access Token を用意する必要がある。

https://github.com/settings/tokens

GitHub にログインして上記のページにアクセスし、Generate new token を押す。token の用途がわかりやすいように名前を付け、Generate token を押す。追加の権限は必要ない。生成された token をなくさないようにメモし(ページ遷移すると二度と見れないので注意。メモし忘れた場合は再生成する)、vimrc に以下のように設定する。

let g:dein#install_github_api_token = 'your token'

your token のところに生成した token を書く。言うまでもないが、この token は人に知られてはまずいものなので、vimrc を公開しているのであれば別のファイルに分離するなどの工夫が必要だ。

更新方法を変更する

通常、プラグインの更新には dein#update() を使っていたと思うが、新しい方法では dein#check_update() の第1引数に TRUE な値を渡すことで行う。

call dein#check_update(v:true)

特定のプラグインだけ更新したい場合はプラグインの一覧を第2引数に渡す。

call dein#check_update(v:true, ['dein.vim'])

プラグインを100個単位で入れていたとしても、あっという間に更新のチェックが終わる。

仕組み

ここからはオマケで、高速化の仕組みについて。

Vimプラグインはそのほとんどが GitHub 上で公開されている。今までは、プラグインの新しいバージョンが公開されているかどうかを、リポジトリ 1 つずつチェックしていた。当然 1 件ずつ通信を行うため、プラグインを100個も200個も入れていると、とても時間がかかる。

新しい方法では、GitHub の GraphQL API を使い、リポジトリを 100 件単位で更新があるかどうかをチェックする。このために Personal Access Token が必要になる。

GitHubREST API では 1 度のリクエストでアクセスできるリポジトリは 1 つだけになってしまうが、GraphQL API であれば 1 度の API リクエストで 100 件のプラグインのチェックができるため、更新されたプラグインがなければ非常に高速にチェックが終了する、というわけだ。

この手法については私が雑談レベルで提案していたものだが、今回 Shougo さんがものすごい速さで実装してくれた。ありがとうございます!

更にオマケ: 別の高速化の話

プラグインマネージャは更新処理の際、「今ローカルにインストールされているプラグインのバージョン(Git のコミット)はいくつか」を知る必要があるが、Windows では Linux などに比べると外部プロセスの起動が非常に遅く、リポジトリ毎に git コマンドを実行するだけでも数が多いとかなり時間がかかっていた。

別のプラグインマネージャである minpac ではこの問題を改善するために、「Git のコミットを得るために git コマンドを実行せずに直接 .git/ ディレクトリ内のファイルを読む」という手法を採用していたが、このたびこの方法が dein.vim にも取り込まれた

よって特に Windows ユーザーは以前に比べて更に高速になっている。

なお、こちらの変更は特に設定をしなくても恩恵を受けられる。

Vim で q を prefix キーにする

前置き

Vimプラグインをたくさんいれていると、それらを呼び出すためにキーマッピングを用意したくなることはよくある。

Vim はキーシーケンスに対してマッピングを割り当てられるので、何かのキーを prefix キーとして、そのキーに続けて何かしら機能を割り当てると言うテクニックがよく用いられる。

" スペースキーを prefix にする例

" スペースキー単体では何も起きないようにする
" これをしておかないと、うっかり <Space> + 割り当ててないキーを
" 押すと <Space> の元の機能が発動する
nnoremap <Space> <Nop>

" <Space>q でウィンドウを閉じる
nnoremap <silent> <Space>q :<C-u>quit<CR>

" ... 以下、<Space> + 何かにキーを割り当てられる

しかしこの方法をもってしても、割り当てたい機能はどんどん増えていくものである。prefix キーとして利用しやすいキーはいくつかあるが、それらが枯渇するほど機能を割り当てている人も世の中にはいるようだ。

q を prefix にすることで起きる問題

q は、マクロの記録を開始するコマンドである。q + レジスタのアルファベット1文字で、そのレジスタに対してマクロの記録を開始する。

しかし、26個もあるマクロを全て器用に使いこなしている人はおそらくまずいないと思う。私なんてだいたい1つしか使わない。どこに何が記録されているか、覚えられないからだ。

となると、残りの q + アルファベットは空いていることになる。q を prefix にすればこれらが使える。何ならアルファベット以外の文字も使えることになる。

nnoremap q <Nop>
nnoremap qa :<C-u>echo 'Awesome feature!'<CR>

こうすることで、qa は無事便利機能に割り当てることができる…が、こうしてしまうと、q<Nop> にすることで、マクロの開始が一切できなくなってしまう。

これはさすがにまずい。しかしこれは単に q<Nop> を割り当てなければ解決する。

nnoremap qa :<C-u>echo 'Awesome feature!'<CR>

マクロの記録も開始できる。これで何も問題はない…?

更に潜む問題

Vim のマクロの記録は q 単体で終了する。ところが、q で始まるキーマッピングがあると、押された q がマクロの終了であるのか、はたまたキーマッピングの呼び出しなのかを判断するため、Vim はしばらくの間キーマッピングの待受をする。

待受時間を待ってやり過ごすか、q で始まるキーマッピングではない何か別のキーのコマンドを実行すれば済むのだが、いかんせんやきもきしてしまう。やはり prefix 以外のキーマッピング待ちは発生させたくない。

解決策

今回、この問題を解決するために以下のように設定してみた。

nnoremap <script> <expr> q reg_recording() is# '' ? '<SID>(q)' : 'q'

nnoremap <silent> <SID>(q) q
nnoremap <silent> <SID>(q)a :<C-u>echo 'Awesome feature!'<CR>
nnoremap <silent> <SID>(q)<Space> :<C-u>quit<CR>

q を押した際に、マクロの記録中であれば即座に q を起動してマクロの記録を終了させ、そうでなければ prefix としての q を呼び出す。prefix の設定がない場合はそのまま q として機能させることで、マクロの記録開始も行えるようにする。

こうすることで、q を prefix として機能させつつマクロの記録開始/終了に影響を与えないようにすることができる。私は <Space>q をよく q<Space>誤爆することがあったので、同じ機能を割り当ててみた。

今回はなんとなく <SID> を使ってみたが、q prefix のキーマッピングを複数のスクリプトで定義したい場合は <Plug> を使っても問題ないだろう。

nmap <expr> q reg_recording() is# '' ? '<Plug>(q)' : 'q'

nnoremap <silent> <Plug>(q) q
nnoremap <silent> <Plug>(q)a :<C-u>echo 'Awesome feature!'<CR>
nnoremap <silent> <Plug>(q)<Space> :<C-u>quit<CR>

この場合は q のキーマッピングnnoremap ではなく nmap を使うことに注意する必要がある。

残る問題

ここまでやっても一応まだ問題は残ってる。ここで定義した q で始まるキーマッピングは、マクロの記録中に呼び出すことはできない。 しかしこれはある意味当然であり、マクロ記録中に呼び出したい機能を q に割り当てないようにする他はない。

Vim Short Tips Advent Calendar を開催しました

全然ブログを更新しない thinca です。

さて、今年も Advent Calendar の季節がやってきました。あちこちで大量の知見が出回っていますね。

記事が増えるのはいいことなんですが、一方で私はこの流れにあるつらみも感じていました。

書くのがつらい

長編記事は書くのが大変です。いや、別に誰も長編記事を書いてくれ、とは言っていません。

しかし上がってくる記事はどれも力作。こんな流れの中、しょぼい記事は上げづらい、なんて感じたことはないでしょうか。

特に日本人は空気を読むように訓練されている節があるので、ハードルが高いと感じてしまう人もいそうな気がします。というか私は大作記事は大変なのでできれば書きたくないです…。

読むのがつらい

特にこの時期に大量の記事が出回ることになるので、楽しみな反面、読むのが大変です。

途中で挫折して読むのをやめてしまったカレンダー、ありませんか。

試験的な試み

そこで今回試しにやってみたのが、Vim Short Tips Advent Calendar です。

内容を、Twitter の 1 ツイートに収まるものに限定し、書く手間と読む手間を下げよう、という試みです。テーマが Vim なのは私が Vim 界隈で活動しているからですね。

内容も、高度なものである必要はありません。というか短いので高度なことは書けません。知ってるとちょっと便利な Tips がメインです。

実はこれ、11 月中にカレンダーがあちこちで立てられるなかぼんやり考えていたものなんですが、vim-jp コミュニティ内でコンセプトを説明して参加者を募ったのが 11/30 の 20 時頃。実際にカレンダーを立てたのはその1時間後の 21 時頃というギリギリでの開始でした。

にも関わらず、参加者はあっという間に集まり、最初数日分は即座に埋まり、その辺りを走っているうちに最後まで全てメンバーが埋まりました。コンセプトの狙い通り、参加のハードルを下げたのが功を奏したのだと思っています。

参加者や各 Tips を見てくれた人からも概ね好評だったように思います*1。こういうやり方もありだな、と感じました。

Tips 一覧

せっかくなので Tips 一覧を引用してみたいと思います。短いので全部並べてもサクッと読めますね。お気に入りの Tips を見付けたら、ぜひいいねや RT をしてあげてみてください。

1日目

2日目 3日目 4日目 5日目 6日目 7日目 8日目 9日目 10日目 11日目 12日目 13日目 14日目 15日目 16日目 17日目 18日目 19日目 20日 21日目 22日目 23日目 24日目 25日目

おまけ

*1:アンケートを取ったわけではないので私が感じた限りでは

VimConf 2019 が開催されて1週間が過ぎました

今年も無事 VimConf を終えることができました。私は今年もスタッフの一人として参加しました。参加してくれた皆さん、発表してくれた皆さん、スタッフ、そのほか関係者の皆さん、ありがとうございました。おつかれさまでした。

1週間経ったこともあり、感想記事が続々上がってきています。また、(遅くなりましたが)参加した皆さんにアンケートのお願いも送信し、続々と回答が集まっています。

VimConf の運営スタッフは全てボランティアです。スタッフには金銭的な報酬は一切ありません。まあこれは別に珍しいことではなく、大抵のコミュニティドリブンのカンファレンスはどこもそうだと思います。

それでいてやることは山のようになります。みんなプライベートの時間を切り崩してなんとか対応しています。みんなできる範囲でやっているので、負担が偏ったりもします。たぶん私は他のメンバーに比べると負担は軽かった方。みんなありがとう。

話が逸れた。こういった状況の中で、多くの感想記事やアンケートでの意見を拝見していると、大変だったけどやってよかった、と思えます。今のところ発見できた感想記事は全て目を通しています。ありがとうございます。

イベントの盛り上がりと継続と言う意味で、フィードバックは非常に重要です。「もうみんな書いてるし…」「イベントから時間が経ってしまったから…」そんなことはありません。今からでも遅くないです。あなたの記事を見た誰かが、次回は参加したいと思うかもしれません。

…感想を書こうと思ったら感想にすらなっていないポエムになってしまった。 ともあれ、カンファレンスは、参加してくれる皆さんがいてくれてこそ成立しています。そして参加してくれた皆さんがまた参加したいと思ってくれたのであれば、運営スタッフの一人としてこれほど嬉しいことはありません。

ライブコーディングで作ったプラグインを整理して公開した

先日、ゴリラ.vim #9 に参加してライブコーディングをしてきた。

gorillavim.connpass.com

その際に作ったプラグインを整理して最低限の形した。整理する過程で色々変わったのでその話など。

公開したプラグインは以下。

github.com

どんなプラグインなのか

これは日本語における、ひらがな⇔カタカナの変換や全角⇔半角の変換をするプラグイン

極稀に欲しくなる操作で、サクラエディタなどには標準で付いている。Vim でもやりたかったので作ってみることにした。ネタとしても小さめでライブコーディングでもなんとかなるかなという目論見。

試験的なプラグインということもあって、無駄に最新バージョンの Vim を要求する。scriptversion 4 が通らない Vim では動かない。

プラグイン

変換するという想定でライブコーディング時には convja.vim という名前で作り始めた。

しかしあとであれこれ考えて、文字種の判定や抽出もできると便利かも(やるとは言っていない)と思い、汎用的な処理ができるように jautil.vim という名前にしてみた。無駄に汎用化してしまうのは私の悪い癖である。わかってはいる…。

インターフェース

ライブコーディング時では、以下のようなインターフェースを想定していた。

echo convja#convert('123アイウ', {'target': 'hankaku', 'type': 'kana'})
# => '123アイウ'

しかし作っているうちに紆余曲折があり、もっとシンプルに指定できるようにしたいなぁという気持ちになったので以下のような形式に落ち着いた。

echo jautil#convert('123アイウ', 'hankaku:kana')
# => '123アイウ'

簡易とはいえ特殊な文法を知る必要があるが、まあ辞書の形式を知るのと大差ないだろう。

拡張

第2引数の target に配列を渡せるようにした。これにより、まず半角カナを全角カナにし、その後全角カナをひらがなにすることで全角/半角両方のカナをひらがなに直す、ということが1度の呼び出しでできる。

echo jautil#convert('アイウエオカきくけこ', ['hankaku:kana', 'katakana'])
# => 'あいうえおかきくけこ'

また、第1引数に配列を渡すことで第1引数と第2引数を入れ替えられるようにした。これにより、partial を使って特定の変換をする関数を用意することができるようになる。

let H2Z = function('jautil#convert', [['hankaku']])
echo H2Z('abc')
" => 'abc'

今後の展望

あれこれこうできたらいいなと思っていることはあるが、優先度は激低なのでやるかは不明。ライブラリだし vital module 化したいよなー。

もっとちゃんと使いたいぜって人がいたら Issue を立てたりしてください。やるかどうかはわからないですが…。

ゴリラ.vim #1 に行ってきた

ゴリラ.vim #1 に行ってきた。

この規模の Vim イベントで定員オーバーは初めて見たかもしれない。しかもまだ実績のない第1回でこれなのだから、ゴリラさんの求心力の高さが伺える。

会場は渋谷ヒカリエにある株式会社ディー・エヌ・エーさん。セキュリティゲートの受付で思わず「うほうほ」と挨拶しそうになったけど、なんとか堪えました。危なかった。

発表は初心者向けから上級者向けまでいい感じにバラけており、後になるほど高度になっていく感じで発表順序も完璧だった。満足度が高い。

dice_zu さんが私の作った showtime.vim を使ってくれてて嬉しかった。もうちょっとちゃんとメンテしないと…。

懇親会では寿司とカツサンドをつまみながらおしゃべり。学生さんが多かった印象。ちょいちょい移動しつつ話してたけども、更にもうちょっとあちこち移動して話をすれば良かったと少し後悔。

この感じのイベントを今後は毎月のペースでやる予定とのことで、今後が楽しみです。

帰り際のゴリラさんとの会話

ゴリラさん「thinca さん、次回は発表してください!」

マンボウ「そうですね。検討してみます」

ゴリラさん「検討じゃなくて、してください!」

マンボウ「あ、は、ハイ…」

ということで次回は何か発表することになった。進撃のゴリラには敵わなかったよ…。何を話そうかなぁ。

VimConf 2018 で Bram Moolenaar さんと会った話

2018年11月24日に VimConf 2018 が開催されてから、早いものでもう 2 週間経った。

2 週間経ってしまった…。2 週間…早い…。

このままだと私の VimConf が終わらないので、正直何を書けばいいのかわからないのだけど、なんか書こうと思う。

VimConf 2018 前日

今年の VimConf は色んな意味で、忘れられないものになった。

2018 年 11 月 23 日。若干の発熱により、私は寝込んでいた。翌日には VimConf が控えていると言うのに、ここに来てまさかの風邪…。 幸いにも辛さはほぼなく、微熱が主な症状。一日中寝て過ごすことになったわけだけど、この間にも様々なことを考えた。

症状がひどくなったら VimConf は欠席せざるを得ない。私は当日にするべきタスクを持っていなかった*1ので、最悪私がいなくてもイベントの開催には支障がない。とは言え半年以上かけて準備をしてきたイベント。しかも Bram さんと会えるまたとない機会。これを逃がしたら次はないだろう。Vim に携わる者として、多少無理を押してでも行きたい…。しかし Bram さんに会えたとして、私は英語が大の苦手である。言いたいことはほとんど言えないだろう。Bram さんが何を言っているのかも、聞きとれる自信がない。正直、その点で言うと会うのが怖くすらある。そしてもちろん、症状が回復したとしても病み上がりの身。周りには迷惑をかけることになるだろう。だとしても…。

VimConf 2018 当日

そうこうして迎えた 2018 年 11 月 24 日。体調は完調とまでは行かないものの、出かけられそうなくらいにはなっていた。後悔はしたくない。普段より厚着をして、あまり好きではないマスクを着け、意を決して家を出た。

予定より少し遅れて会場に着くと、すでに開場待ちの人達がちらほら。KoRoN さんに呼ばれてスタッフルームに入る。「Bram さんもう来ているよ。mattn さんと話してる」

本当にこの時が来たのだな、と思った。その後、まだ開場前のホールで、Bram さんと会った。私は名前くらいしか言えなかった。そしてたぶん、私のことなんて Bram さんは知らないだろうと思う。スタッフジャケットを着ていたので、かろうじてスタッフだということは伝わった気がする。握手してくれた。めっちゃドキドキした。

ただでさえない文章力が崩壊してきた…。えーと、ともあれ私は Bram さんと対面することに成功した。でもやっぱり何も話せず、懇親会も含めてこの日は Bram さんとはこれっきりだった。

VimConf 2018 翌日

2018 年 11 月 25 日。VimConf 2018 も終わり興奮も冷めやらぬ中、VimConf の裏イベント、vimthon が開催された。VimConf スタッフと一部の Vim 開発者、そして Bram さんを迎えてわいわい Hackathon をするイベントだ。当日の様子をまとめた Togetter がある。

f:id:thinca:20181125093709j:plain
VimConf Hackathon

体調が悪化していたらキャンセルしようかとも思っていたが、幸いにもどちらかと言うと回復してきていたので、こちらも参加できた。

全員が揃ってしばらくしたところで、全員がそれぞれ自己紹介。中には簡単なものではなく、人によっては作ったもののデモなどをガッツリ、と言う感じの濃い自己紹介もあった。

座席の配置の関係で、最後は私の番。簡単に済ませることもできたのだけど…ここは少し勇気を出して、自分で作ったプラグインをいくつか紹介した。あまり多くの種類はデモできなかったけれど、どのプラグインを見せようかと選ぼうとした際に vimrc に書かれた私のプラグインのリストが画面に映り、これは全部私が作ったものだ、という話をした。

会の終わり際、Bram さんが帰る頃合いになった。別れを惜しみつつみんなそれぞれツーショット写真を取ったりした。その際に Bram さんに、「プラグインをたくさん作ってくれてありがとう」と言われた。多分。英語のヒアリングに一切自信がないけど、たぶん言われたと思う。本当に嬉しかった。

最高の体験

いつにも増して文章力のないただの日記になってしまった…。とにかく私は最高の体験をしました。

ここのところ Vim 活がまったく捗っておらず、いかんともしがたい状況が続いているので、Vim 活がんばろう。

おしまい。

*1:私に限らず、当日にするべきタスクを極力減らす方向でスタッフ全体で準備していた