Vim
typo
VimDay 6

Vim 保存時のタイポで']'が作られてしまうことを防ぐ

はじめに

この記事はVim Advent Calendar 2018 6日目の記事です。

私はタイプミスが多いです。
よくやらかしてしまうのが、ファイル保存時の:w:w]とタイポしてしまい、
カレントディレクトリに]という不要なファイルを作ってしまうことです。

色々試したり、教えてもらったりして]を作らない(個人的には)ベストな方法に
辿りついたので備忘録もかねて以下に記載していきます。
(タイプミスをなくせという批判は無視)

1. autocmdを使う

Vimにはモード変更や、ファイルオープンなどのイベントをフックし、自動でコマンドを実行する仕組みが存在します。
以下ではファイル保存前(BufWritePreイベント発生後)にファイル名をチェックし、
不適切なファイル名(])であればファイル保存を無効にしています。

augroup vimrc_augroup
  " expand('<amatch>:t') でファイル名
  autocmd!
  autocmd BufWritePre * if expand('<amatch>:t') == ']' | throw "oops!!" | endif
augroup END

一見するとうまくいっているように見えるかもしれませんが、
throw "oops!!"という部分が綺麗ではありません。

現状のVimでは自動コマンドの停止(今回で言うところのファイル保存無効化)を行う術がないようで、
ワークアラウンドとして、throwを使い例外を投げて無理やり処理を止めていますが、
throwした後も以下のようなエラーメッセージが表示され、とても美しくありません
20181205-203458.png
もっと綺麗な方法がないか調べてみましたが、
ググったりヘルプを見てみても別の方法が全く分からなかったので、
VimのSlackで質問してみたところ、以下2つの方法を教えていただきました。

2. tyru/stoptypofile.vim を使う

実は自分が解決したい問題にドンピシャなプラグインtyru/stoptypofile.vimが既に存在しました。

このプラグインでは:w]だけでなく、:w hogehoge]等保存時のファイル名の末尾に特定のキーワードが付いた場合、
その名前で保存してよいかを確認してれます。
20181205-214112.png
デフォルトでは[]/という3つのキーワードを使ってチェックしていますが、
g:stoptypofile_autocmd_charsの設定を変えることで任意のキーワードに変更することできます。

また、特定のプラグインでは特別なバッファ名(例: [qfreplace], fugitive://, etc..)
を使用しているケースがありますが、チェック対象から除外したい文字列はg:stoptypofile#ignore_patternに指定しておくことができます。(正規表現で指定可能)

不便だと感じたことは大抵誰かが解決ずみですね。素晴らしい世の中。
私は以下に記載するもう1つの方法で問題を解決したのでこちらのプラグインを使っているわけではないのですが、
stoptypofile.vimを使えばかなり柔軟にタイポを検出できるので、お勧めです。

3. 短縮入力(Abbreviations)をタイポ制御に使う

結論から記載すると、以下をvimrcで設定するだけで解決することができます。

cnoreabbrev w] w

とっても簡単ですね。私はこれを自分のvimrcに記載しています。

ちょっとだけ説明すると、Vimには短縮入力を行う機能が備わっています。

" '#in'入力後に非キーワード文字(<Space>, <CR>等)を押すと '#include' に展開する設定
inoreabbrev <buffer> #in #include

この短縮機能をつかってコマンドラインモードでのw]wに展開しているだけです。
もし:w]とタイポしてしまってもちゃんと:wに展開してくれるので、意図した通りにファイルを保存することができます。

最後に

augroup vimrc_augroup
  autocmd!
  autocmd BufWritePre * if expand('<amatch>:t') == ']' | throw "oops!!" | endif
augroup END
" ↓
cnoreabbrev w] w

修正前よりも修正後のほうが綺麗に短く記載することができました。
満足。