結論
日本語入力の設定で円記号をバックスラッシュに割り当てるのはやめて、Hammerspoon で以下のスクリプトを使います。
--- Perfect backslash(\) for Mac JIS keybord users
-- The problem:
-- On Mac, Japanese IME setting to replace Yen-backslash is ignored by
-- IntelliJ, jEdit or such as because JVM uses another keymap traditionally.
-- Solution:
-- Use Hammerspoon (http://www.hammerspoon.org/) instead of Japanese IME
-- setting. Paste below to your ~/.hammerspoon/init.lua file.
-- @author Hisateru Tanaka (tanakahisateru@gmail.com)
local VK_1 = 0x12
local VK_ESC = 0x35
-- Secret key codes not included in hs.keycodes.map
local VK_JIS_YEN = 0x5d
local VK_JIS_UNDERSCORE = 0x5e
--local log = hs.logger.new('keyhook','debug')
function flagsMatches(flags, modifiers)
local set = {}
for _, k in ipairs(modifiers) do set[string.lower(k)] = true end
for _, k in ipairs({'fn', 'cmd', 'ctrl', 'alt', 'shift'}) do
if set[k] ~= flags[k] then return false end
end
return true
end
-- NEVER define as local variable!
jisKeyboardFilter = hs.eventtap.new({
hs.eventtap.event.types.keyDown,
hs.eventtap.event.types.keyUp
}, function(event)
local c = event:getKeyCode()
local f = event:getFlags()
-- log.d(...)
if c == VK_JIS_YEN then
-- To input \ even if JVM, toggle Option key status when Yen key.
if flagsMatches(f, {'alt'}) then
event:setFlags({})
elseif flagsMatches(f, {}) then
event:setFlags({alt=true})
end
-- Hint: Never replace key code to backslash itself because JIS
-- keyboard does'nt have phisical backslash and assignes it to close
-- bracket (]) key.
elseif c == VK_JIS_UNDERSCORE then
-- Also map single undetscore (_) key to backslash (\).
if flagsMatches(f, {}) then
event:setKeyCode(VK_JIS_YEN)
event:setFlags({alt=true})
end
elseif c == VK_1 then
-- Customization example: Option+1 => ESC
if flagsMatches(f, {'alt'}) then
event:setKeyCode(VK_ESC)
event:setFlags({})
end
end
end)
jisKeyboardFilter:start()
elseif
のところはオマケなので、物理 ESC あるよって人はさっくり消してください。
解説
JVM でできた GUI アプリケーションは伝統的に、Macでバックスラッシュを標準で 入力するように しても、円記号でバックスラッシュを入力するとした設定を、なぜか無視します。ATOK使いもMacでシュッとバックスラッシュを打ちたい という動機で ~/Library/KeyBindings/DefaultKeyBinding.dict
を書いても、やはり無視されます。そのため、JetbrainsのIDEでバックスラッシュがデフォルト入力にならない ことになり、JVM ベースのエディタを使う人はこれまでだいたい Karabiner を使うのが通例でした。
ところが、いま Karabiner の Sierra 対応が、Karabiner-Elements を済ませてからということで、遅れています。そして、Karabiner-Elements のナイトリービルドでも、ある理由からうまく円記号をバックスラッシュに割り当てることができません。(2017.01.27 現在)
keyhack は Python なんだけどどうも Mac がもともと持っているホットキーとコンフリクトしそうだし... というわけで使うのは Hammerspoon が現在最有力です。ここではやらないけど、こいつだけで、Mac 標準では設定できないショートカットを作れたり、アプリケーションフォーカスの監視ができたり...
さらに深い解説
JIS キーボード版の Mac には、物理的にバックスラッシュキーが付いていません。円記号の刻印のあるキーは、 international3
キーだそうです。なんと! ちなみにアンダースコアに見えるのは international1
だそうな。
Karabiner-Element で international3
を backslash
に書き換えればいいか、というと、話はそう簡単ではありません。物理的に存在しないバックスラッシュキーの信号が来たとき、JIS キーボードの Mac OS はそれを ]
キー信号とみなします。
低レベルなIOの世界では、修飾キーなしでバックスラッシュを入力できる信号パターンは存在せず、また JVM は IME の変換設定をことごとく無視します。つまり、JIS キーボードを使っている以上、Option + ¥
と操作するしかないわけです。
では、Hammerspoon でさっくり簡単に行くかというと、まだもうひとつ罠があります。hs.keycodes.map
(http://www.hammerspoon.org/docs/hs.keycodes.html#map) には international3
にあたるキーの名前が登録されていません。文字で指定できないため、ハックしたいキーのコード 0x5d
を調べなければなりません (Karabiner-Element に付いてくるキーコードイベントの監視ツールで調べました)。
これでようやく、「Option キーなしで 0x5d が来てもムリヤリ Option キーを押していたことにする(キーダウン/アップとも)」 というアイデアにたどり着けます。
ちなみに、Karabiner 使えない対策: Hammerspoon で macOS の修飾キーつきホットキーのキーリマップを実現する ではホットキーを使っていますが、そもそもホットキーは「Siriを呼び出す」みたいな単機能の発動に向いています。発動の頻度が非常に高かったり、キーリピートを活かしたいような場合は、hs.eventtap.new(...):start()
で、ホットキーよりもっと手前でキーボード信号イベントを横取りするのが良さそうです。(最初はとても参考にさせてもらいましたが)