LoginSignup
2
2

More than 5 years have passed since last update.

MacOS Sierra で入力ソースの切り替えのキーバインドを設定する(HammerSpoon)

Posted at

はじめに

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の詳細はここから

init.lua
-----------------------------------------------------------------------------------
-- 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

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2