Hammerspoon でコマンドキーに「かな」「英数」を割り当てる

筆者は US キーボードの MacBook を使っている。
 かっこいいし、余計なキーがなくすっきりしていていい。
 US キーボードを日本語環境で使っていて困るのは、日本語入力と英語入力の切り替えだ。
 JIS 配列のキーボードなら「英数」キー、「かな」キーがスペースキーを挟んで配置されており、迷いはない。
 US キーボードの場合は、[コマンド] + [スペース] みたいなことをして入力を切り替えなくてはならない。

⌘英かな

US キーボードにおいては JIS キーボードの「かな」「英数」の場所に、コマンドキーが配置されている。ライトコマンド、レフトコマンドだ。このコマンドキーに「英数」キー、「かな」キーを割り当てるとインプットメソッドの切り替えが格段にやりやすくなる。
 その割り当てを簡単におこなってくれるのが「⌘英かな」だ。

🔗 ⌘英かな

ほかに Karabiner-Elements でも同じことが出来るはず。

Hammerspoon でもやれそうだと思い、かつてスクリプトを書いた。
 夜コーヒーというブログに掲載していたのだが、最近そのブログを閉じたので、スクリプトを再掲しておきたい。
 以下の記事を参考にさせていただいている。

macOS SierraにアップデートしてHammerspoonでCommandキーにかなと英数を割り当てた | mizoguche.info

init.lua

local simpleCmd = false
local leftSet = false
local rightSet = false

local leftCmd = 0x37
local rightCmd = 0x36
local eisuu = 0x66
local kana = 0x68

local function keyStroke(modifiers, character)
    hs.eventtap.keyStroke(modifiers, character, 5000)
end

local function eikanaEvent(event)
    local c = event:getKeyCode()
    local f = event:getFlags()
    if event:getType() == hs.eventtap.event.types.keyDown then  
        if f['cmd'] and c then
            simpleCmd = true
        end
    elseif event:getType() == hs.eventtap.event.types.flagsChanged then
        if f['cmd'] then
            if c  == leftCmd then
                leftSet = true
                rightSet = false
            elseif c == rightCmd then
                rightSet = true
                leftSet = false
            end
        else
            if simpleCmd == false then
                if leftSet then
                    keyStroke({}, eisuu)
                elseif rightSet then
                    keyStroke({}, kana)
                end
            end
                simpleCmd = false
                leftSet = false
                rightSet = false
        end
    end
end

eikana = hs.eventtap.new({hs.eventtap.event.types.keyDown, hs.eventtap.event.types.flagsChanged}, eikanaEvent)

eikana:start()

getFlags() で、コマンドとかシフトとかのモディファイキーが押されているかどうかがわかる。「テーブル」と呼ばれている配列みたいなデータが返ってくる。
 コマンドキーが押されており、かつ他のキーも押されていれば(例えばファイルを開く cmd + o など)、これは通常のコマンドの動作として処理されるべきであり、simpleCmd という変数を true にしておく。

もうひとつ、とにかくコマンドキーが押された場合は、それが左のコマンドキーなら leftSet を、右なら rightSet という変数を true にしておく。

あとは、simpleCmd が false の時、rightSet が true なら「かな」を、leftSet が true なら「英数」を入力する、という感じ。

ひとつだけ、if f['cmd'] and c then という最初のほうにある条件文。
 これは「コマンドが押されていて」かつ「キーコード c になにか数字が入っていれば」発動する仕掛けになっている。
 しかしコマンドキーもキーコードを持っているはずであり、押せばただちに「55」だかの数字が変数 c に格納されるはずだ。上の条件文では、コマンドキーを単独で押しても true として成立するはずなのだ。
 が、実際はコマンドキーを押しただけは、変数 c は空っぽのままだ。
 どうやらモディファイキーのキーコードは、キーを押した時ではなく、キーを離したタイミングで出力されるらしい(はっきりとはわかんないけど)。
 つまりコマンドキーを押しっぱの状態では f['cmd'] の部分しか条件を満たさない、と思われる。

また event.types.flagsChanged というのは、モディファイキーが押された時、なんかする構文みたいなやつだ。
 この flagChanged はモディファイキーを押した時だけでなく、離したタイミングでもフラグがチェンジした、と判断するものらしい。

上記のスクリプトは今のところ動いてるけど、キーコンビネーションによっては、おかしなことになってしまうかもしれない。