読者です 読者をやめる 読者になる 読者になる

エンジニアの頭の中

フリーランスエンジニアが書く技術系ブログです。

Karabinerの代わりにHammerspoonを使用してmacOS SierraでVim風のキーバインドを実現する

f:id:mitsu3204:20170403231525j:plain

macOS Sierraへアップデートするため、macキーバインドツールであるKarabinerの使用をやめて、Hammerspoonに移行した話です。

Karabinerが未対応のためmacOS Sierraに移行できずにいたが思わぬところできっかけが訪れる

macOS Sierra では、キーのカスタマイズソフトであるKarabinerが使用できないため(2017年3月3日時点)、macOS Sierraには移行せず、OS X El Captainを使い続けていました。

Karabiner - OS X用のソフトウェア

macOS SierraではAirPodsが使えない

https://store.storeimages.cdn-apple.com/8561/as-images.apple.com/is/image/AppleInc/aos/published/images/M/ME/MMEF2/MMEF2?wid=572&hei=572&fmt=jpeg&qlt=95&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1473705678057

AirPodsを購入して以来、AirPodsをすっかり気に入っていまいた。

MacでもAirPodsを使用したくなったのですが、OSがmacOS Sierraでないと、AirPodsを使用できないということを知りました。

AirPodsを理由にmacOS Sierraへの移行を決意する

AirPodsが使いたかったので、Karabinerの代わりとなるキーバインドを変更できるソフトを探して、macOS Sierraへと移行することを決意しました。(Sierraの他の機能には興味無し!)

ということで、Karabinerの代わりに使用したソフトウェアと、その設定内容について以下に記載します。

Karabinerで実現していたキーバインド

私が、Karabinerで実現していたキーのカスタマイズは以下の3点のみです。

  • functionキー+hjklキーでカーソル移動(Vim風の移動キーを実現)
  • 左commandキーで英語入力へ切り替え
  • 右commandキーで日本語入力へ切り替え

ちなみに、キーのカスタマイズは、上記以外にも、caps lockキーをcontrolキーとして使用していますが、これはOSの機能で実現可能なため、そちらで設定しています。 

 

Karabinerの代わりにHammerspoonを使用

Karabinerと類似の機能を持つソフトをいくつか調べてみた結果、一番良さそうだったのが、Hammerspoonでした。

github.com

Hammerspoonは、単にキーバインドの変更ツールではなく、様々な自動化を行うためのアプリで、Lua言語で設定を書くのが特徴です。

 

 

ただ、設定をいじり始めて気付いたのが、Hammerspoonでは、hjklキーによる移動をfunctionキーと組み合わせて設定することができないということでした。仕方がないので、諦めてcontrolキーと組み合わせることにしました。

操作が変わってしまう点は慣れれば問題ないでしょう。 

Hammerspoonのインストール

brew cask install するのみです。

brew cask install hammerspoon

GithubのReleasesからzipをダウンロードすることもできます。

Hammerspoonの設定内容

最終的な設定内容は以下の通りです。

  • controlキー+hjklキーでカーソル移動(Vim風の移動キーを実現)
  • 左commandキーで英語入力へ切り替え
  • 右commandキーで日本語入力へ切り替え

設定ファイルの内容は以下の通りです。 

~/.hammerspoon/init.lua

local function keyCode(key, modifiers)
   modifiers = modifiers or {}
   return function()
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), true):post()
      hs.timer.usleep(1000)
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), false):post()      
   end
end

local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

local function enableAllHotkeys()
   for k, v in pairs(hs.hotkey.getHotkeys()) do
      v['_hk']:enable()
   end
end

remapKey({'ctrl'}, 'h', keyCode('left'))
remapKey({'ctrl'}, 'j', keyCode('down'))
remapKey({'ctrl'}, 'k', keyCode('up'))
remapKey({'ctrl'}, 'l', keyCode('right'))
remapKey({'ctrl', 'shift'}, 'h', keyCode('left', {'shift'}))
remapKey({'ctrl', 'shift'}, 'j', keyCode('down', {'shift'}))
remapKey({'ctrl', 'shift'}, 'k', keyCode('up', {'shift'}))
remapKey({'ctrl', 'shift'}, 'l', keyCode('right', {'shift'}))
remapKey({'ctrl', 'cmd'}, 'h', keyCode('left', {'cmd'}))
remapKey({'ctrl', 'cmd'}, 'j', keyCode('down', {'cmd'}))
remapKey({'ctrl', 'cmd'}, 'k', keyCode('up', {'cmd'}))
remapKey({'ctrl', 'cmd'}, 'l', keyCode('right', {'cmd'}))
remapKey({'ctrl', 'shift', 'cmd'}, 'h', keyCode('left', {'shift', 'cmd'}))
remapKey({'ctrl', 'shift', 'cmd'}, 'j', keyCode('down', {'shift', 'cmd'}))
remapKey({'ctrl', 'shift', 'cmd'}, 'k', keyCode('up', {'shift', 'cmd'}))
remapKey({'ctrl', 'shift', 'cmd'}, 'l', keyCode('right', {'shift', 'cmd'}))

local prevKeyCode
local escape = 0x35
local leftCommand = 0x37
local rightCommand = 0x36
local eisuu = 0x66
local kana = 0x68

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

local function handleEvent(e)
    local keyCode = e:getKeyCode()
    local isCmdKeyUp = not(e:getFlags()['cmd']) and e:getType() == hs.eventtap.event.types.flagsChanged
    if isCmdKeyUp and prevKeyCode == leftCommand then
        keyStroke({}, eisuu)
    elseif isCmdKeyUp and prevKeyCode == rightCommand then
        keyStroke({}, kana)
    end
    prevKeyCode = keyCode
end

eventtap = hs.eventtap.new({hs.eventtap.event.types.flagsChanged, hs.eventtap.event.types.keyDown, hs.eventtap.event.types.keyUp}, handleEvent)
eventtap:start()

設定を保存したら、hammerspoonのメニューから「Reload Config」を選択すれば、保存した設定内容が反映されます。

 

commandキーの英かな変更は、以下のページを参考にさせて頂きました。

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

 

以上