【Karabiner-Elements+Goku】インポート用の設定ファイルを作成する

※使用環境: `Goku 0.2.5`, `Karabiner-Elements 12.4.0`, `jq 1.5`, `macOS 10.13.6`

# インポート用の設定ファイルを作る理由

### GUIのみでルールをON/OFFしたい
Karabiner-Elementsは、旧Karabinerと違い、設定画面から特定のルールをON/OFFする機能がありません。インポート用の設定ファイルを作って、`~/.config/karabiner/assets/complex_modifications`に保存しておけば、擬似的にではありますが、設定画面からON/OFFを切り替えられるようになります。

### 特定のルール設定を共有したい
インポート用の設定ファイルを作っておけば、gistなどを使って簡単に設定を共有することができます。
設定ファイルの共有には、[公式サイト](https://pqrs.org/osx/karabiner/complex_modifications/)を使う方法もありますが、結構重い手順を踏む必要があるのと、Karabiner-Elementsの以外の知識が必要になってくるため、ちょっとした設定をサクッと共有したい場合には向きません。

また複数のProfileで同じルールを共有したい場合にも活用できます。

### Gokuから`karabiner.json`を直接更新したくない
既存のルールをすべてGokuに移行するまでの間は、Gokuから`karabiner.json`を直接更新してしまうと移行前のルールが消えて困ることになります。Gokuを使って記述したルールを、インポート用の設定ファイルに書き出して、Karabiner-Elementsの設定画面からルールを追加するようにすれば、そういった問題を避けられます。

# 手順
1. Gokuでルールを記述
2. `goku`の`--dry-run-all`オプションと`jq`を使って、インポート用設定ファイルを生成
3. `assets/complex_modifications`に配置して、Karabiner-Elementsへ反映

## 1. Gokuでルールを記述
- インポート用設定ファイルにしたいルールを、Gokuを使って記述します

```clojure:sample_rules.edn
{:main [{:des "[Terminal]  Cmd+S -> Ctrl+S" :rules [[:!Cs :!Ts :terminal]]}
        {:des "[Terminal]  Cmd+T -> Cmd+T, EISUU" :rules [[:!Ct [:!Ct :japanese_eisuu] :terminal]]}]
 :applications {:terminal ["^com\\.googlecode\\.iterm2$" "^com\\.apple\\.Terminal$"]}}
```

## 2. `goku --dry-run-all`と`jq`を使って、インポート用設定ファイルを生成
- `goku --dry-run-all`は、生成した`karabiner.json`を標準出力に書き出します
- その結果をpipeで`jq`に渡して、インポート用設定ファイルを生成します

```sh
$ GOKU_EDN_CONFIG_FILE=sample_rules.edn
$ goku --dry-run-all \
    | jq --arg profile "Default" '(.profiles | map(select(.name == $profile))[0] | .complex_modifications.rules)' \
    | jq --arg title "Sample Rules" '{"title": $title, "rules": .}' \
    > sample_rules.json
```

## 3. Karabiner-Elementsへの反映
- `assets/complex_modifications`にインポート用設定ファイルを配置して、Karabiner-Eelementsへ反映します。

```sh
$ cp -p sample_rules.json ~/.config/karabiner/assets/complex_modifications/
```

- Karabiner-Elementsの設定画面から「Complex Modifications」を選択し、左下の「Add rule」ボタンをクリックすると、作成したルールが追加可能になっていることが確認できます。

![karabiner_sample_rule2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32927/70af6faa-f71a-a10d-ea28-2a071d751612.jpeg)


# 補足
## シェルスクリプト
設定ファイル名と`title`名を渡して実行すれば、Karabiner-Elementsへ反映する簡易的なシェルスクリプトです。中身はこの記事で書いている内容と同じです。使い方は`-h`オプションで表示されるヘルプを確認してください。

- [QuestionDriven/generate_json.sh](https://gist.github.com/QuestionDriven/214110f5f65e4d49ac96f16f06114463)

```sh
$ ./generate_json.sh -h
```



## インポート用設定ファイルの構造
[公式サイト](https://pqrs.org/osx/karabiner/complex_modifications/)にあるインポート用設定ファイルの中身を確認すると、JSONの構造は以下のようになっています。[^1] 

[^1]: 公式ドキュメントには、インポート用設定ファイルの定義についての記載はありませんでした。

```js:インポート用.json
{
  "title": "Sample Rules",
  "rules" : [ {
    "description" : "Rule1",
    "manipulators" : [ ... ] 
  }, {
    "description" : "Rule2",
    "manipulators" : [ ... ]
  }]
}
```

- `"title"`はインポート用設定ファイル特有の記述で、設定画面で「Add Rule」をクリックした時に表示される
- `"rules"`以下は`karabiner.json`の`complex_modifications.rules`と同じ


## `karabiner.json`の構造

`"complex_modifications"`の`"rules"`のみがインポート用設定ファイルに必要な箇所です。

```js:karabiner.json
{
  "global": { ... },
  "profiles" : [ {
    "name" : "Sample1",
    "simple_modifications" : [ ... ],
    "complex_modifications" : {
      "rules" : [ {                  // <-- この"rules"だけが必要 
        "description" : "Rule1",     //
        "manipulators" : [ ... ]     //
      }, {                           //
        "description" : "Rule2",     //
        "manipulators" : [ ... ]     //
      }]                             //
    },
    ...
  }, {
    "name" : "Sample2",
    "simple_modifications" : [ ... ],
    ...
  }]
}
```

#参考資料
- [pqrs-org/KE-complex_modifications](https://github.com/pqrs-org/KE-complex_modifications)
- [Karabiner-Elements単体で親指シフト定義ファイルを作るジェネレーター](https://mono96.jp/thumb-shift/37332/)
- [Karabiner-Elementsの設定項目をまとめました#設定ファイルの保存場所について](https://qiita.com/s-show/items/a1fd228b04801477729c#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BF%9D%E5%AD%98%E5%A0%B4%E6%89%80%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [Karabiner-Elementsの設定が超絶楽になるDSL「Goku」](https://qiita.com/QuestionDriven/items/da4459c471fc3def031f)
- [jq Manual](https://stedolan.github.io/jq/manual/)