いものやま。

雑多な知識の寄せ集め

Karabiner-Elementsで英数/かなの切り替えをトグルにしてみた。

Macを使っててちょっと困るのが、英数/かなの切り替えがトグルでないこと。

まぁ、トグルでなくて明示的に指定した方が分かりやすい、という人もいるけど、仕事では(残念ながら)Windowsを使っているので、MacWindowsで操作が違うのは、けっこう面倒。
あと、自分の場合、(絵を描くわけでもないけど)マウスの代わりにペンタブを使っているので、ペンを持った状態のままキーを叩こうとすると、右手の親指を動かすことが出来ず、「かな」キーを押しづらいというのもある。

そんなわけで、以前はKarabinerを使ってトグル切り替え出来るようにしてたんだけど、困ったことに、MacSierraになったときに、Karabinerは使えなくなってしまった。
これに困った人はたくさんいて、代替ソフトがいろいろ出てたんだけど、どれも微妙な感じ。

なので、ずっと我慢して、かなに切り替える場合、右手を下に引いて右手の人差し指で「かな」キーを押すとかいう無茶をやってたんだけど、久々に調べたら、Karabinerの後継であるKarabiner-Elementsで英数/かなのトグル切り替えが出来るようになったとのこと。
そこで、Karabiner-Elementsを使って英数/かなのトグル切り替えを出来るようにしてみた。

ダウンロード&インストール

ダウンロードは、以下のサイトから:

Karabiner - Software for macOS

ダウンロードしたら、dmgファイルを開いて、その中に入っているpkgファイルをダブルクリックすれば、インストーラが起動する。
あとは、インストーラの指示に従ってインストールすればOK。

インストールが終われば、アプリケーションフォルダにKarabiner-Elements.appとKarabiner-EventViewer.appがインストールされる。

設定

ここで行う設定は、以下の2つ:

  • 「英数」キーを押したとき、英数/かなをトグルする
  • 'ろ'のキー(右Shiftの左側のキー)を押したときに、バックスラッシュ(\)を入力し、Shift+'ろ'を押したときに、アンダースコア(_)を入力する

後者の設定もWindowsのキーマップに似せるためのもので、何も設定してないとバックスラッシュではなくアンダースコアが入力されるので、 \TeXを使うときに地味に不便だったりする。

何はともあれ、まずはKarabiner-Elementsを起動。
アプリケーションフォルダを開き、Karabiner-Elements.appを開く。

f:id:yamaimo0625:20180114124349p:plain

起動すると、おそらく次のような設定ダイアログが表示されるはず。

f:id:yamaimo0625:20180114130417p:plain

表示されない場合、メニューバーにあるKarabiner-Elementsのアイコンをクリックし、そこから"Preferences..."を選択すればいい。

この設定ダイアログにはいくつかのページがあり、上の画像のページ("Simple Modifications")では、あるキーを別のキーに置き換えるということが出来る。
ただ、今回はそんなシンプルな話ではないので、ここは使わない(使えない)。

ちなみに、"Virtual Keyboard"ページでは、キーボードの種類が選べるので、適切なキーボードになっているか、確認しておいた方がいい。

f:id:yamaimo0625:20180114131150p:plain

今回行うような複雑な設定には、"Complex Modifications"ページを使う。
ただ、その前にJSONファイルを用意しておかないといけない。

まず、ターミナルなどを使って、以下のフォルダを開く:

$ open ~/.config/karabiner/assets/complex_modifications/

ここに、適当な名前のJSONファイル(例えば、my_option.json)を用意して、以下の内容を入力して保存:

{
  "title": "自分用の設定",
  "rules": [
    {
      "description": "英数キーで入力をトグルできるようにする",
      "manipulators": [
        {
          "type": "basic",
          "description": "入力ソースが英字の場合、ひらがなにする(入力ソースがひらがなの場合、上書きの必要なし)",
          "from": { "key_code": "japanese_eisuu" },
          "to": [ { "key_code": "japanese_kana" } ],
          "conditions": [
            {
              "type": "input_source_if",
              "input_sources": [ { "language": "en" } ]
            }
          ]
        }
      ]
    },
    {
      "description": "'ろ'にバックスラッシュ、Shift+'ろ'にアンダースコアを割り当てる",
      "manipulators": [
        {
          "type": "basic",
          "description": "'ろ'にバックスラッシュを割り当てる(Shift+'ろ'は、上書きの必要なし)",
          "from": { "key_code": "international1" },
          "to": [ { "key_code": "international3" } ]
        }
      ]
    }
  ]
}

この詳細については、後ほど。

ファイルが用意できたら、"Complex Modifications"ページを開き、"Add rule"をクリック。

f:id:yamaimo0625:20180114133335p:plain

以下のようなシートが表示されるはずなので、「自分用の設定」の"Enable All"をクリック。

f:id:yamaimo0625:20180114133508p:plain

すると、以下のようになるはず:

f:id:yamaimo0625:20180114133615p:plain

これで完成!

ちゃんと「英数」キーで英数/かなのトグルが出来るし、'ろ'でバックスラッシュ、Shift+'ろ'でアンダースコアが入力されるようになってるはず。

設定の詳細

ここからはオマケ。
上のJSONファイルでうまくいかなかったり、自分でKarabiner-Elementsの設定を行いたい人向け。

まず、Karabiner-Elementsの動作イメージを説明しておくと、Karabiner-Elementsが起動している場合、入力デバイス(キーボードやマウス)で起きたイベント(キーが押された、など)を、直接Macに渡すのではなく、Karabiner-Elementsを経由させてからMacに渡す、という感じになっている。
なので、JSONファイルでは、どのイベントをどのイベントに変換するか、というのを記述することになる。

詳細については、karabiner.json Reference Manual - Karabiner - Software for macOSを参照。

JSONファイルの構成

"Complex Modifications"のルールを記述するJSONファイルの全体構成は、以下のようになっている:

{
  "title": "(ルールセットのタイトル)",
  "rules": [
    {
      "description": "(ルール1の説明)",
      "manipulators": [
        {
          // 変換操作の内容1-1
        },
        ...
        {
          // 変換操作の内容1-n
        }
      ]
    },
    ...
    {
      "description": "(ルールmの説明)",
      "manipulators": [
        {
          // 変換操作の内容m-1
        },
        ...
        {
          // 変換操作の内容m-n
        }
      ]
    }
  ]
}

変換操作の記述

変換操作の記述は、以下のような感じ:

{
  "type": "basic",
  "description": "(変換操作の説明)",
  "from": {
    // 変換元のイベント
  },
  "to": [
    {
      // 変換後のイベント1
    },
    ...
    {
      // 変換後のイベントn
    }
  ],
  "conditions": [ // 変換操作を行う条件(オプション)
    {
      // 条件1
    },
    ...
    {
      // 条件m
    }
  ]
}

なお、toの他に、to_if_aloneto_if_held_downto_after_key_upto_delayed_actionなどもあるけど、省略。
基本的にはtoを使えばいいと思うので。

あと、conditionsはあってもなくてもいい。
指定した場合、条件が満たされたときだけ変換操作が行われるようになる。
今回の場合は、入力が英数のときだけ、「英数」キーを「かな」キーとして働かせることになるので、そのときに使っている。

fromに関して

変換元のイベントの記述は、以下のような感じ:

"from": {
  "key_code": "(入力されたキーのキーコード)",
  // 以下はオプション
  "modifiers": {
    "mandatory": [ // 必須なキー(組み合わせたときにだけ働く)
      "(必須なキーのキーコード)",
      ...
    ],
    "optional": [  // 一緒に押せるキー(組み合わせても働く)
      "(一緒に押せるキーのキーコード)",
      ...
    ]
  }
}

なお、key_codeの他に、consumer_key_codepointing_buttonanyというのもあり、そのいずれかを指定することになっている。
ただ、基本的にはkey_codeでOKのはず。

modifiersは、指定しなかった場合、他のキーと組み合わせたときには働かなくなる。
少しややこしいのだけど、以下のように考えればいいと思う:

やりたいこと modifiersの指定
他のキーと一緒に押されたときは、変換操作をやりたくない modifiersなし
特定のキーと一緒に押されたときだけ変換操作をやりたい modifiersmandatoryを指定する
特定のキーと一緒に押されたときにも変換操作をやりたい modifiersoptionalを指定する

例えば、今回だと、'ろ'のキー("international1")が押されたときにバックスラッシュのキー("international3")が押されたイベントを送るようにしてるんだけど、Shiftと一緒に押されたときにも変換処理が行われてしまうと、縦棒(|)が入力されてしまう。
なので、modifiersなしにすることで、Shiftと一緒に押されたときにはバックスラッシュのキーではなく'ろ'のキーがそのまま送られるようにしている。
(結果として、Shift+'ろ'でアンダースコアが入力される)

toに関して

変換後のイベントの記述は、以下のような感じ:

"to": [
  {
    "key_code": "(変換後のキーのキーコード)",
    // オプション
    "modifiers": [
      "(一緒に押されたとするキーのキーコード)",
      ...
    ],
    "lazy": false,
    "repeat": true
  },
  ...
]

なお、key_codeの他に、consumer_key_codepointing_buttonshell_commandselect_input_sourceset_variableというのもあり、そのいずれかを指定する。
基本的にはkey_codeのはず。

ちなみに、select_input_sourceを使うことで、入力ソースを切り替えるイベントを送ることも出来る。
最初はこれを試して、Safariとかでは問題なく動いたんだけど、ターミナルで入力ソースが切り替わらないという自分としてはかなり致命的な問題が生じたので、素直にキーコードを送るイベントを使うようにしている。

あと、lazyは他のキーが押されるまでイベント変換を遅延させるかどうかという設定、repeatは繰り返し変換を行うかどうかという設定。
まぁ、明示的に指定する必要があるケースはあまりなさそう。

conditionsに関して

変換操作を行うかどうかの条件にはいくつかタイプがある:

タイプ 説明
frontmost_application_if, frontmost_application_unless アプリのバンドル名、ファイルパスの条件
device_if, device_unless バイスの条件
keyboard_type_if, keyboard_type_unless キーボードの種類(ansiやjisなど)の条件
input_source_if, input_source_unless 入力ソースの条件
variable_if, variable_unless 変数の条件

それぞれのタイプで、指定する内容は異なってくる。

今回は、入力ソースが英字のときにだけ変換操作を行いたかったので、input_source_ifを使ってる。

input_source_ifは、以下のような感じ:

{
  "type": "input_source_if",
  "input_sources": [
    {
      "language": "(言語の正規表現)",
      "input_source_id": "(input source idの正規表現)",
      "input_mode_id": "(input modeの正規表現""
    },
    ...
  ]
}

なお、languageinput_source_idinput_mode_idはそれぞれオプショナルなので、特に問題がなければlanguageを指定しておくだけで十分。
ちなみに、これらの値はKarabiner-EventViewer.appを起動して、"Variables"ページを見ると、確認できる。

キーコードの確認について

あと、キーコードの確認も、Karabiner-EventViewer.appを起動すると、出来る。
"Main"ページを開いて適当なキーを押すと、そのキーのキーコードがテーブルの"name"列に表示されるので、それを使えばいい。

なお、"japanese_kana"や"japanese_eisuu"はエイリアスで、本来の名前はそれぞれ"lang1"、"lang2"となっている。
どんなエイリアスが使えるのかは、コードを確認する必要がある。

以下のリポジトリで、src/share/types.hppを参照するといい:

今日はここまで!