Vim の問題を調査したときの記録

先日私の環境で起きた Vim に関する問題を調査した際の記録。一例なので汎用的に使える手法ではないけど、こういう感じのことをしているよというのを書き留めておきます。

結果的に無駄だった工程も書いています。1 本道で調査が進むことの方が珍しく、だいたい回り道します。

問題

cgn で検索のマッチ対象を別のキーワードに置き換えたあと . で繰り返すと、Bell が発生する。」

cgnc + gn で、gn は検索にマッチした範囲です。つまり検索にマッチした内容を c で書き換え、. で次のマッチ対象にも同様の変更を行います。1 つずつ確認しながら置換したい場合などによく使われる操作です。

問題について

Vim では不正な操作をした場合など様々な場面で警告としてベルを鳴らします。 例えばノーマルモードでそれ以上移動できない方向に移動しようとした場合など、割と些細なことでも鳴ったりします。

人によっては煩わしくて鳴らないように設定している人もいると思います。プラグインの利用者であればそれも良いかと思います。無効にしてしまえば今回の問題は解決します。

しかし、ベルを無効にすることはコンパイラの警告を全て無視しているようなものです。私は Vim プラグインの開発をしているので、些細な問題にも気付けるようにベルは有効にしています。

調査

ベルの厄介なところは、「何か問題が起きた」ということしかわからないところです。メッセージすらない…ハードモードです。

何由来のベルか調べてみる

ベルは 'belloff' オプションを使うことで種類ごとに抑制できます。これを使えば何の操作でのベルか絞れるかも…? と思って設定してみることに。

たぶんこれかな…と思い最初に error を設定してみると、見事エラーは抑制されました。 error は「その他のエラー」。何もわからないということがわかった…1。結果的にこの調査は完全に無意味でした。そういうこともある。

キーマッピングを確認する

. でエラーが起きるので、. に何か機能が割り当てられていないか確認。repeat.vim をインストールしていたのでこの辺りかもしれないと睨みました。 しかし実際に nmap . で設定を調べてみると、何も割り当てられておらず。repeat.vim にはいくつか派生バージョンがありますが、私が使っているものは repeat#set() が呼ばれるまでキーマッピングの設定をしないようです。

またもあてが外れましたが、徐々に絞れてきています。

autocmd を確認する

. がデフォルトのままだとすると、そこでエラーが起きるとすれば autocmd の発動によるものである可能性が高いです。 . で起きるイベントとなると…たぶん TextChanged かな? ということで TextChanged について調べることに。

:autocmd TextChanged
--- Auto-Commands ---
ALERunOnTextChangedGroup  TextChanged
    *         call ale#Queue(g:ale_lint_delay)
anzu  TextChanged
    *         call anzu#clear_search_cache()
vimconsole  TextChanged
    *         :call <sid>text_changed()
plugin-wtrans  TextChanged
    wtrans://source/*
              call wtrans#buffer#translate(expand('<amatch>'))
neosnippet  TextChanged
    *         call neosnippet#handlers#_restore_unnamed_register()
plugin-unite  TextChanged
    <buffer=2>
              call unite#handlers#_on_text_changed()

内容は記事執筆時点で再現のために出したものなので調査時とは少し違うかもしれません。 ともあれこの中に原因があると踏んで、1 つずつイベントを削除して、問題が再現するか確認します。ただし plugin-wtransplugin-unite はパターン的に発動しないことが明確なので最初から除外可能です。

:autocmd! ALERunOnTextChangedGroup TextChanged

1 つずつ消して、問題が再現するか試していきます。しかし全部消してもエラーは出続けました。むむむ。

実際に起きている autocmd を確認する

ざっくり雑に TextChanged かな、と疑ってみましたが、そもそもこの予想が外れていそうです。実際に起きているイベントを確認してみることに。 こういう場合は 'verbosefile' を使うと便利です。

:set verbosefile=/home/thinca/log.txt
:8verbose normal .
:set verbosefile=

起きたイベントがファイルに記録されます。ログレベル2をもっと上げれば、実行された全てのスクリプトの行が記録されるので、それを使うこともありますが…今回はベル。ベルは記録されていないので、全てのログを出してもどこで問題が起きたかはわかりません。そこで今回はイベントだけ出します。

と言うわけで実行してみた結果(一部抜粋):

InsertEnter Auto commands for "*" を実行しています
InsertLeave Auto commands for "*" を実行しています

InsertEnterInsertLeave でした!そもそも TextChanged は実行されてなかった。

考えてみれば cgn は一旦挿入モードに入ってテキストを変更するので、. でリピートしたとしてもそこは変わらないわけですね。

というわけで今度こそ。

InsertEnter のイベントを確認する

先ほどやったように 1 つずつイベントを消して、再現するかどうか確認します。すると、以下の箇所で問題が発生していることがわかりました。

neocomplete  InsertEnter
    *         call neocomplete#handler#_do_auto_complete('InsertEnter')

ここまでわかればあとは該当コードを追っていけば良さそうです。

該当コードを追ってみる

この先はおまけ。該当コードは以下のようなもの。

function! neocomplete#handler#_do_auto_complete(event) abort "{{{
  if s:check_in_do_auto_complete(a:event)
    return
  endif

  if g:neocomplete#auto_complete_delay > 0 && has('timers')
        \ && (!has('gui_macvim') || has('patch-8.0.95'))
    if exists('s:timer')
      call timer_stop(s:timer.id)
    endif
    if a:event !=# 'Manual'
      let s:timer = { 'event': a:event }
      let s:timer.id = timer_start(
            \ g:neocomplete#auto_complete_delay,
            \ function('s:complete_delay'))
      return
    endif
  endif

  return s:do_auto_complete(a:event)
endfunction"}}}

+timer が利用可能な場合に少し待ったのちに s:complete_delay() を呼び出しています。s:complete_delay() 内では、補完処理を行っています。

ここで実際に起きている処理を思い出して見ます。cgn. で繰り返すと、一瞬挿入モードに入ってすぐに抜けるのでした。つまり s:complete_delay() が呼び出される頃にはすでに挿入モードを抜けています。今回の問題は、ノーマルモードで補完処理を行おうとして起きていたものでした。

ちなみに、この問題はすでに修正してもらえました。Shougo さん、ありがとうございます!

まとめ

Vim で問題が起きた際の調査の一例でした。

今回の例は再現率が 100 % だったのでなんとかなりました。トリガーがわからないとその分難しくなります。

他に汎用的な手法として、プラグインを少しずつ無効にしていってどのプラグインが原因か調べる方法もあります。プラグイン数が多いと大変ですが、確実性は高いです。問題を起こしているプラグインさえ特定できれば、最悪原因がわからなくても最小構成での再現を作ることでバグレポートを出すこともできます。

バグ調査は地道な作業ですが、快適な編集環境のためにできることからやっていきましょう。


  1. 正確にはその他のエラー以外のエラーではないことがわかった。

  2. 例で設定しているのは8。詳細は :help 'verbose'

進捗キャンプに行ってきた

書くのが遅くなってしまったけど、先週末に金曜を休みにして 4 連休を利用して友人達と進捗キャンプに行ってきた。

旅館に引き籠もってひたすら進捗を出す会。たまに休憩をしつつ、たまに近くにいる利点を活かして相談しあったり、進捗のマサカリを投げあったりして和気あいあいとしてかなり楽しかった。

環境もかなりよくて、広い部屋で思い思いの姿勢でだらーと開発。私は仰向けとかでだらっと開発していて、とても人様に見せられる格好ではなかったので知ってる人しかいなくてよかった。

以下に成果を簡単に。

プラグインを 1 つリリース

wtrans と言う node.js 製の CLI ツールと、それを使う wtrans.vim をリリースした。とは言っても、これ春だか夏だか(忘れるくらい昔)に作り始めたやつで、1週間くらいでサクッと作るかって思って今に至るのでだいぶ引っ張った。悪い癖だ…。

完全に個人用に作ったやつなのでどんなツールかの解説はあえてしない。簡単なドキュメントは書いてあるので気になる人はそっちを見てください。

vimrc読書会 bot の改修

特に Promise の then() を使いまくっていてつらかった部分を、どうせ hubot で Node.js なのでバージョン上げて async/await に書き換える作業などをしてた。 ろくにテストを書いていなかったので恐る恐るだったけど、なんとか無事動いたのでよかった…。テスト書きたいけど、書くのつらい…。

あとはちょっとした新機能の追加とかした。たぶん次回辺りにお披露目される。本当はまだ追加したい機能とか整理したいところとかいっぱいあってつらい…。

vital.vim 周りのあれこれとか

特に外部モジュールについていい加減つらいという事案があるので、この辺りとかを投げられたのでやろうと思っている。

ウデマエが全て S になった

一番の成果と言っていいかもしれない。今まで A+ 辺りをうろうろしていたので、ようやくここまで来たかという感じ。前作では S+ は一瞬だけ上がってあとはずっと S だったので、今回は先に行ってみたいところ。

以上

他何か色々やった気がしないでもないけど、忘れてしまった…。

本当はもっと進捗出したかった感はあるけど、とは言え普段よりかは捗った気がするので、かなりよかった。また行きたい。

VimConf 2017 を振り返る

VimConf 2017 に、スタッフとして参加したので、その簡単に振り返りなどを。この内容はあくまで個人的なものであり、運営チームとしての見解ではありません。

今年の VimConf の立ち上げ

例年の VimConf に参加してくれていた人ならわかると思いますが、今年の VimConf は規模が去年までとは違い、かなり大きくなりました。

そもそも今年の VimConf の企画立ち上げ当初、我々には課題がありました。VimConf では将来的に Bram さんを招待したいと謳っているのですが、昨年までのペースではとてもではないけどそれは実現できないだろう、ということです。これを達成するためには、VimConf は大きく変わる必要がありました。

規模を大きくするには多くの壁があります。多くの人が入る会場を確保し、資金を調達する必要があります。会場を大きくしたとして、人が集まるかどうかはわかりません。国際カンファレンスを銘打っているのに、国際感がないとの指摘も以前からありました。とても大変であろうことは想像に難くありませんでした。この時点で、例えば、Bram さんを招待するという目標を撤回して細々と続けていく、という選択肢もあり得ました。

しかし、我々は前に進むことに決めました。正直なところ私は乗っかっただけなのであまり偉そうなことは言えないんですが。この辺りの決断に関する話を秋葉原にある肉の万世でしたのは今でも覚えています。

会場について

今回の開催で、良かった点をいくつか挙げてみようと思います。まずは会場について。

今回会場として使わせてもらった富士ソフトさんのアキバプラザは素晴らしかったですね。全席電源付き、Wi-Fi あり、そして雛壇状になっているので後ろでも発表が見やすいと、参加者にとってもそうでしたが、様々なオプションが付いていたおかげで、なんとか少ないスタッフでも無事回すことができました。 例えば参加者に配布した通訳用のレシーバー、あれも会場側が用意してくれたものです。

Fatih さんの登壇および英語発表

Fatih さんに登壇してもらえたのは本当に幸運だったと思います。

先ほど、国際感がないという話をしましたが、Fatih さんの登壇によって一気に国際感が上がりました。

また、スピーカー募集時に意識したおかげもあってかはわかりませんが、英語で発表してくれるスピーカーさんも予想より多く、国際カンファレンスの名に恥じないイベントになったと思います。

この場を借りて、Fatih さんおよびスピーカーの皆さん(もちろん日本語で発表した人も!)にお礼を言いたいと思います。ありがとうございました!

スポンサー

正直に言うと、私は最初、Vim のイベントにスポンサーはそうそう付かないだろうと思っていました。

企業で特定技術を使っていれば、その特定技術のイベントのスポンサーになることで技術者にアピールすることは理解できるのですが、Vim は個人単位で利用を選択するレベルのもので、企業として Vim をやっていきます!ということにはならないわけなので、難しいのかな、と。しかし実際には多くの企業がスポンサーになってくれました。更には終わった後にスポンサーになり損ねたのを悔やむ声も。本当にありがたいことです。

今回の開催で、「Vim のイベントに企業スポンサーをつけるのは難しいのではないか」という私の疑念は完全に払拭されました。

チケット完売

チケットについても、不安がありました。規模が大きくなったとは言え、去年の倍以上の値段で、枠も増えています。実際にチケットを売り出すまでは、ちゃんと掃けてくれるのか心配でしたが、そんな心配をよそに、無事完売御礼となりました。買えなかった人には申し分けなかったですが、来年に繋がるかどうかはチケットがちゃんと売れるかどうか次第だったので、ホッとしました。

開催を終えて

まずはとにかく無事に終わって一安心と言ったところです。当日の様子や上がってくる感想記事などを見た感じだと評判も上々のようで、本当にやって良かったと思います。

一方で反省材料もあれこれと。ここで具体的には書きませんが、来年に活かしたいところです。

興奮冷めやらぬ週明け、スタッフメンバーでささやかな打ち上げをしました。会場は秋葉原肉の万世。お肉おいしいです。

ちなみにスタッフはみんなざっくりの担当はありつつも雑用もみんなしつつみたいな感じで、私は主にパンフレットおよびイベントロゴの作成、をしてくれるデザイナーさんとの連絡役でした。パンフレット、気に入って頂けたなら嬉しいです。

当日作っていたものについて

なんか真面目っぽい話をしてしまったので、最後に少し雑な話を。

皆さんの発表を聞いていて、感極まってきて何かしら作りたくなってきたので、以前からアイディアがあったもののプロトタイプを作ってみた。

https://gist.github.com/thinca/ac438e1139c054b70a740b8f29e5ba0d

これは、Vim の中で動くターミナル(:terminal)の中で動く zsh の中で、:FooBar のように : で始まるコマンドを実行すると、外側の Vim でそのコマンドを実行し、zsh のコマンドの実行結果として出力するというもの。ギリギリ動くものの、まだ実用レベルではない。また、ターミナルについて詳しくないのでこのアプローチが妥当かとかもよくわかってない。

懇親会の最後に飛び込み発表タイムがあったので披露してみたのだけど、開発した環境が ssh 先で、会場の Wi-Fi は提供が終了していたのでテザリングでやったら回線がうまいこと動かなくてちょくちょく固まってしまった。みんなゴメンよ…。

1点、実行コマンドがそのまま出ちゃうのがなんとかできれば割と実用レベルまで持って行ける可能性があるので、できそうならやってみたいところ。Vim 本体を直すか、アプローチを変えるか…。

Udon.vim #0 に行ってきた

はるばる行ったぞ初四国!というわけで Udon.vim #0 に行ってきた話。

うどん県上陸

神戸から深夜フェリーでうどん県へ。4 時間ほどの船旅。

フェリーだけど海っぽい揺れは全然なく、せいぜいエンジンっぽい揺れがあるくらいだった。フェリー感はあまりないけど、4 時間乗ることを考えるとこうなってないと船酔いする人がつらい。

結果的に使わなかったけど、横になって寝れるスペースもあり、そういう意味では高速バスより快適説があって、とてもよかった。本数が少ないのがネック。

本編

もくもく会ということで、私は前日に行われた関西Ruby会議2017のレポートを書く作業をしていた。香川まで行ってやることではない…。

ここまで来たからには交流メインでやるべきだったのだけど、たぶん話せてない人とかいた気がする(たぶん)。完全に失敗した。

他では、y0za さんの発表があったりして、とてもよかった。私も何か技術系の発表をすればよかったかも。次に遠征する際はちゃんと準備しよう。

懇親会

香川大学の学生さんが何名か参加していて、就活の話なども話題に上がった。

あとは、香川だけだと人が集まらないので、四国.vim をやるか、みたいな話題が上がった。次回は愛媛で柑橘類食べ放題の Vim 勉強会が開催されるとのもっぱらの噂。

うどん録

滞在中にうどんを 4 杯食べました。

1日目。

2日目。

うどんめっちゃおいしいのだけど、最低でも1玉単位で出てくるのでハシゴは2件までしか無理だった…。観光客向けに半玉ずつ提供とかあると嬉しい。

さいごに

主催してくれた @mozi_kke さん、宿を提供してくれた @koturn さん、その他参加された皆さん、ありがとうございました!

香川となると気軽に「また行きます」とまでは言えないけど、機会があればまた行きたい。

Fablic.vim #1 に行ってきた

Fablic.vim #1 に行ってきたよ。

イベントの詳しい内容は公式レポートに譲って、個人的な感想などを。

ピザ

まずは開始前にピザを頂きつつアイスブレイク。ピザおいしい。

本編

最前列の見やすい席で聴講。ゲーム系のプラグインで盛り上がった。最近作ってないのでまた作りたいなぁ。

飛び込みの発表が割とあったのも良かった。少人数なのもあって、そういうのがやりやすい空気。ハードル低いのよい(発表者のレベルは高かったので本当にハードルが低いかはちょっとわからないけど)。

懇親会

最初にピザを食べたけど、発表が一通り終わった後にも追いピザが来てとても良かった。これは最初早めに開始して、最初のピザが完食された後に本編に来た人がピザ食べられなくて大変残念だったので、急遽追加で用意されたもの。柔軟な対応と配慮が行われて大変素晴らしかった。

私はと言うと、puyo.vim のデモの流れで、@rbtnn さんぷよぷよテトリスSで対戦して盛り上がった。こういう時に Nintendo Switch は便利すぎる。とても良かった。

次回は7月頃とのことなので、また参加させてもらおうと思います。次は何か発表するかも。というか声がかかる予感がある。何か考えておかないと…。

Meguro.vim #3 を開催した

第3回目の開催となった Meguro.vim #3 を開催したよ。簡単に振り返り。

ランチ

カレーを食べました。

f:id:thinca:20170520121712j:plain

本編

割とぐだぐだに始まってしまったのが反省点。途中で自己紹介タイムを挟むことに。

全体的に、みんな自由に作業したり雑談したりできていたみたいで、雰囲気はとてもよかったと思う。この感じでやっていきたい。

途中、キーボード談義が発生して皆さんキーボードについてアツく語っていてとてもよかった。

会の最中に、遠隔地にいる @ttk_vim さんに、Meguro.vim のロゴを作ってもらった。かっこいい!本当にありがとうございます!

ばんごはん

中華を食べました。

f:id:thinca:20170520195422j:plain

確か9人くらいが参加。

ふり返り

今回こそ、ふり返りを実施しました。

https://github.com/thinca/Meguro.vim/issues/1

各位コメントを書いていく形式です。どなたでも参加可能です。宣伝されてなくてイベントの存在を知れずに参加できなかった、とか書いても大丈夫です。(実際どれくらいいるのか気になる)

次回

次回は 7 月頃を予定してます。一応具体的な日も決まっているけど確定ではないのでここには書かないでおく。

Meguro.vim #2 リベンジを開催した

Meguro.vim #2 リベンジなるイベントを開催したので、簡単にレポートっぽい何かを。

元々は 2/25 に Meguro.vim #2 が開催予定だったのだけど、私が風邪を引いてしまい開催できなかった…参加登録してくれた方には申し訳なかった…。というわけで、仕切り直して 3/25 に #2 リベンジという形でなんとか無事開催!

本編

今回はたまたま Osaka.vim #9 at Kobe が同じ日に開催されており、Lingr でお互い挨拶した結果、その場のノリでお互いの会場を 無駄に Google ハングアウトで繋ぐことに。こうしてサテライト会場っぽい感じになってとてもよかった。 どちらももくもく会だったので、もくもくしたりたまに発生する雑談の様子などをお互いに見ることができてとても良かった。別の機会でもできそう。もっとやって行きたい。

本編の内容では、duzzle.vim が空前の大ブーム。作られたのはかなり昔だけど、その完成度は高く、絶賛の声が多数。続編も望まれているので、みんなでプレイして続編を待ちましょう。

また、参加者は私を入れて 9 人と多くはなかったのに、事前に知らなかったけど実は(元)同じ会社の人が参加していた、みたいなのが 2 組も発生し、業界狭い事案だった。すごい。

晩ごはん

晩ごはん会は、出席率100%を達成!次回もこの調子で行きたい。あ、参加を強制するとかではなく。

おまけ: 試射会

今回は日程が Splatoon 2 の先行試射会と重なったので、思いきって試射会も一緒にやる形式にしてみた。実際に参加したのは、昼の部はほとんどおらず、ハードを持ってきたも私だけだったけど、夜はそこそこいて、@yysaki さんがハードを持ってきてくれたので大型のテレビとプロジェクタの2面で Splatoon 2 を遊ぶことができた。終了後も 1-2-Switch でかなり盛り上がってかなりよかった。

結果として何人かに布教することができたように思う。計画通り。

振り返り

実は終了後にアンケートも兼ねて任意参加で参加者みんなで KPT をやろうと思っていたのだけど、気付いたら月曜で今さらみんなに書いてくださいって言いづらくなってしまったので、反省。次回はちゃんと終わったあとまで考えて準備しないと。

あと、この記事自体書くのが遅すぎる。遅くても翌日には書きたいところ。この辺りも次回の課題。