1. tanakahisateru

    Posted

    tanakahisateru
Changes in title
+IntelliJとかJVMのIDE使いでもKarabinerなしでバックスラッシュを片手入力したい
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,73 @@
+# 結論
+
+日本語入力の設定で円記号をバックスラッシュに割り当てるのはやめて、[Hammerspoon](http://www.hammerspoon.org/) で以下のスクリプトを使います。
+
+https://gist.github.com/tanakahisateru/ea015d3e5ee5e088898411c2643f1123
+
+```lua
+--- Perfect backslash(\) for Mac JIS keyboard 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')
+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 and not f['alt'] then
+ -- Always Option pressed with Yen key to input \ even if JVM.
+ event:setFlags({alt = true})
+ -- 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 and not f['shift'] then
+ -- Also map undetscore (_) without shift key to backslash (\).
+ event:setKeyCode(VK_JIS_YEN)
+ event:setFlags({shift = false, alt = true})
+ elseif c == VK_1 and f['alt'] then
+ -- Customization example: Option+1 => ESC
+ event:setKeyCode(VK_ESC)
+ event:setFlags({alt = false})
+ end
+end):start()
+```
+
+`eleif` のところはオマケなので、物理 ESC あるよって人はさっくり消してください。
+
+# 解説
+JVM でできた GUI アプリケーションは伝統的に、[Macでバックスラッシュを標準で](http://qiita.com/bayashi/items/3fc8fc48ae51937104b0) 入力するように しても、円記号でバックスラッシュを入力するとした設定を、なぜか無視します。[ATOK使いもMacでシュッとバックスラッシュを打ちたい](http://qiita.com/tomzoh/items/656b463935e6d64d8ea8) という動機で `~/Library/KeyBindings/DefaultKeyBinding.dict` を書いても、やはり無視されます。そのため、[JetbrainsのIDEでバックスラッシュがデフォルト入力にならない](http://qiita.com/uchiko/items/f7ea7915c3953074b797) ことになり、JVM ベースのエディタを使う人はこれまでだいたい [Karabiner](https://pqrs.org/osx/karabiner/index.html.ja) を使うのが通例でした。
+
+ところが、いま Karabiner の Sierra 対応が、[Karabiner-Elements](https://github.com/tekezo/Karabiner-Elements) を済ませてからということで、遅れています。そして、Karabiner-Elements のナイトリービルドでも、ある理由からうまく円記号をバックスラッシュに割り当てることができません。(2017.01.27 現在)
+
+[keyhack](https://sites.google.com/site/craftware/keyhac-ja) は Python なんだけどどうも Mac がもともと持っているホットキーとコンフリクトしそうだし... というわけで使うのは [Hammerspoon](http://www.hammerspoon.org/) が現在最有力です。ここではやらないけど、こいつだけで、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 の修飾キーつきホットキーのキーリマップを実現する](http://qiita.com/naoya@github/items/81027083aeb70b309c14) ではホットキーを使っていますが、そもそもホットキーは「Siriを呼び出す」みたいな単機能の発動に向いています。発動の頻度が非常に高かったり、キーリピートを活かしたいような場合は、`hs.eventtap.new(...):start()` で、ホットキーよりもっと手前でキーボード信号イベントを横取りするのが良さそうです。(最初はとても参考にさせてもらいましたが)