Hammerspoon で sands
Hammerspoon で SandS というキーコンビネーションを実行するスクリプトを書いた。
以前「夜コーヒー」というブログで発表していたものの再掲となる。
SandS とは
macOS High Sierra のころ。
Karabiner というキーボードをカスタマイズするアプリが使えなくなってしまった。
筆者は Karabiner で「sands」と呼ばれるキーカスタマイズを実行していた。
High Sierra のアップデートで sands が使えないことになり、不便な思いをしたのだった。
sands というのはシフト アンド スペースだか、スペース アンド シフト だかの略語だったと思う。スペースキーにシフトの機能を付与するキーカスタマイズのことだ。
[スペース] + [ a ] キーを押したとき、sands なら大文字の A が入力される。
[スペース] を単独で押すと通常のスペースキーの動作、つまり空白が入力される。
なんでこんなことするのかというと、SKK という日本語入力方法を使うさい、シフトキーを多用するからだ。シフトキーの多用は小指を酷使する。スペースキーにシフトの機能を付与することで、親指でもシフトを押せることになり小指への負担は軽減されるというわけ。
以下に以前の記事をそのまま再掲する。
いまさらだけど、Hammerspoon で SandS。2017年最終版
前に Hammerspoon というアプリケーションで、スペースキーをシフトキーとして代用する SandS を実現するスクリプトを作って、このブログに掲載していたりした。
しかしながら、SandS の挙動としては、スペースキーを押しっぱなしの時はそのままカーソルを留まらせて、スペースを入力しない、というのが正しいらしい。
おれがこしらえたスクリプトではそうならない。スペースを押しっぱなしだと、ちょっとした間を経たあと、スペースが連続されて入力されるようになっているのである。
これ、直したいなと思いながらずっと放置していたんだけど、時間が取れたから直したよ。相変わらず未熟な感じだけど、ま、動くよ。
コードは以下の通り。
📝 init.lua (ホームフォルダの、.hammerspoon のなかにある)
local spaceOn = false
local shiftOn = false
local spaceStay = false
local function flagCheck(flag)
local mods = {'fn', 'cmd', 'ctrl', 'alt', 'shift'}
local modifier = false
for i, value in ipairs(mods) do
if flag[value] then modifier = true end
end
return modifier
end
local function terminate()
spaceOn = false
shiftOn = false
spaceStay = false
end
local function sandsEvent(event)
local c = event:getKeyCode()
local f = event:getFlags()
if event:getType() == hs.eventtap.event.types.keyDown then
if c == 49 then
if flagCheck(f) == false then
if spaceOn == false and shiftOn == false then
spaceOn = true
spaceStay = true
event:setKeyCode(-1)
elseif spaceOn and spaceStay then
event:setKeyCode(-1)
else
terminate()
end
end
elseif spaceOn and c ~= 49 then
if flagCheck(f) == false then
shiftOn = true
event:setFlags({shift=true})
end
end
elseif event:getType() == hs.eventtap.event.types.keyUp then
if c == 49 then
if spaceOn and shiftOn == false then
spaceStay = false
hs.eventtap.keyStroke({}, "space", 5000)
else
terminate()
end
end
end
end
eventtap = hs.eventtap.new({hs.eventtap.event.types.keyDown, hs.eventtap.event.types.keyUp}, sandsEvent)
eventtap:start()
andS を実現させるには以下のような状況に対応する必要があるのではないか、と愚考する。
⌨️ モディファイキー + スペース
例えば [command] + [space] のような。こういう場合は、flagCheck() という関数でチェックして、モディファイキーとのコンビネーションなら、通常の動作とする。
⌨️ 単なるスペース入力
spaceOn という変数を true にして、キーを下げた時はスペースを入力せずに待機し、キーが上げられた時にスペースを入力する。
⌨️ SandS スペース + 他のキー
spaceOn が true になっていて、なおかつ他のキーが押された場合に、shiftOn という変数を true にする。その上で、モディファイキーShift をセットする。
⌨️ スペースキーの押しっぱなし
スペースキーを押すと同時に、spaceStay という変数を true にする。スペースキーを押しっぱなしということは、スクリプトを二周、三周していくということなので、各変数の true 、false の状況によって if で挙動をふり分けて、スペースの入力を抑制している。
どうもスッキリと分かりやすいコードにできない。
でもまぁ直せて良かったな、とは思う。