Karabiner の private.xml 設定方法


Realforce 86U を mac に接続して使う際、キーマップを Karabiner で自分好みに変更したので、そのときの手順をまとめました。


# 1. デフォルトのキーマッピングを調べる

Realforce 86U はこんな感じのキーボード。
[Realforce 86Uの画像](http://ecx.images-amazon.com/images/I/71Dj7t8IT8L._SL1500_.jpg)

US配列で、かつ Windows 用キーボードなので、まず mac に接続した時に、デフォルトでどのキーがどういう挙動をするのかを調べる必要があります。

### Karabiner デバッグモードを起動する

```
$ sudo sysctl -w karabiner.debug=1
$ sudo tail -f /var/log/system.log # OS X 10.8+
```

これでキーを押すたびに以下のようなログが出ます。
以下は、アプリケーションキー（スペースキーから見て右2つ目のキー）を押した時の例です。

```
Dec 29 15:18:38 hodaka kernel[0]: org.pqrs.Karabiner --Debug-- KeyboardEventCallback [ caught]: eventType 10, flags 0x80000000, key 0x006e, kbdType  40, repeat = 0
Dec 29 15:18:38 hodaka kernel[0]: org.pqrs.Karabiner --Debug-- KeyboardEventCallback [sending]: eventType 10, flags 0x00000000, key 0x006e, kbdType  40, repeat = 0
```

\[ caught\] は押されたキーが何かを表すもので、key のところを見ると、```0x006e``` となっています。
\[semding\] はどのキーとしてコンピュータに命令を送るかを表すもので、こちらも ```0x006e``` となっています。

KeyCode をまとめたファイルが[こちら](https://github.com/tekezo/Karabiner/blob/version_10.5.0/src/bridge/generator/keycode/data/KeyCode.data)にあるので、これを参照して、```0x006e``` がなんのキーかを調べると 'PC_APPLICATION' と書いてあります。

つまり、アプリケーションキーを押した時には、'PC_APPLICATION' として入力され、'PC_APPLICATION' として命令を送っているということです。mac はアプリケーションキーには対応していないので、無駄なキーということになりますね。Windows キーボードと Apple キーボードの対応関係については、[こちら](http://www.trinityworks.co.jp/software/WinKPro/) のサイトに記載してあったので、適宜参考にしてください。

windows キーや、Alt キー、その他挙動がよくわからないキーに関しても同様の手順で調べていきます。

### Karabiner デバッグを終了する
常にログを吐き続けてしまうので、調べ終わったら以下のコマンドで終了してください。

```
$ sudo sysctl -w karabiner.debug=0
```



# 2. private.xml の設定

XML 形式で設定を記述していきます。全体を root 要素で囲んで、その中に設定を記述した item 要素を追加していきます。item 要素内の設定は、基本的に以下のタグを使って記述されます。

| タグ | 意味 |
| :-- | :-- |
| \<name\> | Karabiner のプリファレンスに表示させる名前 |
| \<identifier\> | private.[hoge] の形で設定。hoge の部分は、一意に決めなければならない。ここを設定しないと、プリファレンス上でのチェックボックスが表示されない。 |
| \<autogen\> | 振る舞いの設定 |


## autogen の書き方

キーコードのリストが公式より示されているので、随時参照しながら、設定を記述していきます。

+ [List of KeyCode.](https://github.com/tekezo/Karabiner/blob/version_10.5.0/src/bridge/generator/keycode/data/KeyCode.data)
+ [List of ModifierFlag.](https://github.com/tekezo/Karabiner/blob/version_10.5.0/src/bridge/generator/keycode/data/ModifierFlag.data)

### \_\_KeyToKey\_\_ シンタックス

基本的には、以下のような構成で成り立っています。

```
<autogen>
  __KeyToKey__
  FromKey,
  ToKey,
  ToKey,
  ToKey,
  ...
</autogen>
```

FromKey と ToKey は両方とも、KeyCode（1つ）と ModifierFlag（任意、複数指定可）より構成されています。
上の構成を見ていただければわかるかと思いますが、FromKey は1つのみ指定可能です。FromKey 内で指定できる KeyCode はひとつであるため、J と K の2つの KeyCode を 1つの FromKey 内で指定することは不可能なため、「J + K をタブキーに変換する」といったようなことはできません。

#### ex1. Key to Key

以下では、スペースキーをタブキーに変換しています。

```
<autogen>__KeyToKey__ KeyCode::SPACE, KeyCode::TAB</autogen>
```

#### ex2. Modifier + Key to Key

以下では、レフトコントロールキー + スペースキーをタブキーに変換しています。

```
<autogen>
  __KeyToKey__
  KeyCode::SPACE, ModifierFlag::CONTROL_L,
  KeyCode::TAB
</autogen>
```

ここでひとつ注意事項があります。
FromKey 内で ModifierFlag を何も指定しなかった場合、autogen はいかなる ModifierFlag でも動いてしまいます。
つまり、上の例では、ModifierFlag の ModifierFlag が明示されていないので、もちろん、レフトコントロールキー + スペースキーはタブキーに変換されますが、任意の修飾キーを加えた、シフトキー + レフトコントロールキー + スペースキーもタブキーに変換されてしまいます。

これを防ぎ、レフトコントロールキー + スペースキーのときのみタブキーに変換させたい場合は、以下のように設定します。

```
<autogen>
  __KeyToKey__
  KeyCode::SPACE, ModifierFlag::FN | ModifierFlag::NONE,
  KeyCode::TAB
</autogen>
```

修飾キー「何もない」というのを無理やり設定するやり方です。


#### ex3. Modifier+Key to Modifier+Key

以下では、レフトコントロールキー + スペースキーを、レフトコントロールキー + タブキーに変換しています。

```
<autogen>
  __KeyToKey__
  KeyCode::SPACE, ModifierFlag::CONTROL_L,
  KeyCode::TAB,   ModifierFlag::CONTROL_L
</autogen>
```

#### ex4. 複数修飾キーを設定する

以下では、レフトコントロールキー + fnキー + スペースキーをタブキーに変換しています。

```
<autogen>
  __KeyToKey__
  KeyCode::SPACE, ModifierFlag::CONTROL_L | ModifierFlag::FN,
  KeyCode::TAB
</autogen>
```

#### ex5. 複数のキーに変換する

以下では、スペースキーをタブキー + リターンキーに変換しています。

```
<autogen>
  __KeyToKey__
  KeyCode::SPACE,
  KeyCode::TAB, KeyCode::RETURN
</autogen>
```

なぜ、「スペースキー + タブキー がリターンキーに変換」と解釈されないかは、上に書いたとおり、FromKey は1つと Karabiner の仕様で定まっているからです。


### \_\_KeyOverlaidModifier\_\_ シンタックス

少し複雑かもしれないのですが、USキーボードを使っている方はおそらくこのシンタックスを使うことになるかと思うので、紹介します。

基本的には、FromKey to ToKey ですが、ひとつ違うのは、FromKey キーが押されている間だけ、そのキーを修飾キーとして扱う設定を追加できるということです。

以下の例では、レフトオプションをJIS英数に変換しますが、レフトオプションが押されている間だけ、そのキーがレフトコマンド修飾キーとして働きます。

```
<autogen>
  __KeyOverlaidModifier__
  KeyCode::OPTION_L,
  KeyCode::COMMAND_L,
  KeyCode::JIS_EISUU
</autogen>
```



## 特定のデバイス、アプリケーション上でのみキーをリマップする設定

### 特定のアプリケーション上でのみ動作するように設定

root 要素配下に appdef 要素を追加し、その下に、appname 要素（好きな名前でよい）、equal 要素（決まった値でなければならない。調べ方は以下を参照。）を設定します。

#### equal 要素に記述すべき値の調べ方

1. 指定したいアプリケーションを立ち上げる
2. EventViewer を起動する

	![ここを参照](https://pqrs.org/osx/karabiner/img/eventviewer-menu.png)


3. App タブをクリックし、指定したいアプリケーションの「Application Bundle Identifier」項目に書かれた値が equal 要素に指定すべき値。Chrome であれば com.google.Chrome となる。

	![Application Bundle identifier](https://pqrs.org/osx/karabiner/img/eventviewer-app.png)



以上をふまえて設定すると以下のようになります。
以下は、Chrome を起動しているときのみ、スペースキーをタブキーに変換するように設定しています。

```
<?xml version="1.0"?>
<root>

  <appdef>
    <appname>CHROME</appname>
    <equal>com.google.Chrome</equal>
  </appdef>

  <item>
    <name>Space to Tab in App Store.app</name>
    <identifier>private.appdef</identifier>
    <only>CHROME</only> <!-- only 要素の値は、appname 要素の値を指定する -->
    <autogen>__KeyToKey__ KeyCode::SPACE, KeyCode::TAB</autogen>
  </item>

</root>
```

### 特定のデバイス上でのみ動作するように設定

root 要素配下に devicevendordef 要素を追加し、その下に、vendorname 要素（好きな名前でよい）、vendorid 要素（決まった値でなければならない。調べ方は以下を参照。）を設定します。
そして、もうひとつ、root 要素配下に deviceproductdef 要素を追加し、その下に、productname 要素（好きな名前でよい）、productid 要素（決まった値でなければならない。調べ方は以下を参照。）を設定します。


#### vendorid, productid 要素に記述すべき値の調べ方

1. 最初は上と同じで、EventViewer を起動する
2. Devices タブをクリックし、VendorID と ProductID を調べる

	![VendorID, ProductID](https://pqrs.org/osx/karabiner/img/eventviewer-devices.png)


以下は、自分のキーボードを接続している時のみ、スペースキーをタブキーに変換するように設定しています。

```
<?xml version="1.0"?>
<root>

  <devicevendordef>
    <vendorname>LOGITECH</vendorname>
    <vendorid>0x046d</vendorid>
  </devicevendordef>

  <deviceproductdef>
    <productname>MY_KEYBOARD</productname>
    <productid>0xc52b</productid>
  </deviceproductdef>

  <item>
    <name>Space to Tab in MY_KEYBOARD</name>
    <identifier>private.deviceproductdef</identifier>
    <device_only>DeviceVendor::LOGITECH, DeviceProduct::MY_KEYBOARD</device_only><!-- それぞれ、vendorname、productname を参照のこと -->
    <autogen>__KeyToKey__ KeyCode::SPACE, KeyCode::TAB</autogen>
  </item>

</root>
```



# 参考

+ [公式マニュアル](https://pqrs.org/osx/karabiner/xml.html.ja)
+ [\_\_KeyToKey\_\_ に関する git issue](https://github.com/tekezo/Karabiner/issues/187)