はじめに
MacOS Sierra ではキーバインド変更アプリのKarabinerが利用できない。(Karabiner-Elementsのみ)
よってこれまでKarabinerで実現していた以下の機能を実現するアプリとしてHammerSpoon( http://www.hammerspoon.org/)を利用する。
- SHIFT+SPACEによる日本語入力切替
- ESC押下に英数押下のアクション追加(vimのエディットモードをESCで抜ける際に日本語入力を解除するため)
Sierraにアップデートする前に「El Capitan」での動作確認を行なっているためこのバージョン以降であれば動作する。
環境情報
OS: 10.12.6 (MacOS Sierra)
HammerSpoon: 0.9.55
HammerSpoon設定
設定作成/反映
メニューバーのアイコンを押下し、「Open Config」を選択すると設定ファイルのinit.luaがエディタで開かれる。
init.luaにluaで設定(コード)を記述し、再度メニューバーのアイコンから「Reload Config」を選択し設定を反映させる。
メニュバーから「Console」選択すると、設定読み込みの様子やエラーの確認ができるコンソールが開く。
コンソールの下部にはプロンプトも用意されているので、コードの断片のデバッグなどに利用できる。
なおメニューバーの「Preference」を選択し表示される設定画面下部の「Accessibility」が「Disable」だと利用できる機能に制限が発生する。(例:hs.eventtap.event.types.keyDown/keyUp)
特に理由がなければ「Enable」にする。そして「Enable」にした後、必ずHammerSpoonを再起動すること。
init.lua
「hs」で始まる変数でHammerSpoonのAPIが利用できる。
APIの詳細はここから。
-----------------------------------------------------------------------------------
-- define const vars
-----------------------------------------------------------------------------------
---------------------
-- modifire keys
---------------------
--local MOD_COMMAND = 55 --hs.keycodes.map['cmd']
--local MOD_SHIFT = 56 --hs.keycodes.map['shift']
--local MOD_ALT = 58 --hs.keycodes.map['alt']
--local MOD_CTRL = 59 --hs.keycodes.map['ctrl']
---------------------
-- general keys
---------------------
local SPACE = 49 --hs.keycodes.map['space']
local ESCAPE = 53 --hs.keycodes.map['escape']
local KEY_CODE_JIS_EISUU = 102
--local KEY_CODE_JIS_KANA = 104
---------------------
-- application names
---------------------
--local VIM_BINDING_APPS = {
-- "ターミナル", "iTerm2", "Boostnote"
--}
-----------------------------------------------------------------------------------
-- define functions
-----------------------------------------------------------------------------------
--------------------------------------------------------
-- constract function of executing multiple functions.
--------------------------------------------------------
local function multiFunc(functions)
return function()
for i, func in ipairs(functions) do
func()
end
end
end
--------------------------------------------------------
-- constract tap (press and release) key function.
--------------------------------------------------------
local function tapKey(mods, key)
mods = mods or {}
return function()
hs.eventtap.event.newKeyEvent(mods, key, true):post()
hs.timer.usleep(1000)
hs.eventtap.event.newKeyEvent(mods, key , false):post()
end
end
--------------------------------------------------------
-- set hotkey. (remap)
--------------------------------------------------------
local function remapKey(mods, key, tapKeyFunc)
hs.hotkey.bind(mods, key, tapKeyFunc, nil, tapKeyFunc)
end
--------------------------------------------------------
-- handle key action event.
--------------------------------------------------------
local function keyactionEventHandler(e)
local keycode = e:getKeyCode()
--hs.alert(keycode)
if keycode == ESCAPE then
hs.eventtap.event.newKeyEvent({}, KEY_CODE_JIS_EISUU, true):post()
end
end
-----------------------------------------------------------------------------------
-- remap keys
-----------------------------------------------------------------------------------
--global
remapKey({'shift'}, SPACE, tapKey({'cmd'}, SPACE))
--for vim editor.
--remapKey({}, ESCAPE, multiFunc({
-- tapKey({}, ESCAPE),
-- tapKey({}, KEY_CODE_JIS_EISUU)
--}))
-----------------------------------------------------------------------------------
-- listen event
-----------------------------------------------------------------------------------
local keyactionEventListener = hs.eventtap.new({
hs.eventtap.event.types.flagsChanged,
hs.eventtap.event.types.keyDown,
hs.eventtap.event.types.keyUp
}, keyactionEventHandler)
keyactionEventListener:start()
設定概要
日本語入力切り替えはホットキーで、ESC押下時の動作はイベントハンドリングにより実現。
(現状は利用していない設定や関数も含んでいるが、今後のためにある程度事前に用意。)
ESC押下時の動作をホットキーで実現すると、ESC押下してから反応するまでに1秒程度のタイムラグが発生するため不採用。
(複数のアクションを実行する参考例としてコメントアウト。)
--for vim editor.
--remapKey({}, ESCAPE, multiFunc({
-- tapKey({}, ESCAPE),
-- tapKey({}, KEY_CODE_JIS_EISUU)
--}))
ホットキーの設定はremapKey関数で行う。remapKey関数の第1、第2引数で指定したホットキー押下時に、第3引数で指定した関数を実行する。
第3引数で利用しているtapKey関数は指定したキーの「押す」「離す」を1[msec]間隔で行う関数を返却する。
multiFunc関数を利用すれば、複数のアクションを1つのホットキーに割り当てることができる。(現状は利用していない)
キーに関するイベントの監視はkeyactionEventListenerで行なう。
hs.eventtap.event.typesの後に続くものが定義されたイベント。
- 修飾キーのイベント: flagsChanged
- 一般キーのイベント: keyDown/keyUp
修飾キー(modifires)のイベントはkeyDown/keyUpでは取得できない為、注意が必要。
参考
http://qiita.com/naoya@github/items/81027083aeb70b309c14
http://mizoguche.info/2017/01/hammerspoon_for_sierra/
http://kitak.hatenablog.jp/entry/2016/11/28/104038
http://rochefort.hatenablog.com/entry/2017/02/25/070000
http://virtnote.blogspot.jp/2017/04/hammerspoon.html