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

k0kubun's blog

railsへの執着はもはや煩悩の域であり、開発者一同は瞑想したほうがいいと思います。

Linux向けの最強のキーリマッパーを作った

X Window Systemで動作するキーリマッパー「xremap」を作った

2017/1/9追記: xkremap→xremapにリネームしました

僕はKarabiner用のRuby DSLを作ったりそれを使って大量の設定を既述する程度にはKarabinerのヘビーユーザーなんだけど、デスクトップ環境にLinuxを使い始めてからもう1年以上経つ今でもLinux環境で使えるKarabiner並にリッチなキーリマッパーを見つけられずずっと不便していたので、ユースケースを満たす最低限のものを自分で作った。

github.com

ちなみにX用であって別にLinuxの何かに依存しているわけではないので、タイトルは釣りである。

これは何

RubyDSLかつシンプルなキーの指定方法によりキーリマップを設定することができる。例えば、以下の設定ファイルを書いてxremapに渡す*1とターミナルやEmacsの外でもEmacsライクなキーバインドが使えるようになる。

remap 'C-b', to: 'Left'
remap 'C-f', to: 'Right'
remap 'C-p', to: 'Up'
remap 'C-n', to: 'Down'

remap 'C-a', to: 'Home'
remap 'C-e', to: 'End'

remap 'C-k', to: ['Shift-End', 'Ctrl-x']

また、xbindkeys等のツールより優れている点はアプリケーション*2ごとのキーバインドを設定できるところにある。普段Emacsバインディングを使っていると、Slackが割りあてるC-kとコンフリクトするわけだけど、例えば以下のように書くとSlackでのみ下記の設定を適用し問題を回避することができる。

window class_only: 'slack' do
  remap 'Alt-n', to: 'Ctrl-k'
end

あと、任意のキーからシェルを起動することができるので、ランチャーとしても使える。

remap 'C-o', to: execute('nocturn')
remap 'C-u', to: execute('google-chrome-stable')
remap 'C-h', to: execute('urxvt')

補足だけど、ある単一のキーを別のキーにリマップするみたいなことはXmodmapとかでやったほうがいいと思う。その方が多分速いので。僕はErgoDoxのファームウェアでそういうリマップはできるので不要なんだけど、xremapはEmacsバインディングみたいな何らかのキーの組み合わせをキーの組み合わせやシーケンスに変換したい時に使う。

なぜ作ったのか

GitHub等でキーバインドが奪われるし、その度にJavaScriptを読みたくない

GitHubというサイトはC-k, C-bを奪ってくる。社員は誰もEmacsを使ったことがないに違いない。 僕はいままでEmacsバインディングinclude "/usr/share/themes/Emacs/gtk-2.0-key/gtkrc"によって設定していたんだけど、これだと普通にブラウザに奪われるため、user.jsを書く必要があって面倒だった。

xremapを使うとXのルートウィンドウレベルでキー入力イベントをフックしてリマップするので、例えばGitHubのコメント欄とかでブラウザにキーバインドが奪われない点が便利。

rbindkeysがRuby >= 2.2で動かない & wineを使うとSEGVする

類似のツールにrbindkeysというものがあり、というかほぼ要件を満たしていたので長い間使っていた。が、上述したようなランチャーの用途には使えず別のツールで解決していたのとか、単純に不安定なのとか、DSLが複雑などの理由でずっと自分向けの奴を作りたいと思っていた。仕様も内部実装も仕組みも全て僕の好みに変えたrbindkeysがxremapといえる。いままでお世話になりました。

rbindkeysと比較して、xremapは下記のような違いがある。

  • キーイベントの取得やリマップにLinux Input Subsystemを使わないので、Linuxじゃなくても(多分)動く & rootじゃなくても実行できる
  • キーボードを抜き差ししてもそのまま使える
  • DSLの違いにより、キーの指定がシンプルに書ける
  • C-kとかのリマップの挙動が安定している

あと、この場合別にRubyでもmrubyでもどっちでもいいなあとは思ったんだけど、最近慣れてきたmrubyを採用している点も異なる。

macOSと違ってCommandキーがないから色々コンフリクトするのを解決したい

コピーやペーストがC-c, C-vなどControlに割りあてられているため、例えばEmacsC-fとブラウザの検索のC-fが被ってしまっていた*3

アプリケーションごとにキーバインドを変えられる程度にはリッチかつ十分に安定したキーリマッパーがあると、macOSみたいにCommandキー相当のキーを作ることができる。会社で貸与されてるノートPCがMacBookなので今でもmacOSは使うのだけど、できれば複数の環境の差異をなくしたいというのがあった。

気持ち

デスクトップ環境でLinuxを使っている人はNocturnxremapをよろしくお願いします。

*1:systemdとかで起動するのがよい xremap/xremap.service at 6e8e1f21285ecedfa7ac88d703ad80d25a2699dd · k0kubun/xremap · GitHub

*2:正確にはウィンドウのclass

*3:gtkrcによる設定だと、テキスト入力欄かどうかで挙動が変わっていたが、検索とかは常に使えて欲しかった

広告を非表示にする