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

shtaxxx日記

コンピュータアーキテクチャについて研究している研究者の日記や技術紹介

macOS Sierra上のMicrosoft Office各種でEmacsキーバインドを使う

macOS Sierraでは(現状)Karabinerが動作しないため,標準でEmacsキーバインドが利用できないアプリケーションにもEmacsキーバインドを割り当てることができずに困っていた.英かなでもキーバインドの変更が可能であるが,一部のアプリケーションでは一部のキーバインドを無効にしたい場合には対応していないため,Hammerspoonを使ってみた.


下記の記事に倣って,Hammerspoonをインストールし,.hammerspoon/init.luaを書いた.

qiita.com

自分の設定ファイルは以下の通りである. Word,ExcelPowerPointだけで良かったのだが,面倒だったので,アプリケーション名がMicrosoftを含むとき時だけアクティブになるように設定した. その他のアプリケーションでも同様の方法で設定できるはず.

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 disableAllHotkeys()
   for k, v in pairs(hs.hotkey.getHotkeys()) do
      v['_hk']:disable()
   end
end

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

local function handleGlobalAppEvent(name, event, app)
   if event == hs.application.watcher.activated then
      -- hs.alert.show(name)
      -- if name == "Microsoft Word" then
      if string.find(name, "Microsoft") then
         enableAllHotkeys()
      else
         disableAllHotkeys()
      end
   end
end

appsWatcher = hs.application.watcher.new(handleGlobalAppEvent)
appsWatcher:start()

remapKey({'ctrl'}, 'p', keyCode('up'))
remapKey({'ctrl'}, 'n', keyCode('down'))
remapKey({'ctrl'}, 'b', keyCode('left'))
remapKey({'ctrl'}, 'f', keyCode('right'))

remapKey({'ctrl'}, 'a', keyCode('home'))
remapKey({'ctrl'}, 'e', keyCode('end'))

remapKey({'ctrl'}, 'h', keyCode('delete')) -- backspace
remapKey({'ctrl'}, 'd', keyCode('forwarddelete')) -- delete

remapKey({'alt'}, 'w', keyCode('c', {'cmd'})) -- copy
remapKey({'ctrl'}, 'w', keyCode('x', {'cmd'})) -- cut
remapKey({'ctrl'}, 'y', keyCode('v', {'cmd'})) -- paste