🔙 Back to Top

Fri Dec 4 13:16:32 JST 2015

Vim - コーディング中の文法チェック

タイトルの通り. コーディングをしながら、そのコードの文法が正当なものであるかを、 書きながらチェックするためのプラグインがいくつか存在する. 「書きながら」とは言っても、素の Vim は非同期的にプロセスを呼んだりはできない.

QuickFix

プラグインではなく(?) 初めからある機能. :make はその場で make するコマンドであるが、これでエラーが出た時、 QuickFixは、 エラーメッセージを適当に解釈 (エラーが出たファイル名と行番号を抽出する) して、それを保持する. :copen で、エラーが出た箇所のリストを開いたり、箇所にジャンプしたりできる (:help quickfix). あと、勝手に最初に出現したファイルを開く. これは偶に不便だ. 避けるためにはQuickFix の利用を諦めて :make じゃなく :!make とする手がある.

QuickFix を利用するためには適切な Makefile を用意する必要がある. 実際には :make&makeprg を呼び出す. 例えば

:set makeprg=date

としてから :make すると :!date が呼び出されて利用される. 次に掲示する syntastic 等、文法チェッカ系のプラグインは、これを利用している.

syntastic

恐らくこの世の中で一番ポピュラーなプラグインで、 開発もそれなりに盛んで、新しい言語があれば、大体追加対応されている (https://github.com/scrooloose/syntastic/tree/master/syntax_checkers).

バッファをファイルに書きだしたタイミングで勝手にQuickFix 同等のことをする. syntastic が優れているのは、エラー箇所の行に Signs を表示するところ (これはスクリーンショットを見たほうがいい). 画面の左端っこを見て、赤く光ってるところがあれば、そこにエラーがある. そもそもエラーが出ると、signを出すための列がぽんっと出現して、全ての行が少し右にずれるので、 一目でエラーが出たかどうかが分かるのが良い. 行だけでなく、その行の中の何文字目かまでエラーにあれば解釈し、 カーソルがそこに乗った時、ステータスラインらへんにエラーメッセージを表示する. かなりIDEになる.

エラー箇所リストは :copen ではなく :Errors で表示する. でも、signを見ればいいのでそんなに使わない.

かなり長らくこれを使っていた. Signs はかなり便利. QuickFix だと、ジャンプ機能はあるものの、行番号を読み取る必要が、まあまあある.

しかしながら、ファイルに書き出すタイミングで文法チェックが勝手に走るのが辛い. その間 Vim への操作がブロックされて、 C++ を書いてる時なんかはその文法チェック (g++ -std=c++11 -fsyntax-only) が、コンパイルするのと同じくらい時間がかかる. どんな小さいプログラムでも一秒くらいとまるし、 大きなプログラムを書いてると4,5秒ブロックされる. 自然と、:w するのが億劫になる. 明らかに :w するタイミングが減ったし、:w したあと少し手をキーボードから離す癖がついた.

私は一昨日これを .vimrc から消した.

syntastic-async

"syntastic async" でググると出てくる. 正に先の syntastic をfork したプロジェクトで、これを非同期的にするバージョン. 即ち、ファイル書き出しのタイミングで文法チェックが走るが、それがバックグラウンドで動くのでユーザーの操作はブロックされない.

気になるのは、最後の更新が2年前のこと. 追加したい言語があれば syntastic の方から自分で拾ってくればいいだろうけど、 ちょっと気がかりだ.

ところでこれは AsyncCommand なるプラグインに依存している.

AsyncCommand

いくつかの非同期的に外部プロセスを呼ぶコマンドが提供される. :Asyncmake は、正にQuickFix を非同期で呼び出す. めっちゃいいぞこれ.

vim の server 機能を利用してる.

vim +vimclient (びるどおぷしょん)

+clientserver 付きでコンパイルされた vim であることが要請される. 例えば Ubuntu なら vim-gtk を入れておけば間違いない. 研究室マシンの上の vim は残念ながら、vim-tiny だった. また、 vim を起動するときにはいつもサーバーモードで起動することが必要:

vim --servername A main.cc

まとめ

# zshrc
alias vi='vim --servername A'
" .vimrc
nn mk :AsyncMake<cr>

QuickFix はQuickFixで便利だし、syntastic は syntastic で便利である. しかしユーザーの操作を奪う syntastic は最悪である. 非同期バージョンを使おう.

No.304 鍵(1) - yukicoder

問題

http://yukicoder.me/problems/765

解答

http://yukicoder.me/submissions/62466

3桁なので1000通りしかなく全通り試せばよい. "unlocked" が出てもすぐにプログラムを止めないと (?) WAになる (http://yukicoder.me/submissions/62465) のでちゃんと入力をチェックする.

No.305 鍵(2) - yukicoder

問題

http://yukicoder.me/problems/768

解答

http://yukicoder.me/submissions/62467

今度は10桁になって組み合わせが膨大になる代わりに、 正解した桁数が返ってくる.

投げる10桁を \[w_1 ~ \cdot ~ i ~ \cdot ~ w_2 ~ (i \in \{ 0 .. 9 \})\] とする. \(w_1, w_2\) を固定して、 \(i\) だけ10通り全て試すと、 正しい \(i\) のときだけ、 返ってくる正しい桁数は、正しくない \(i\) に比べてちょうど 1 だけ多いはず.

というわけで、

  1. 頭の桁から順に10通りずつ試す
a = ''
for i in 0 ... 10
  b = a + i.to_s
  b = b + '0' while b.length < 10
  puts b
end
  1. 返って来た数字が一番大きいものを採用して、頭を固定
a = a + i.to_s

貪欲法だと思える.