きみはねこみたいなにゃんにゃんなまほう

ねこもスクリプトをかくなり

Karabiner-Elements と AppleScript で background のアプリに特定のキーストロークを送る

ターミナルやエディタでコーディングしつつ、参考書を表示しているKindleのページ送りをしたかったのが動機です。 表題で言っている background のアプリとは最前面(foremost)ではないウィンドウで動作しているアプリを指しています。

指定したアプリ向けにキーストロークを送る AppleScript を Karabiner-Elements で特定のキーにより実行することで実現します。 「background のアプリに」と言いつつ実際にやっていることは、一瞬 foremost に持ってきてキーを送って元のアプリに戻す、という処理です。

AppleScript の用意

アプリにキーストロークを送る send-key.applescript を用意します。 AppleScript を書くのは初めてですが自然言語志向すぎて胸焼けしそうですね。

on run argv
  if (count of argv) < 2 then
    log "send-key [TARGET_APP] [KEY_CODE]"
    log "KEY_CODEs: 123(LEFT), 124(RIGHT), ..."
    error number -1721
  end if

  set targetApp to (item 1 of argv as text)
  set keyCode to (item 2 of argv as number)

  set currentApp to (path to frontmost application as text)

  activate application targetApp
  tell application "System Events" to key code keyCode
  activate application currentApp
end run

シンプルに書きたい人は変数を埋め込んで以下のようにしてもOKです。

set currentApp to (path to frontmost application as text)
activate application "Kindle"
tell application "System Events" to key code 123
activate application currentApp

事前に以下のように動作確認をしておきます。osascriptAppleScript をシェルから起動するためのものらしいです。

osascript send-key.applescript Kindle 124

これで Kindle のページが進んで元のアプリが frontmost になっていれば成功です。

background のアプリに直接キーストロークを送る仕組みが見つからなかったので、 一度ターゲットのアプリを activate してからキーストロークを送り元のアプリを再び activate しています。 なので一瞬ウィンドウがチカチカします。ホームメイド感がありますね。

Karabiner-Elements の設定

Karabiner-Elements に前述のスクリプトを起動するキーの設定をします。 デフォルトだと ~/.config/karabiner みたいです。

f:id:lightbulbcat:20201121220129p:plain

以下のような感じで profiles[].complex_modifications.rules に設定を追加します。 全体は長いので、今回関係のないフィールドは省略しています。

設定の肝は from のキーに対して shell_command で任意のコマンドを実行可能な点です。 これができるだけでも Karabiner の用途はかなり広がりますね。

ここでは適当に Command + 1 でページ送り、Command + 2 でページバックするようにしています。

{
  "profiles": [
    {
      "complex_modifications": {
        "rules": [
          {
            "description": "Kindleのページ移動",
            "manipulators": [
              {
                "from": {
                  "key_code": "1",
                  "modifiers": {
                    "mandatory": ["command"],
                    "optional": ["any"]
                  }
                },
                "to": [{"shell_command": "osascript /path/to/send-key.applescript Kindle 123"}],
                "type": "basic"
              },
              {
                "from": {
                  "key_code": "2",
                  "modifiers": {
                    "mandatory": ["command"],
                    "optional": ["any"]
                  }
                },
                "to": [{"shell_command": "osascript /path/to/send-key.applescript Kindle 124"}],
                "type": "basic"
              }
            ]
          },

設定ファイルの構造については Karabiner-Element のドキュメント をご覧ください。

更新したら「Restart Karabiner-Elements」をすれば早速反映されます。

サボったところ

Karabiner-Element の設定をいい感じにしたらいけるかもしれませんが、調べるのが面倒で放置している箇所です。

  • Kindle を起動していない時に設定したキーを打つと問答無用で Kindle が立ち上がってくる
  • 他にもあるかも…

快適にコードを書きたいというのが当初の目的なので、時間はコーディングに割くべきと、多少の不具合には目をつぶっています(正当化)。