ぽよメモ

レガシーシステム考古学専攻

Karabiner-Elementsのプロファイルを動的に切り替え

2016/11/8現在,最新バージョンは0.90.64となり,デフォルトでプロファイル切り替え機能が実装されました.詳しくは以下に.

poyo.hatenablog.jp

きっかけ

Macの環境をmacOS Sierraのリリースと同時に新規インストールでまっさらにしました.
後期から研究室に居場所ができるので,手元に余っているMajestouch黒軸を置いて使おうかなと.そこでKarabinerをインストールしようとしたら

Karabiner - OS X用のソフトウェア より

macOS Sierraサポート状況

Karabinerは今のところmacOS Sierraでは動作しません。

Sierra対応は、まずは単純なキーの変更を行える機能をKarabiner-Elementsとして開発中です。 (設定画面を除くとSierra上で動作しています)

Karabinerのフル機能のSierra対応はKarabiner-Elementsが完成してから対応します。

https://github.com/tekezo/Karabiner-Elements

非常につらい…しかしkarabiner-elementsというソフトウェアが開発中であり,キーの変更は可能であることが分かりました.インストールし,手動で設定をしたところ確かにきちんと設定はできたのですが,複数のプロファイル切り替えを手動でする必要があり,面倒だなーと.

そこでPythonでUSB機器を監視し,特定のデバイスが接続されたときにKarabiner-Elementsの設定ファイルであるkarabiner.jsonを書き換えるようなスクリプトを書き,launchdを使ってデーモンとして登録することで動的な書き換えができるようになりました.

karabiner.jsonを設定

karabiner.jsonの基本的な設定は以下です.

{
    "profiles": [
        {
            "name": "Default",
            "selected": true,
            "simple_modifications": {
                "caps_lock": "japanese_kana",
                "right_shift":"japanese_eisuu"
            }
        }
    ]
}

キー割り当ては以下のようにします.

"simple_modifications": {
    "キーボード上のキー": "割り当てるキー",
    "right_shift":"japanese_eisuu"
}

試しにJIS配列のキーボードにおけるCapsLockをControlに,変換・無変換キーをそれぞれJIS配列Macにおける英数とかなに割り当てます.

{
    "profiles": [
        {
            "name": "Default",
            "selected": true,
            "simple_modifications": {
                "caps_lock": "left_control",
        "japanese_pc_nfer": "japanese_eisuu",
        "japanese_pc_xfer": "japanese_kana"
            }
        }
    ]
}

その他のキーの名称は以下のソースコード中にあります. https://github.com/tekezo/Karabiner-Elements/blob/master/src/share/types.hppk

複数のプロファイルを設定

簡単なことでprofiles以下に複数設定するだけです.

{
    "profiles": [
        {
            "name": "Default",
            "selected": true,
            "simple_modifications": {
                "caps_lock": "left_control"
            }
        },
        {
            "name": "Second",
            "selected": false,
            "simple_modifications": {
                "caps_lock": "left_control",
        "japanese_pc_nfer": "japanese_eisuu",
        "japanese_pc_xfer": "japanese_kana"
            }
        }
    ]
}

ここで,selectedという項目をtrueにするとそのプロファイルが有効になります.

karabiner_profile_changer

そこでこういうものをつくりました.

github.com

これは一定時間おきに接続されたUSBデバイスを監視し,外付けキーボードが接続されたときに特定のプロファイルを有効にします.
バイスやそれに紐付けるプロファイル名はcloneしたディレクトリ内にconfig.jsonを作製し,そこで指定することができます.また,監視する間隔およびkarabiner.jsonの場所を指定します.

実行する前準備として,lsusbおよびPythonのパッケージとしてPyUSBをインストールします.Macにはhomebrewがインストールされていることとします.

$ brew install lsusb
$ pip install --pre pyusb
$ git clone https://github.com/pddg/karabiner_profile_changer.git
$ cd karabiner_profile_changer
$ cp config.json.sample config.json
$ cp karabiner_profile_changer.plist.sample karabiner_profile_changer.plist

バイスを指定

config.jsonへの記述は以下のようにします.

{
    "default_profile": "Default",
    "config_file": "/path/to/karabiner.json",
    "interval": 10,
    "devices":[
        {
            "profile_name": "Device1",
            "vendor_id": "0x4d9",
            "product_id": "0x2011"
        }
    ]
}

このとき,karabiner.jsonにはDefaultDevice1というプロファイルが存在することとします.何も刺していない状態でmain.pyを動かすと,Defaultプロファイルのselectedtrueになります.
バイスの指定にはvendor_idproduct_idが必要になります.この値は16進数で記述する必要があります.

これら二つの値は幸いなことにkarabiner-elementsで簡単に知ることができます.
karabiner-elementsのlogというタブを開き,外付けキーボードを抜き差しすると以下のようなログが出ます.

f:id:pudding_info:20160926184203p:plain

このうちのひとつに着目すると,以下のようにvendor_idproduct_idを知ることができます.

f:id:pudding_info:20160926184207p:plain

これをconfig.jsonに記述すると,このデバイスとプロファイル名を結びつけることができます.もちろん複数のデバイスを登録し切り替えることができますが,現状USBデバイスのみしか対応はしていないため,Bluetoothキーボードでは使えません.

launchdに登録

launchdはinit等と同じデーモン管理をしています.リポジトリに同梱されている.plistファイルに,main.pyへのパス,pythonインタプリタへのパス,そしてユーザ名を記述し,保存します.
登録は以下のようにします.

$ cp karabiner_profile_changer.plist ~/Library/LaunchAgents/
$ launchctl load ~/Library/LaunchAgents/karabiner_profile_changer.plist

一度loadすると,次回からはOSの起動時に自動で起動します.
plistファイルを変更した場合はunloadしてからもう一度loadする必要があります.

まとめ

このスクリプトはあくまで記述したkarabiner.jsonに記述したプロファイルのselectedを書き換えるだけであり,それ以外の要素は改変しません.プロファイル名はわかりやすいようにデバイス名などにしておくことをオススメします.
短時間で書いたスクリプトですのでバグ等が存在する可能性があります.お気づきになられた場合はプルリクエスト等でお知らせください.