そろそろ新しいMacBook欲しい… けど El Capitan から Sierra になるとKarabinerが使えなくなるって話だし… とか色々不安があり躊躇していた。 代替、というかちゃんと設定すれば代替できそうなHammerspoonが良さげだったので それを使ってKarabinerからの脱却を試みてみた。
Hammerspoon
Mac OSの様々な操作を自動化するためのツールで、ユーザがLuaのスクリプトで設定を書くことでOSの様々な機能を使えるようにブリッジしてくれる。
Key Remap
基本的に 以下の記事のコピペで大丈夫そう。
自分は以下のように書いた。
local function keyStroke(mods, key) return function() hs.eventtap.keyStroke(mods, key, 0) end end local function remap(mods, key, fn) return hs.hotkey.bind(mods, key, fn, nil, fn) end -- global remap({'ctrl'}, 'h', keyStroke({}, 'delete')) remap({'ctrl'}, '[', keyStroke({}, 'escape')) remap({'ctrl'}, 'j', keyStroke({}, 'return')) remap({'ctrl', 'cmd'}, 'j', keyStroke({'cmd'}, 'return')) -- disable when a specific application is active local remapKeys = { remap({'ctrl'}, 'b', keyStroke({}, 'left')), remap({'ctrl'}, 'f', keyStroke({}, 'right')), remap({'ctrl'}, 'n', keyStroke({}, 'down')), remap({'ctrl'}, 'p', keyStroke({}, 'up')), remap({'ctrl'}, 'y', keyStroke({'cmd'}, 'v')) } local function handleGlobalAppEvent(name, event, app) if event == hs.application.watcher.activated then if name == 'iTerm2' or name == 'Code' then for i, key in ipairs(remapKeys) do key:disable() end else for i, key in ipairs(remapKeys) do key:enable() end end end end appsWatcher = hs.application.watcher.new(handleGlobalAppEvent) appsWatcher:start()
hs.hotkey.bind
で指定したキー操作時の振る舞いを指定できるので、hs.eventtap.keyStroke
で置き換えたいキー操作を指定してそれをemitさせるfunctionをセットする。pressedfn
, releasedfn
, repeatfn
と3種類の振る舞いを定義できるので注意。リマップは基本的にpressedfn
, repeatfn
を同じkeyStroke
を起こすfunctionにしておけば良さそう。
あと上述記事にもある通りiTermやVSCodeなどのターミナルやエディタではそれぞれ独自にキーバインド設定できたりするし リマップによる変換があると逆にそれが災いして期待した動作にならなかったりするので、applicationの切り替え時にイベントを取得してdisable()
/enable()
するように。
別にすべてのリマップを無効にする必要は無かったりもするので、常に有効にしておきたいものとは別に切り替え対象のリマップのkeybindだけを保持しておいて それらだけを有効化/無効化の対象にした。
Sticky Shift
Karabinerでもう一つお世話になっていたのが、所謂sticky-shift的なものをセミコロン;
で行う、というもの。
セミコロン;
を押した後にキーを押す、という操作でShiftキー押しながらの操作を代替する。(別に使うのはセミコロンじゃなくてもいいのだけど 最も一般的なのがこれ、なのかな)
AquaSKKを使っていると変換位置の指定の際にShiftキーを多用することになりつらいので、ずっとこの方法にお世話になっていたし、すっかりそれに慣れてしまっていた。
Karabinerでは AquaSKK で ; (セミコロン) を Sticky Shift に使う - Qiita のように設定して使っていたのだけど、これもHammerspoonでどうにか。
local stickyShift = false local targets = {} for i = 96, 122 do targets[hs.keycodes.map[string.char(i)]] = true end hs.hotkey.bind({}, ';', function() if hs.keycodes.currentMethod():find('AquaSKK') then stickyShift = true else hs.eventtap.keyStrokes(';') end end) keyTap = hs.eventtap.new({hs.eventtap.event.types.keyDown}, function(event) if stickyShift and targets[event:getKeyCode()] then event:setFlags({shift = true}) end stickyShift = false end):start()
stickyShift
という変数を持っておいて、入力ソースがAquaSKKのときに;
が押されたらフラグを立てる。それ以外のときは普通にそのまま;
のkeyStroke
をemitするだけ。
keyDown
イベントを監視し、stickyShift
フラグが立っていて かつtarget
のkeyCode(母音と主な子音だけで良いのだけど とりあえず全アルファベットを対象にしている)だったら、setFlags
を使ってshift
が押されている状態にイベントを書き換える。stickyShift
フラグは継続させる必要ないので強制的にfalse
に戻す。
これで今まで通りに;
を使ったsticky-shiftでの日本語入力ができるようになった。
ひらがなモードのときだけフラグを変えて ASCIIモードなら;
はそのまま通す、とかも出来れば良いのだけど、入力ソースの判別までは出来ても 現在の入力モードが何か、までは取る方法が分からなかった(無い?)ので;
を普通に打ちたい場合は普通に英字入力に切り替えるしかない。
まぁこれはKarabinerのときもそうだったし仕方ない。
あと どういうわけか、SierraだとVisual Studio Code上でAquaSKKがまったく効かなくて、ひらがなモードに入ることすらできないようだ。キー設定とかそういう問題じゃなさそうで どうにもならないんだけど、、他の人は普通に使えているのだろうか…?
まぁVSCodeはコード書くものだし日本語の文章書きたいときは他のアプリケーションを使えばいいか…ということで割り切る(この記事の下書きはAtomで書いてる)。
Launcher
あとよく使っていたのがhotkeyでのアプリ切り替え。cmd
+ctrl
+左手で打てるキー の組み合わせでターミナル/エディタ/ブラウザ/チャット/ツイッター などをサクサク切り替えたくて 以前はSlateやPhoenix、もしくは有料アプリのShortcutsなんかを使っていたりもしたけど、これもHammerspoonで解決できるようになったのでLauncherアプリは不要になった。
local function launcher(mods, key, appname) hs.hotkey.bind(mods, key, function() hs.application.launchOrFocus('/Applications/' .. appname .. '.app') end) end launcher({'cmd', 'ctrl'}, 'q', 'iTerm') launcher({'cmd', 'ctrl'}, 'w', 'Visual Studio Code') launcher({'cmd', 'ctrl'}, 'e', 'Google Chrome') launcher({'cmd', 'ctrl'}, 't', 'Twitter') launcher({'cmd', 'ctrl'}, 's', 'Slack')
Key Repeat
あとそういえばkarabinerで便利だったのがキーリピート間隔の設定だったのだけど、
システム環境設定での設定可能範囲を超える場合はdefaults
コマンドで設定すれば良いだけ、というのをググって知ったので 問題なかった。
$ defaults write -globalDomain KeyRepeat -int 1 $ defaults write -globalDomain InitialKeyRepeat -int 10
とかやって再起動すれば反映される(システム環境設定での変更ではKeyRepeat
は2
、InitialKeyRepeat
は15
が最小値っぽい)
雑感
とりあえずKarabinerが無くても困らない程度の設定は出来たっぽい。他にもカスタマイズしたければinit.lua
を頑張って書けば色々できそうではある。
しかしまぁKarabinerがSierraでも動いてくれるのが何よりだし このHammerspoonだって いつまたMac OSの変化で使えなくなってしまうか分からないし
こうしてMacの変更に振り回されて色々と苦労しないといかんのはどうにからならないもんかなぁ、と思ってしまう