🌵

Hammerspoonで特定のアプリのみキーバインド設定する

2022/08/29に公開

https://zenn.dev/obregonia1/articles/419ae303355f54

以前この記事でHammerpoonで ctrl + n で↓キーとか ctrl + f で→キーにキーバインドしてて最近困ったことに気づいてこの設定を見直す必要があったので紹介したいと思います。

困ったことというのは最近Vimを使い出して色々試しているときに1ページ送る ctrl + f がHammerspoonで設定したキーバインドのせいでカーソルが一つ右に移動する挙動になってしまいました。

そこで特定のアプリだけキーバインドを有効にしたりできないのかなと思って調べてみたらできそうなのでやってみました。

キーバインドを関数化

前回の記事ではだいぶベタ書きでキーバインドの設定をしていたので関数化しておきます

local function keyCode(key, mods, callback)
  mods = mods or {}
  callback = callback or function() end
  return function()
    hs.eventtap.event.newKeyEvent(mods, string.lower(key), true):post()
    hs.timer.usleep(1000)
    hs.eventtap.event.newKeyEvent(mods, string.lower(key), false):post()

    callback()
  end
end
	
local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

これで ctrl + n で↓キーにしたいときは下記のように remapKey を呼べばいいのでだいぶすっきりしました。

remapKey({"ctrl"}, "n", keyCode("down"))

第一引数には修飾キーが入るんですが {"ctrl", "shift"} みたいに複数でも可能です。

特定のアプリのみでキーバインドを設定する

今回はとりあえず すべてのアプリで有効化するキーバインドChromeのみで有効化するキーバインド を分けて、アプリがアクティブになったタイミングでキーバインドのオン・オフをするようにしました。

local function switchHotKeys(enable)
    hotkeys = hs.hotkey.getHotkeys()
    if enable then
        for k, v in pairs(hotkeys) do
            v["_hk"]:enable()
        end
    else
        for n in pairs(limitedRemaps) do
            hotkeys[n]["_hk"]:disable()
        end
    end
end

local function handleGlobalEvent(name, event, app)
    if event == hs.application.watcher.activated then
        if name == "Google Chrome" then
            switchHotKeys(true)
        else
            switchHotKeys(false)
        end
    end
end

local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

watcher = hs.application.watcher.new(handleGlobalEvent)
watcher:start()

-- Chrome など特定のアプリでのみ有効化するキーバインドのインデックスを代入しておく
limitedRemaps = {1, 2}

-- limitedRemaps start
remapKey({"ctrl"}, "n", keyCode("down"))
remapKey({"ctrl"}, "p", keyCode("up"))
-- limitedRemaps end

remapKey({"ctrl"}, "[", keyCode("escape"))
remapKey({"alt"}, ";", keyCode("\\"))
remapKey({"alt"}, "'", keyCode("\\", {"shift"}))
remapKey({"ctrl", "alt"}, "f", keyCode("right", {"alt"}))
remapKey({"ctrl", "alt"}, "b", keyCode("left", {"alt"}))

Hammerspoon docs: hs.application
ちなみにアプリケーション名はプロセスIDとかで確認できます

感想

色々とハマッてしまいだいぶ時間かかりましたがなんとか思った通りの挙動になってよかったです!現状はとりあえずChromeのみとそれ以外で分けてますが色々と増やしていこうと思います。

だいぶ時間が経って気づいたのは、そもそも ctrl + f で →キーにする必要性は特に無いので時間かけて頑張った意味は無かったです🙃ポジティブに考えるとLuaにプチ入門できたので良かったのかなって感じです

似たようなことやりたい人いればぜひ参考にしてください〜Hammerspoonめっちゃ便利ですよ!

参考:
https://tamamemo.hatenablog.com/entry/2017/01/30/183650

Discussion