Vimでインサートモードを抜ける時に日本語入力を解除したい〜Mac+JISキーボード+Karabiner編〜

Vimでインサートモードを抜ける時に、確実に日本語入力を解除したいですよね。

調査したので、メモがてら報告します。

時間がかかりましたが、結論、Karabinerでいけました。

はまり込みの原因は、USキーボードとJISキーボードの違いのせいで見つけた記事と同じ解決策が通用しなかったこと。この原因に気づくのに時間がかかった。

#僕の環境

 - Mac OS X El Capitan
 - JIS キーボード
 - VIM - Vi IMproved 7.3
 - Google日本語入力 2.20.2700.1
 - Karabinerによるキーのリマップで「Oyayubi R 1 line Shift 右手1行ずらし 親指シフト(NICOLA)」設定を使用

まさかの親指シフトです。知ってます？

キーボードからの日本語入力は、ローマ字入力、かな入力メジャーですけども、そのどちらでもない第三の日本語入力方式です。まあそれは今回の記事とは関係ないです。

##時代遅れ

この記事は2018年3月21日に書いてるんですけど、最新のMac OS XはEl CapitanではなくSierraです。

それに伴って、KarabinerはKarabiner Elementsを使うのが主流になってるようです。

つまりこの記事は執筆時点で時代遅れなわけですね。なんてこった。

まあでも…誰かの役に立つかもしれないし…。主題となる「JISキーボードとUSキーボードの違い」の話は長く通用するはずだし。

#うまくいかなかった方法

まず、調べた中ででてきた方法と、それが何でダメだったかを書いておきます

##Google日本語入力のキー設定

特定のキー入力に対して「キャンセルし、IMEをオフにする」という設定をするものです。

どうやらGoogle日本語入力のアップデートでダメになったっぽいです。多分。

この設定項目自体はあるし、ブラウザの検索欄とかで試すとちゃんと有効になるんですが、vimで使うとダメ。インサートモードを抜けるだけで日本語入力がオフにならない。

##set imdisableを設定

Mac Vim や Kaoriya Vim じゃないとダメ。

#うまくいった方法→Karabinerのキー設定

結局、Karabinerを使った方法がうまくいきました。

このためだけにソフト一つ入れるのは気が引けますが、僕の場合はもともと親指シフトのために使ってたので、そこのハードルはなかったですね。

そしてKarabinerにはもともと「`Esc`を押すと、`Esc`と`英数`を押したことにする」という設定項目があります。普段Vimで`Esc`でインサートを抜ける人はこれを使えばヨシ。

でも、`Ctrl+[`についての設定項目はナシ。`Esc`はフォームポジションから遠いので、Vimでインサートから抜ける時は`Ctrl+[`を使いたいんですよね。なので自分でxmlを書いてやる必要があります。

##private.xmlを書く

Karabinerの設定を開いて`Misc & Uninstall`タブから`Open private.xml`をクリックします。

適当なエディタで開いて、中身をこんな感じにします。

```xml:private.xml
<?xml version="1.0"?>
<root>
  <item>
    <name>Control+[ to Control+[+EISUU</name>
    <identifier>private.ctrl+[2ctrl+[+eisuu</identifier>
    <autogen>
      __KeyToKey__
      KeyCode::BRACKET_RIGHT,ModifierFlag::CONTROL_L,
      KeyCode::BRACKET_RIGHT,ModifierFlag::CONTROL_L,
      KeyCode::JIS_EISUU
    </autogen>
  </item>
</root>
```

`<root>`の中に、`<item>`をどんどん追加していけば良いです。

Karabinerの設定画面では、この`<item>`をオン・オフの単位として、チェックボックスが表示されます。

`<name>`は`<item>`の名前。

`<identifier>`は、Karabinerがアイテム同士を区別するための文字列です。
だからまあ、他と被らなきゃなんでもいいんですが、`private.`から始めるといいってどっかに書いてありました。

`<augogen>`これが肝心の中身です。

今回使う設定項目は`__KeyToKey__`です。何かキーが押された時に、別のキーが押されたことにするものです。

基本的には`KeyCode::キーの名前`を`,`で並べて書けばよくて、

「一つ目の`KeyCode`が押された時、二つ目以降の`KeyCode`が押されたことにする」と解釈されます。

一つ目だけが入力で、二つ目以降は全部出力なわけです。

`ModifierFlag`は、「〜を押しながら」みたいな意味です。僕はそう理解してます。

ということで、今回のコードを解釈すると次のようになります。

```
CONTROL_Lを押しながらBRACKET_RIGHTが押された時、

CONTROL_Lを押しながらBRACKET_RIGHTが押され、さらにJIS_EISUUが押されたことにする
```

という意味になります。

あとはこの`private.xml`を保存して、Karabiner設定画面の`Change Key`タブに戻って、`Reload XML`を押してやれば、今作った設定項目が現れます。

他にも「特定のアプリケーションを使っている時だけ有効にする」とかいろいろ設定できるオプションがあるので、そうしたい場合は調べてみてください。

#え、BRACKET_RIGHT?????

Vimでインサートモードを抜けるショートカットは`Ctrl+[`です。

`[`←これ、「左」じゃない？？？

`BRACKET_LEFT`じゃない？？？

はい。そうなんですよね。ず〜〜っと、設定を`BRACKET_LEFT`で書いてて、全然うまくいかなくて、一度「うまくいきませんでした。」っていう記事を書こうとしていたほどです。

参考にしていた記事でも、`BRACKET_LEFT`って書いてましたからね。そのまま真似してるのにどうしてうまくいかないんだと。

##キーが違う


押したキーのコードを教えてくれるページで、いろいろキーを押してみて、ようやく間違いに気づきました。

こちらです。

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code

ここの中ほどの`Try it out`の所で試せます。

どう見ても開発者向けのドキュメントで、「キーを教えてくれるサービス」という感じじゃないんですけど

「キーを教えてくれるサービス」として見つけた奴は、なんか微妙に違う表現(`Bracket_Open`とか)をしてくるので、イマイチ使えませんでした。

さて。ここで`[`キーを押してみると、

`code='BracketRight'`

って出るんですよね。

ここまできてついに気づきました。

「USキーボードだと、この位置に`]`があるんじゃないのか…？」

画像検索して調べたらたしかにそうなってました。

はい。

ということで、どうやらKarabinerの設定ファイルは、こちらのUSキーボード基準のKey Codeを書かなきゃいけないようなんですね。

Vimのショートカットはあくまで`[`でいけるので、なんか不思議ですけども。

僕が参考にした記事の執筆者は、恐らくUSキーボードを使っていたのでしょう。


#USキーボードのVimショートカットについて思ったこと

##`Ctrl`

`Ctrl`押しにくくないですかね。

JISキーボードだと、左手小指`A`のすぐ左にあるので、すぐ押せるんですけど、

USキーボードだと、そこにあるの`CapsLock`ですよね？

`Ctrl`を押すには、左手小指をグッと下に下げないといけないですよね？

それとも、あんまり使わないんですかね…？基本的に`ESC`でインサートモードを抜けている…？

でもそれでも、ウィンドウ操作とかしようと思ったら`Ctrl+w`を押さなきゃいけないはず。

う〜んわからない。

##`[`

でも`[`の位置はいいですね。JISキーボードより一つ左にあるから、インサートモードを抜ける時に押しやすい。

ということで、良いところは採用しましょう。

Karabinerの設定xmlをこうしてやりました。

```xml:private.xml
<?xml version="1.0"?>
<root>
  <item>
    <name>Control+[ to Control+[+EISUU</name>
    <identifier>private.ctrl+[2ctrl+[+eisuu</identifier>
    <autogen>
      __KeyToKey__
      KeyCode::BRACKET_RIGHT,ModifierFlag::CONTROL_L,
      KeyCode::BRACKET_RIGHT,ModifierFlag::CONTROL_L,
      KeyCode::JIS_EISUU
    </autogen>
    <autogen>
      __KeyToKey__
      KeyCode::BRACKET_LEFT,ModifierFlag::CONTROL_L,
      KeyCode::BRACKET_RIGHT,ModifierFlag::CONTROL_L,
      KeyCode::JIS_EISUU
    </autogen>
  </item>
</root>
```

`BRACKET_LEFT`にも同じ設定を追加してやりました。JISキーボードだと`@`にあたります。

これで`Ctrl+@`でも`Ctrl+[`でも同じ動作ができるし、`@`は`[`より一つ左側にあって押しやすいので、快適ですね。

でも代わりに`Ctrl+@`にもともと割り当てられているショートカットが使えなくなりましたね。

##`Ctrl+@`のショートカット

調べてみると

「前回挿入したテキストを挿入して、インサートモードを終了する」だそうです。

なるほど、使ったことはないけど、使おうとして使っていくと便利なのかも…？

でも、USキーボードの@って`Shift+2`で出すんですよ。

ってことはこのショートカット、`Ctrl+Shift+2`を押す想定ってことですよね？

押しづらいですよね？押しづらい位置にあるのは、あんまり使われる想定で作ってないってことですよね？

じゃあ潰してもいいかな。「いやいや、`Ctrl+@`は頻繁に使うぞ！！」という方がいましたら教えてください。