ぼくがかんがえたさいきょうのIdeaVIM

って言うほど最強じゃないけど,IdeaVIMがリリースされるたびにパッチ当てるの疲れたからforkしたって話。一応,いくつかはpull request出してるよ(放置されてるけどw


公式のIdeaVIMの代わりに,ここに置いてあるオレオレIdeaVIMを使うと,IntelliJ起動時にIdeaVIMに好きなキーマップを設定できるようになります。
https://github.com/masanobuimai/ideavim/downloads


元々過去に作ったオレオレパッチの集大成なのだけれど,Vrapperのmapコマンドが羨ましくて,でもmapコマンド実装するほどの腕と根性がなかったので,この辺で妥協したやつ。
詳しくはこの辺参照してね。→ mapコマンドの代わりに,こんなの作ってみた #intellij - marsのメモ


使い方は,こんな設定ファイル(_ideavimrc.groovy)をホームディレクトリに置いて,そこに好きなキーマップを定義します。

import com.maddyhome.idea.vim.key.KeyParser
import com.maddyhome.idea.vim.key.Shortcut
import com.maddyhome.idea.vim.command.Command
import javax.swing.KeyStroke
import java.awt.event.KeyEvent


// gc, gf, gs, ga でそれぞれのGotoコマンド実行
parser.registerAction(KeyParser.MAPPING_NORMAL, "GotoClass", Command.OTHER_READONLY, new Shortcut("gc"))
parser.registerAction(KeyParser.MAPPING_NORMAL, "GotoFile", Command.OTHER_READONLY, new Shortcut("gf"))
parser.registerAction(KeyParser.MAPPING_NORMAL, "GotoSymbol", Command.OTHER_READONLY, new Shortcut("gs"))
parser.registerAction(KeyParser.MAPPING_NORMAL, "GotoAction", Command.OTHER_READONLY, new Shortcut("ga"))

// Ctrl+] で定義に移動。Ctrl+T で戻る
parser.registerAction(KeyParser.MAPPING_NORMAL, "GotoDeclaration", Command.OTHER_READONLY, Command.FLAG_MOT_EXCLUSIVE,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, KeyEvent.CTRL_MASK)))
parser.registerAction(KeyParser.MAPPING_NORMAL, "Back", Command.OTHER_READONLY, Command.FLAG_MOT_EXCLUSIVE,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK)))

// J を IntelliJ の join lines にリマップ
parser.registerAction(KeyParser.MAPPING_NORMAL, "EditorJoinLines", Command.OTHER_READONLY, new Shortcut("J"))

// Ctrl-n, Ctrl-p でキーワード補完
parser.registerAction(KeyParser.MAPPING_INSERT, "HippieBackwardCompletion", Command.COMPLETION, Command.FLAG_SAVE_STROKE,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)));
parser.registerAction(KeyParser.MAPPING_INSERT, "HippieCompletion", Command.COMPLETION, Command.FLAG_SAVE_STROKE,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_MASK)))


「なんじゃこりゃ?」な内容だと思うけど,IdeaVIMのキーマップ設定を司っている RegisterActions.java を参考に試行錯誤してちょうだい。一時はこれをもうちょっとDSL風にしようかなとも思ったけど,そこまでする気力がなかった。
https://github.com/masanobuimai/ideavim/blob/master/src/com/maddyhome/idea/vim/key/RegisterActions.java


なんとなく想像が付くと思うけど,parser.registerAction()

  • 第1引数が IdeaVIM のモード
  • 第2引数が実行したいIntelliJプラグインのアクション(アクションID)
  • 第3,4引数がコマンドのタイプやオプション(あんまりよくわかってない
  • 最終引数がマッピングするキーストローク

となっとります。アクションIDについては,IdeaVIMやその他プラグイン固有のものは,それぞれのMETA-INF/plugin.xmlに書いてあるし,IntelliJ本体のものは,大昔に調べたこちらが参考になる(調べたときはIDEA8くらいだと思うけど。
プラグイン作って覚えたことを淡々と記録するよ(ActionManagerの登録ID一覧)


諸注意はいろいろあるけど,大事なのはここに登録したキーストロークが元々IdeaVIMにマップされてないと意味無いので,新規のストロークを登録する際には,以下の設定でIdeaVIMにそのキーストロークを割り当ててちょうだい。

Settings -> Keymap -> Plug-ins -> IdeaVIM -> Keys に設定したいキーストロークを登録する
※Keysは2つあるけど,すでにいろいろ登録されているほうに追加する(もう一方は使わない。


あと,このパッチの設定場所みるとわかるけど,parser.registerAction()のキー設定が先勝ちで登録されていくことを利用したしょっぱいパッチなので,いわゆるunmap的なことはできませんので,あしからず。
https://github.com/masanobuimai/ideavim/blob/myPrototype/src/com/maddyhome/idea/vim/key/RegisterActions.java#L43


ちなみに,IdeaVIMのモードに関係なく「IntelliJのこの機能をこのキーに割り当てたい」って場合は,普通にSettings->KeymapでIdeaVIM(のKeys)からそのキーマップを奪えばよいだけ。この魔改造の利点はIdeaVIMのモードごとにキーマップできることです。あとノーマルモードで装飾キーなしのキーストローク使えるのも便利ね。


これ以外にもちょぼちょぼ手を加えているので,詳しいことはコミットログみてね。
Commits · masanobuimai/ideavim · GitHub


【IdeaVIM豆知識】 ~/.vimrc~/_vimrc があれば,ちゃっかりIdeaVIMも読み込んでるってのはマメな。IdeaVIMが解釈できるオプションは :set コマンドでわかるよ。
https://github.com/masanobuimai/ideavim/blob/master/src/com/maddyhome/idea/vim/option/Options.java#L419