はじめに
Karabiner-ElementsとはKarabinerの後継であり、macOSのキーバインド変更を行うためのアプリケーションである。特定のアプリケーションでのみ動作するキーバインドや、あるいは特定のキーと併用された場合にのみ動作をするといった複雑な設定を与えることができ、このような複雑な設定を_Complex modifications_と呼ぶ1。このComplex modificationsはJSON形式のファイルで管理することができ、GitHubとTravis CIを使うことでこのJSONに対してCIができる。この記事ではこのようなCIを構成する方法について解説する。
また、筆者が作成したものが下記のリポジトリーに置かれている。
Karabiner CLI
実はKarabiner-ElementsにはCLIが同梱されており、下記のように使うことができる。
$ "/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli" --help
A command line utility of Karabiner-Elements.
Usage:
karabiner_cli [OPTION...]
--select-profile arg Select a profile by name.
--set-variables arg Json string: {[key: string]: number}
--copy-current-profile-to-system-default-profile
Copy the current profile to system default
profile.
--remove-system-default-profile
Remove the system default profile.
--lint-complex-modifications complex_modifications.json
Check complex_modifications.json
--version Displays version.
--version-number Displays version_number.
--help Print help.
Examples:
karabiner_cli --select-profile 'Default profile'
karabiner_cli --set-variables '{"cli_flag1":1, "cli_flag2":2}'
CIではこのCLIの--lint-complex-modifications
オプションを利用する。
Travis CIでの手順
GitHub上のリポジトリーにComplex modificationsのJSONファイルが設置されているとして、次のような方法で行う。
- Travis CIのmacOS環境にhomebrew + caskでKarabiner-Elementsをインストール
- Bashスクリプトを利用してフォルダー内のJSONを探索
-
karabiner_cli
で(2)のJSONを検査
このような感じであり、具体的には次のような.travis.yml
を用いた。
os: osx
osx_image: xcode11
language: generic
install:
- brew cask install karabiner-elements
script:
- ./test.sh
このあとでtest.sh
からkarabiner_cli
を起動して、それの終了コードを検査するだけである。
#!/usr/bin/env bash
set -eo pipefail
SCRIPT_DIRECTORY="complex_modifications"
for FILENAME in `ls ./$SCRIPT_DIRECTORY`; do
'/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli' \
--lint-complex-modifications \
"${SCRIPT_DIRECTORY}/${FILENAME}"
if [ $? != 0 ]; then
exit 1
fi
done
まとめ(余談)
最初、Karabiner-ElementsのCIを作りたいと思ったときはopen
コマンドとkarabiner://
URLを利用するというのを考えていた。Karabiner-Elementsはkarabiner://
からインターネットやローカルにあるJSONファイルをインポートすることができるので、これでロードできたらOKというようなCIを作ろうとした。しかし、そのためにはどうしてもKarabinerのGUIを操作する必要があったので、次のようなAppleScriptを利用して強引に操作するという作戦を実行した。具体的にはopen "karabiner://......"
を実行すると次のようなWindowが出現する。
注目してほしいのは、これがもしJSONに問題がある場合はImport
ボタンが押せないことである。
これを利用して次のようなAppleScriptを用意した。これは(1)Import
ボタンを押してみて、次に(2)Cancel
ボタンを押してみる。もしここで(2)のCancel
ボタンを押すことに成功したということは、(1)でImport
ボタンが押せなかったことを意味する。したがって(2)が成功したならば、JSONは壊れていると判断する。
tell application "Karabiner-Elements" to activate
tell application "System Events"
tell process "Karabiner-Elements"
tell window "Karabiner-Elements Preferences"
click button "Import" of sheet 1
delay 1
set result to ""
try
click button "Cancel" of sheet 1
on error
set result to "Success"
end try
if (result is not "Success") then
error number -1
end if
end tell
end tell
end tell
これをTravis CI上で実行したものの失敗に終った。今のmacOSはSystem Events
といった何かしらのアプリケーションが、それとは違う別のアプリケーションを操作する場合は、アクセシビリティーのセキュリティをユーザーが許可しなければならない。かつてはこのセキュリティー権限を管理しているデータベースファイルをsqlite3
コマンドで操作することができたらしいが、現在は絶対にGUIで操作しなければならない。もし自動でこの権限を操作できてしまうならば、マリシャスなアプリケーションはまず自動でセキュリティーを解除し、そのあとで他のアプリケーションを操作してしまうため、ここにGUIを求めるのはセキュリティー上の理由において正しいと思う。ともかくこういういった理由でこの作戦は失敗か、あるいはTravis CIの中の人にお願いしてApple Scriptのインタープリターにあらかじめセキュリティー許可を与えてもらうといった方法をとるしかなく、かなり途方に暮れていた。そのあとでもう一度調べなおしてみたところ参考文献の情報に出会い、この記事の方法でCIができることとなった。
参考文献
- Is there a JSON schema for Karabiner configs? (GitHub Issue of Karabiner-Elements)
- Import file from another site (Karabiner-Elements README.md)
この他にもAppleScript関連のサイトをいくつか読んだはずだが、どれを読んだのかもう分からなくなってしまった……
-
Complex modificationsと対比して、「
a
をb
にする」といったキーバインドのことを_Simple modifications_と言う。 ↩