Vim

Vimで日本語を編集するいくつかの方法

More than 1 year has passed since last update.

そこそこ知見がたまってきた気がするので、ここらでいったんまとめさせていただきます……!

なお、このエントリでは以下については原則触れません。

  • 文字コードまわりのオプション
    • fileencodingfileencodingsはじつはわりとややこしいので……
  • Migemo
    • /?での検索だったり後述のf系マッピングだったりのためのプラグインがあるのですが、誤爆率が高めなので積極的には使っていません……
  • スペルチェック
  • LaTeXやMarkdown、Re:VIEWそのほかファイルタイプに特化した設定

そもそもVimは日本語の編集に向いていない

本題に入る前にはっきりさせておきたいのは、以下のような理由があり「そもそもVimは(英語の場合ほど)日本語の編集に向いていない」ということです。

  • Vimのモードと、日本語入力のオンオフという複数の状態が絡んでややこしい
  • 単語がスペースで区切られないため、webでのモーションやテキストオブジェクトの選択が直感的でない
  • アルファベットでない文字に対してはftなどがほぼ使えない
  • 日本語の句読点に対しては、)(でのセンテンス移動やs系のテキストオブジェクトが効かない
  • 半角の括弧に対して使える機能が、全角括弧では使えない

Vimが(プログラミング言語だけでなく)英語の編集に便利すぎて、ちょっと見劣りがしてしまうというだけの話……なのかもしれません。
ともあれ放っておくのも癪ですから、これらをプラグイン等の助けを借りながらいくらかでもどうにかしたい……というのが、このエントリの目的です。

既存のリソース

Vimでの日本語の扱いに関しては、当然ながら既存のまとまったリソースがあります。ひとまず3つ挙げておきます。

  1. vim/gvimで日本語を使いやすくする - fludist
  2. 日本語のカーソル移動の改善: 文節単位のWORD移動(W,E,B)プラグインと、句読点に移動するmap
  3. 「Vimを使う上でのIME(日本語入力)の取り扱い」

これらを読めばすでに述べたような困難のほとんどは解消するような気がしてきました……

はい

気がしてきたのですが、先人の知恵は見なかったことにして(1つ記事を書く都合上……そうさせてください……たいへん助かっています……)続けます。

以下、上述したそれぞれの点について解決策、そして「どの程度いい感じに編集できるようになったか度数」を付けていくことにしましょう。

日本語入力システムとの連携

基本的には参考文献1と3の説明に尽きます。というか、日本語圏の人がVimを使ううえで最も大きな問題でもありますので、これ以外にもググればめちゃくちゃたくさんの情報があります。

GVimを使っている場合はデフォルトのオプションでどうにかなるので便利なのですが、自分はOS XのTerminal.app上でVimを使いたかったので、以下の選択肢を検討しました。

  1. Karabinerでノーマルモードへの移行時に勝手に日本語入力(AquaSKK)をオフにする
  2. Vimプラグインとして実装されたSKKであるeskk.vimを使う

自分は一般的なSKKとの操作感の微妙な違いのあるeskkにどうしても馴染めず、1を選びました。ただ、SKK使いであれば2も一考の余地がありますよ!

  • いい感じに編集できるようになった度数:80点
    • /で日本語入力をオンにして検索したあとにnを押すと……アアッ……
    • それ以外はわりと満足のいく感じになっています!

w、e、bでのモーションやテキストオブジェクトの選択

これも参考文献2の情報に尽きます……が、「なんとなく移動先に自信が持てない」という最大の問題はどうしても解消できません。そりゃそうですね……

したがって、参考文献にあるプラグインは使っておらず、さらには(日本語編集時には)「なんとなく早く左右に移動したいぜ!」みたいなときにしかwbを使っていない状況です……

  • いい感じに編集できるようになった度数:0点
    • これはもう仕方のないものとあきらめています……よい情報などあればお待ちしております!

ft

clever-f.vimvim-easymotionでMigemoが使えます……が、冒頭でも触れたとおり誤爆率が高いので積極的には使っていません。結局これも、webと同様「なんとなく移動先に自信が持てない」という問題なのでしょう。dfに続けて文字列を削除するようなな使い方はどうしても難しいのです。

一方これらのプラグインを使わない場合、参考文献2のように(ある程度カスタマイズするという前提で)digraphsが使えます……が、これはこれでプラグイン使えないのはもったいないですよね……

どちらにするか迷った結果、自分は日本語でのftを本格的に使うのはあきらめて、clever-fを導入しています。

  • いい感じに編集できるようになった度数:30点
    • Migemoを積極的には使っていないと言ったものの、単純な移動のときにはそれでもベンリ

)や(でのセンテンス移動やs系のテキストオブジェクト

参考文献2のdetonさんによるプラグインとしてjsentence.vimがあります。

このプラグインは任意で区切り文字を設定できるので、以下のように設定しています。

let g:jasentence_endpat = '[。.?!]\+'
  • いい感じに編集できるようになった度数:90点
    • それほど使いどころの多いマッピングではないのですが、それでもかなりおすすめです
    • ようやくすっきりした感じに解決策を紹介できました!

全角括弧関連

machpairs

昔は設定してみても使えなかった気がするのですが、いつのころからか全角括弧が使えるようになったっぽいです。
matchparenによるハイライトはしてくれないものの、%で移動できるだけでも使い勝手がわりと向上するので、設定しておくとよいでしょう。

set matchpairs+=「:」,『:』,(:),【:】,《:》,〈:〉,[:],‘:’,“:”

ただ、NeoVimだとまれにうまく効かなくなる(さっきまで使えていたのに急に移動してくれなくなる)ことがあります。なんでや。

括弧系のテキストオブジェクト

vim-textobj-uservim-textobj-jabracesを使いましょう……と言いたいところですが、vim-textobj-jabracesはあまり使わない括弧にもすべて対応しているため、覚えるのが大変です。

これを解決する選択肢としては2つ考えられます。

  1. vim-textobj-multiblockとかvim-textobj-multitextobjを使ってキーバインドをまとめる
  2. vim-textobj-jabracesを使わずに、vim-textobj-userでよく使う括弧のみを定義する

自分は最初1でやっていたのですが、若干動作がもたついてしまいます。たしかに重い処理をしていそうですからしかたがないですね。

結局、後述するsurroundとの兼ね合いもあり、よく使う括弧のみを自分で定義することにしました。"Paren"の"P"、"Brace"の"B"……など、自分でわかりやすいものにしておくとよいでしょう。

call textobj#user#plugin('jbraces', {
    \   'parens': {
    \       'pattern': ['(', ')'],
    \       'select-a': 'aP', 'select-i': 'iP'
    \  },
    \   'braces': {
    \       'pattern': ['「', '」'],
    \       'select-a': 'aB', 'select-i': 'iB'
    \  },
    \  'double-braces': {
    \       'pattern': ['『', '』'],
    \       'select-a': 'aD', 'select-i': 'iD'
    \  },
    \})

surround

Vimのデフォルトの機能ではないのですが、vim-surroundというめちゃんこ便利なプラグインがあります。簡単に言えば、'Hello'というシングルクオートでくくられているテキストを"Hello"のようにダブルクオートに変更したり、あるいは外してしまったりできるプラグインです。

このプラグインはカスタマイズしだいで全角括弧の付け外しや変更もできるようになります。ただ、詳しくは述べませんが(ドキュメントを見ていただければわかるとおり)そのカスタマイズの方法があまり直感的とはいえません。そこでvim-operator-surroundです。

自分はおおよそ以下のように設定しています。

map sa <Plug>(operator-surround-append)
map sd <Plug>(operator-surround-delete)a
map sr <Plug>(operator-surround-replace)a

let g:operator#surround#blocks = {}
let g:operator#surround#blocks['-'] = [
    \   { 'block' : ['(', ')'], 'motionwise' : ['char', 'line', 'block'], 'keys' : ['P'] },
    \   { 'block' : ['「', '」'], 'motionwise' : ['char', 'line', 'block'], 'keys' : ['B'] },
    \   { 'block' : ['『', '』'], 'motionwise' : ['char', 'line', 'block'], 'keys' : ['D'] },
    \ ]
  • いい感じに編集できるようになった度数:100点
    • 日本語・英語・プログラミング言語のいずれでもまったく遜色なく編集できる気分です!

そのほか

  • 行あたりの文字数とかを気にしたいときには、参考文献1のfuenorさんによるJpFormat.vimがめちゃ便利
  • インサートモードでの括弧の自動補完についてはlexima.vimを使っています
    • 詳しい説明は割愛しますがcall lexima#add_rule({'char': '「', 'input_after': '」', 'at': '\%#$'})とか

まとめ

よかったですね!(みなさんの知見もお待ちしております)(お願いいたします)