macOS上のVim以外の部分でVimな動作をKarabiner-Elementsを使って 再現しようとして作ったVim emulationに関して、 これまで今どういう状態にあるか、はパット見わからない状態でした。
そこで、メニューバーに状態を表示したり変更時に通知を出したりできるようにしてみました。
Vim emulation using Karabiner-Elements
Karabiner-Elements は言わずとしれたmacOS上でキーマップを自在に出来るツールです。
色々な設定も公開されています。
これとは別に個人的に公開してるのが以下のもの。
この中にVim emulationがあります。
本家の方にもViモードとかありますが、より色々なことができるようになっています。 (上の方のに入れようかと思ってたんですが、スクリプトをあまりに変更しすぎて統一するのが大変そうだったのでできてない。。。)
Vim emulationを有効にするとではメモ帳などの上でESCを押すと ノーマルモードに入って H、J、K、Lで左下上右に動ける様になったり コピーしたり貼り付けたり、ビジュアルモードが使えたりするようになります。
モードインジケーターの実装
Visual Indicator of Mode · Issue #6 · rcmdnk/KE-complex_modifications
前から自分でもやりたいな、とは思ってたんですが、 Issueでもらったのでやってみました。
実装したのは
- ⌃-⌘-⇧-Vでモード変更時に通知センターを使って通知を出すようにする(もう一回押すと停止する)
- rcmdnk/VEMを使ってメニューバーに状態を表示する
の二種類です。
通知
Vim emulationに
Vim emulation: Enable the display notification when the mode is changed: toggle by Ctrl-Cmd-Shift-v
という項目を加わえたので、これをEnableすると使えるようになります。
ただ、他の項目も中で変更があるので、すでにVim emulationを使ってた人は、一旦設定を外し、一覧表の方からも削除して新しいものを入れ直す必要があります。
有効にして、⌃-⌘-⇧-V を押すと、
こんな感じでモードが変更されるたびに通知が出ます。
実装としては、変更するキーを押した際に
{
shell_command: "osascript -e 'display notification \"Normal Mode\" with title \"vim_emu\"'"}]
}
といった感じのシェルコマンドも送るようにして、これによって通知を出しています。
ただ、通知の表示時間はmacOS自体の設定で決まっいて、
$ defaults write com.apple.notificationcenterui bannerTime -int 1 && killall NotificationCenter
とかすると1秒にしたり出来ますが、他の通知も同様になってしまいます。
まあ面倒なことをしようとすれば、毎回現在の設定を取ってきて、一時的に変更して、通知出した後に戻す、とか出来なくも無いわけですが。
もう一つ問題があって、これを有効、無効化出来るようにしてるわけですが、 これ実はある値が1の時はこれ、0の時はこれ、という2つの別の設定を入れていて、 設定ファイルが膨大になってしまっています。
なので入れてみたものの、もしかしたらそのうち外すかも。。。
メニューバー
メニューバーにどうやって表示しようか、と思ったんですが、 やったことは別のアプリを作って、Karabiner-Elementsの状態を監視して表示する、というもの。
rcmdnk/VEMというアプリをrumpsを使って作りました。
Vim emulationではKarabiner-Elementsの中で変数を覚えておける機能を使ってモードの変更を行っていますが、 それらの値は以下のファイルに記録されています。
/Library/Application Support/org.pqrs/tmp/karabiner_grabber_manipulator_environment.json
Request for a –get-variables option for cli · Issue #2278 · pqrs-org/Karabiner-Elements
なので、後はアプリ側でこれを定期的に見に行くようにすれば良いだけ。
rumpsを使えばそういったメニューバーアプリは簡単に作れます。
なのでこれに関してはVim emulationの方は何も変更せず、アプリを入れるだけで使えるようになります。
起動すると、Vim emulationが有効になっていてモードを変えたりしていれば、
こんな感じで現在のモードがメニューバーに表示されます。
ノーマルモードになれば、
こんな感じ。
デフォルトは色付きアイコンですが、グレースケールな方が良ければ、 オプションで設定できて、
こんな感じで全部がグレースケールなアイコンになります。
rumpsで定期的に実行できる最小単位が1秒なので、変更した後、メニューバーの表示が変わるまでちょっとタイムラグがあります。
ちょっと使ってみた感じでは1秒ごとにチェックしてもシステムに負荷をかけることはないです。
最初はVim emulation側でモード変更時に信号を送って積極的に変更するようなものを考えていたんですが、 rumpsで簡単に作れてしまったのと、Vim emulation側に手を加えなくてもよいということで まずはこれで。
実際作ってみた感じ、このVEMは思った以上にいい感じに出来たと思ってます。
もう1つ欲しい機能としてはVim emulationが有効でないアプリの上に来たときに Disabled表示にしたい、というものがあるのですが、
Windowsでは
Windowsでは AutoHotkeyを使って同じようなものを作っています。
最近一番スターがあるレポジトリになってきました。
こちらでは結構前にタスクトレイアイコンとして状態を表示できるようにしていました。
AutoHotkey自体がポップアップメッセージを出したりも出来るので、インジケーター的なものもあります。