macOS Sierra になってから、これまで使えていた Karabiner が使えなくて非常に困った。
もともと Karabiner は Xcode で emacs ライクなキーバインドを実現するために使用していたが、
代替として Hammerspoon に移行できたのでその設定内容を記載。
動作確認環境
- macOS Sierra 10.12.2
- Hammerspoon 0.9.48
主な設定内容
- C-x C-s で上書き保存(⌘+s)
- C-x C-f で Open Quickly (⌘+shift+o)
- C-space で set-mark 的なもの
- 設定は Xcode 操作時のみ有効
設定ファイル
Hammerspoon の導入などは省略します。
設定ファイルの全文は Github で管理しているのでそちらを参照。
ちなみに、今は使っていませんが Karabinerの設定ファイルも同じリポジトリにあります。
設定内容をかいつまんで記載します。
C-x C-s で上書き保存(⌘+s)
C-x トリガで commandMode:enable() 関数を呼び出し、
-- command mode
hs.hotkey.new({'ctrl'}, 'x', function() commandMode:enable() end),
関数内で hs.eventtap.new にてキーダウンイベントを監視します。
登録した 2ストローク目のキー(例えば C-s)と一致した場合に該当する関数(例えば ⌘-sを発行)を呼び出します。
obj.enable = function(self)
info(self.name.." start")
self.commandWatcher:start()
end
obj.commandWatcher = hs.eventtap.new( {hs.eventtap.event.types.keyDown},
function(tapEvent)
for k,v in pairs(obj.commandTable) do
if v.key == hs.keycodes.map[tapEvent:getKeyCode()] and isEqualTable(v.modifiers, tapEvent:getFlags()) then
info(obj.name.." end")
obj.commandWatcher:stop()
if v.func then
v.func()
end
return true
end
end
if obj.othersFunc then
return othersFunc(tapEvent)
end
end)
return obj
このあたりの書き方は下記のページなどを参照させていただき、クラスっぽい記載にしました。
http://www.ie.u-ryukyu.ac.jp/~e085739/lua.hajime.4.html
C-space で set-mark 的なもの
上記の C-x C-s の場合と同じような記載にしましたが、
登録されている 2ストローク目のキー以外のキーが押された場合に shift を強制的に押されたような動作をするようにしました。
これにより、C-space C-f C-f などと押したときに、shift を押しながらカーソル移動したのと同じような動作をさせるようにしています。
function(tapEvent) -- force shift on
flags = tapEvent:getFlags()
flags.shift = true
tapEvent:setFlags(flags)
return false
end
ちなみにXcode でもデフォルトで C-@ でset mark できますが、選択範囲をわかりやすくしたかったのと、OSのクリップボードと共有させたかったので上記のような設定をしています。
設定は Xcode 操作時のみ有効
下記コードにより ウィンドウの切り替えを監視し、Xcode フォーカス時にのみ設定が有効になるようにしています。
hs.window.filter.new('Xcode')
:subscribe(hs.window.filter.windowFocused,function() enableAll(xcodeBindings) end)
:subscribe(hs.window.filter.windowUnfocused,function()
disableAll(xcodeBindings)
markMode:disable()
commandMode:disable()
end)
最後に
Xcode だけで emacs キーバインドができれば全て解決ですが、それまではこれでしのぎます。
API仕様を見た感じHammerspoon はもっといろいろなことができそうなので、今後も触っていこうかと思います。
http://www.hammerspoon.org/docs/