🇯🇵

Vim で日本語を使うための工夫

2024/01/12に公開2

概要

Vim を使いはじめてから 5年ぐらいになりますが、それ以来まとまった量の文章はほとんど全て Vim で書いてきました。その中には日本語の文章も多く含まれているわけですが、Vim で日本語を編集する際には英語やソースコードを書くときとには生じにくい問題がいくつか出てきます。
代表的な問題としては、IME がオンになったまま normal モードに戻ってしまうと normal モードのコマンドが打てなくなることや、f<char>/ による検索で IME 切り替えのコストが生じてしまうことがあります。
最近このあたりの環境改善についていくつか行ってみて、以前より日本語ファイルの編集を行いやすくなっていると感じるので、その方法を紹介したいと思います。

環境

CUI 環境の vim を前提とします。gvim の IME 連携についてはこの記事では対象としません。

課題

Normal モードで IME が邪魔

Vim で日本語を編集する際にやはり一番やっかいなのは IME の存在ではないかと思います。
Vim の大きな特徴として normal モードでの柔軟なカーソル移動や強力な編集機能が挙げられると思いますが、これらはキーボード上の通常文字に対する key mapping を通して呼びだされることが普通です[1]
IME がオンになっている状態では、ほとんどのキー入力が IME に吸い取られてしまって vim に届かないので、normal モードの key mapping を呼び出せなくなってしまいます。Insert mode で日本語を入力した後 IME をオフにせずに normal モードに戻ったりするとこのような状態に陥ってしまい、 normal mode を多用する Vim ユーザーにとっては大変ストレスです。
下のようなキー入力をしてしまったことは多くの vim ユーザーが経験しているのではないでしょうか?

日本語文字列の検索がしづらい

日本語の文字列の検索のしにくさも問題です。Vim では /f<char> の normal コマンドで文字列検索を行うことができますが、仕組み上 /f コマンドを入力した直後は IME オフになっています。
したがって、日本語の文字を検索しようと思ったら文字を入力する前に IME をオンに切り替える手間が生じて流れが悪いです。しかも、文字列の入力が終わったらまた IME をオフに切り替えなければいけません。例えば、 というひらがなにジャンプしたい場合、f を入力 -> IME オン -> を入力 -> IME オフ という手順を踏むことになります。
検索というのは純粋にその文字列を探すというだけでなく、狙った場所にカーソルを移動させるために行うという役割もあるので、文章の快適な編集操作に欠かせないものです。

解決のための方針

上で挙げた 2点の問題点について、

  • Normal モードで IME オンになっている状態を避ける
  • 検索操作を IME 切り替えなしで行う

という方針で対処する解決案を挙げていきます。

Normal モードの IME 起動を避ける

ESC 連打で normal mode + IME オフを保証する

Vim を使っているとき、とりあえず normal モードに戻ろうと思ったときに ESC を何度か押すことが多いのではないかと思います。そして、normal モードでは常に IME オフになっていて欲しいです。
これらを合わせて考えると、どの状態からでも ESC を連打すれば必ず normal モードかつ IME オフの状態になるという設定ができると良さそうに思えます。

Google 日本語入力や Mozc のようなタイプの IME を用いる場合、"日本語入力モードで ESC を押すと英数モードに切り変わる" という設定をすると比較的自然にこれを実現できます。以下に google 日本語入力の設定例のスクリーンショットを載せます。

karabiner や Xmodmap で ESC を押しやすい位置にもってきておくとベターです。筆者はこの設定でしばらく Ubuntu, MacOS 機で運用していました。

もっとスマートなやり方?

記事をまとめていて改めて調べたところ、karabiner で入力ソースが日本語ではないという条件付きで英数キーを ESC に切りかえるというアイデアを知りました。
こちらでも単一キー連打で normal mode + IME オフを保証できて、かつ日本語入力時の挙動が自然[2] なので、karabiner を使っているならこちらのほうがスマートかもしれません。

https://ykicisk.hatenablog.com/entry/2020/09/26/162106

SKK を使う

より劇的な解決策としては、システムの IME を一切利用しないという方法があります。それでは日本語はどうやって入力するのかといえば Vim の insert mode プラグインとして実装された IME を利用します[3]。この方法であれば normal モードには IME が持ちこまれることがないので定義上 normal mode で IME がオンになるということはありません。

Insert mode プラグインとして実装された IME は基本的に SKK (link: ニコニコ大百科) という方式のものになります。SKK は簡単にいえば変換区切りをユーザーが全て明示的に指定するという思想の IME です。プラグイン実装の IME に SKK 実装が多いのは、文節区切りを予測する機構がいらず実装が比較的単純に行えるからという事情があります。

SKK では変換の開始位置や送り仮名の開始位置を shift キーを押しながら入力し、変換は space キーで行います。一例を挙げると、"日本語を使う" という文だったら キー入力としては、以下のように入力します。

Nihongo<space>woTukaU

慣れるまで少し大変ですが、

  • ひらがなは変換せずに打てる (-> 打鍵数が減る)
  • 文節間違いによる誤変換をしづらい

といったメリットもあるので興味があればぜひ習得してみることをおすすめします。

現在 Vim 上の SKK 実装として現在最も活発にメンテナンスされているのは kuuote さんによる skkeleton というものです。

検索操作の改善

次に、検索操作において IME 切り替えを減らすためのアプローチを紹介します。

migemo による検索

Migemo は、ローマ字入力で日本語の文字列を検索するためのツールです。たとえば nihongo日本語 を検索したりするといったことができます。Vim の / による検索でも migemo を利用することができれば検索時の IME 切り替えを減らすことができます。

Vim で migemo を利用できるようにしたプラグインとして Alisue さんによる kensaku.vim があります。kensaku.vim は単体では UI を提供しないので、/ による検索で使うには kensaku-search.vim を追加で導入します。

以下は、kensaku-search.vim を使って "方法" という文字列をローマ字入力で検索している例です。

Digraph による検索

行内など近くの範囲での移動であれば、/ を使うより f (, F, t, T) による文字単位での移動のほうが便利だったりします。しかし、f<char> による検索でひらがなを入力しようと思った場合、IME を使う方法だと非常に流れが悪いです。
Digraph という ascii 文字の組み合わせで特殊文字を入力する機能を使うと、IME を使わなくてもひらがな・カタカナを入力することができて、f による検索も少しスムースになります。
Insert mode や command line モードで <C-k>{char1}{char2} のように入力することで digraph が入力できます。例えば、<C-k>a'á を入力したり、<C-k>ka を入力したりすることができます。

f で digraph による検索を行う場合も f<C-k>{char1}{char2} のように入力します。
しかし、f<C-k> は少し打つのが大変なので key mapping をつくると良いでしょう。自分は現在は <space>f を使っています。日本語の編集中のみ f 自体を置き換えてしまうのもありかもしれません。

:noremap <space>f f<C-k>
" または Neovim なら以下も可
:lua vim.keymap.set({"n", "x", "o"}, "<space>f", "f<C-k>")

Vim のデフォルトの digraph では a5 -> , ,_ -> など少し覚えにくいものがあります。
一例として以下のような定義をしておくと入力しやすいでしょう。

digraph の定義
digraph aa 12354  "あ
digraph ii 12356  "い
digraph uu 12358  "う
digraph ee 12360  "え
digraph oo 12362  "お
digraph AA 12450  "ア
digraph II 12452  "イ
digraph UU 12454  "ウ
digraph EE 12456  "エ
digraph OO 12458  "オ
digraph xa 12353  "ぁ
digraph xi 12355  "ぃ
digraph xu 12357  "ぅ
digraph xe 12359  "ぇ
digraph xo 12361  "ぉ
digraph xA 12449  "ァ
digraph xI 12451  "ィ
digraph xU 12453  "ゥ
digraph xE 12455  "ェ
digraph xO 12457  "ォ
digraph ,, 12289  "、
digraph .. 12290  "。

これらを使うと <space>f 含む 4打鍵でひらがな・カタカナ・読点に移動できます。
少し長いようにも感じますが、同じひらがなの出現頻度はさほど高くないので ; の繰り返しなしに一発で移動できることは比較的多いです。

clever-f.vim

Vim 組み込みの f 検索を clever-f.vim というプラグインで全面的に置き換えてしまうのもありです。clever-f.vim は migemo search を備えていて、fa に移動するといったことができます。単一アルファベットによる migemo search は予想外に多く漢字にマッチしたりすることもあるので、そのあたりは注意が必要です。
詳しい使いかたについては、最後にリンクをのせた作者による紹介記事や README をご参照ください。

まとめ

この記事では Vim における IME の切り替えや検索のしづらさの問題を避けて快適に編集作業を行うための方法をいくつか紹介しました。
Vim で日本語を扱うのはいろいろな工夫が必要で、自分自身も苦労してきましたが、ようやくある程度納得できる編集環境を整えることができてきたかなという感触があります。
Vim で長く日本語を扱っている方にとっては物足りない内容だったかもしれませんが、日本語編集のための環境を試行錯誤している方の一助になれば幸いです。

参考記事

Vim で日本語を扱うための試みはこれまでもたくさんあります。
自分のためのまとめと先人への敬意も兼ねて、いつもより多めに参考記事を載せておきます。

プラグイン紹介記事

SKK 実装のひとつである skkeleton の作者による紹介記事です

https://zenn.dev/kuu/articles/vac2021-skkeleton

clever-f.vim の作者による紹介記事です。

https://rhysd.hatenablog.com/entry/2013/09/17/220837

文節区切りを移動する motion を実装したプラグインと、本稿でも扱った digraph による f 移動の改善方法の紹介です。

https://gist.github.com/deton/5138905

長文の日本語の文章を書くにあたって便利なプラグインをいくつか紹介しています。

https://riq0h.jp/2023/02/18/142447/

IME 制御

Vim から IME を制御する内容についても様々記事があります。

IME 制御の方法に加えて、IME 切り替えを避けて insert mode の mapping を充実させるアイデアを紹介しています。

https://swnakamura.github.io/posts/vim-japanese-input/

上ポストへの補足記事。歴史がなんとなく垣間見える気がします

https://zenn.dev/koron/articles/d3a14c286948c4

Vim で fcitix を制御

https://qiita.com/sgur/items/aa443bc2aed6fe0eb138

設定の紹介などではないですが、読み物として面白いです

https://mattn.kaoriya.net/software/vim/20170905113330.htm

ほか

IME 関連の設定のほか、'formatoptions' 等のオプションについても紹介しています。

https://www.soum.co.jp/misc/vim-no-susume/12/

自分は試したことはないですが、全角文字に対する key mapping を直接設定してしまうことで IME オンでも最低限操作できるようにしてしまおうといおうアプローチもあるようです。

https://qiita.com/ssh0/items/9e7f0d8b8f033183dd0b

脚注
  1. ここでいう key mapping はユーザー定義のものに限りません。 ↩︎

  2. ESC に英数切り替えの役割を負わせる設定だと、日本語入力中に ESC を押したときに ESC 本来の役割 (e.g. ブラウザ等の入力フォームからフォーカスをはずす) と英数切り替えが同時に発動したりすることがあるので、やや直観に反する挙動になることがあります。 ↩︎

  3. なんなら Vim の外への入力でさえ Vim を IME 代わりにすることもできます: https://zenn.dev/vim_jp/articles/14ab6ea83f711a ↩︎

GitHubで編集を提案

Discussion

Mitsuhiro KogaMitsuhiro Koga

Windowsでは↓のようにzenhanコマンドを導入する事でインサートモードやコマンドラインから抜けた時にIME オフにすることができます。
https://qiita.com/sasaki_hir/items/6d2cf64e4cd585e7b877

sankantsusankantsu

情報ありがとうございますー
仕組み的には VSCode Neovim 以外の環境でも使えそうですね
Windows 関連の情報はカバーできてなかったので参考になりました

見直したらIME 制御のところで紹介した下の記事でも im-select の代替として zenhan.exe が名前だけ出てたみたいですね
https://swnakamura.github.io/posts/vim-japanese-input/