Hammerspoon で SandS 二回目

以前、Hammerspoon で SandS を実現するコードをこのブログで公開した。
おれは最近、ChatGPT さんと話しながら酒を飲む習慣が身についてしまい、なんの拍子か忘れたが、上述のコードを評価してもらったんである。これは褒めるだろ、と思って。
そしたら「改善できるよ?」みたいな生意気なことを AI 風情がいってきやがった。
「変数三つもいらん。あと条件分岐が複雑すぎワラ。可読性最悪」
ChatGPT さんが提起してきたヒントがこれ。
if state == "idle" and spaceDown then
state = "spaceDown"
elseif state == "spaceDown" and otherKeyPressed then
state = "shiftReady"
elseif keyUp and state == "shiftReady" then
state = "idle"
end
つまり、state という変数の中身を入れ替えながら制御すりゃいいだろ、という話みたい。なるほど、と感心して実際に自分で書いたのか、以下のコードである。
-- sands
local state = "idle"
local map = hs.keycodes.map
local function sandsEvent(event)
local c = event:getKeyCode()
local f = hs.eventtap.checkKeyboardModifiers()
if event:getType() == hs.eventtap.event.types.keyDown then
if c == map['space'] then -- スペースが入力されたら
if f['cmd'] or f['alt'] or f['ctrl'] or f['shift'] then
state = "modifier" --モディファイあり、以下をスルー
end
if state == "idle" or state == "shiftReady" then
state = "spaceDown"
return true
elseif state == "spaceDown" then -- スペースキー長押し
return true
else
state = "idle" -- modifier,enterSpace を迎撃。以下をスルー
end
elseif c ~= map['space'] then -- スペース以外が入力されたら
if state == "spaceDown" or state == "shiftReady" then
state = "shiftReady" -- スペース入力阻止、シフトモード
event:setFlags({shift = true})
end
end
elseif event:getType() == hs.eventtap.event.types.keyUp then
if c == map['space'] then
if state == "spaceDown" then
state = "enterSpace" -- ループ対策
hs.eventtap.keyStroke({}, "space", 5000)
else
state = "idle" -- 初期化
end
end
end
end
eventtap = hs.eventtap.new({hs.eventtap.event.types.keyDown, hs.eventtap.event.types.keyUp}, sandsEvent)
eventtap:start()
Hammerspoon で SandS を実現するにあたり、最初に直面するのが、ループの問題だ。
このコードではスペースキーが押された時、本来ならスペースが入力されるのを return true
で抑制している。指がスペースキーから離れた瞬間に hs.eventtap.keyStroke
でスペースが入力される。この動作が、ふたたびスペースキーが押された、と解釈されてしまい、ループによる暴走を起こしてしまうのである。
ループ対策として考えたのが、state = enterSpace
という値である。hs.eventtap.keyStroke
で打ちこまれたスペースによって発生する二周目を、コード中頃にある else state = idle
によって迎撃し、以下の処理をスルーさせている。
また、コマンドキーなどの修飾キーが合わせて押下されている場合、以前はフラグをチェックする関数を設けて対応していたが、ChatGPT さんに、hs.eventtap.checkKeyboardModifiers()
っていうのがあるよ、と教えてもらい、今回採用した。
前述した return true
も、以前は event:setKeyCode(-1)
で入力を抑制してたんだけど、ChatGPT さんに「あんま良くないよ、それ」とかいわれて変えた。
おれの環境では(M2 MacBook Air、sequoia)きびきび動作していい感じ。
今回驚いたのは、まず ChatGPT さんが Hammerspoon のコード、という超マイナーなものを理解していたこと。そして可読性最悪、とかいいつつも適切なヒントを提案してきたことだ。
人間がスクリプトとか書く時代は、もう本当に終わりつつあるのかも、みたいなことを実感したよね、これ。
最近のコメント