mapコマンドの代わりに,こんなの作ってみた

vrapperのmapコマンド,うらやましいと思ったんだけど,よくよく考えてみたらホントに欲しいのは mapコマンド じゃなくて
 「IDEネイティブコマンドをvim風コマンドにリマップする」

ことだったと気づいた。


今までやってたオレオレmapコマンドもどきもやってることはソレだしね。そんなわけで,mapコマンドの実装止めて,こんなパッチ当ててみたよ。

Index: src/com/maddyhome/idea/vim/key/RegisterActions.java
===================================================================
--- src/com/maddyhome/idea/vim/key/RegisterActions.java	(revision 1:dfc4accaca00)
+++ src/com/maddyhome/idea/vim/key/RegisterActions.java	(revision 1+:dfc4accaca00+)
@@ -22,9 +22,13 @@
 import com.maddyhome.idea.vim.command.Argument;
 import com.maddyhome.idea.vim.command.Command;
 import com.maddyhome.idea.vim.helper.ApiHelper;
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+import groovy.lang.Script;
 
+import javax.swing.*;
 import java.awt.event.KeyEvent;
-import javax.swing.KeyStroke;
+import java.io.File;
 
 /**
  * This registers all the key/action mappings for the plugin
@@ -756,7 +760,23 @@
             KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SLASH, KeyEvent.CTRL_MASK),
             KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)
         }));
+
+        try {
+            String home = System.getProperty("user.home");
+            if (home != null) {
+                File rc = new File(home, "_ideavim.groovy");
+                if (!rc.exists()) return;
+                Script script = new GroovyShell().parse(rc);
+                Binding binding = new Binding();
+                binding.setVariable("parser", parser);
+                script.setBinding(binding);
+                script.run();
-    }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
 
+    }
+
     private static RegisterActions instance;
 }


あとは,$HOME/_ideavim.groovy というファイルを用意して,こんな風なこと記述すると,あら不思議。独自のキーストロークIDEネイティブコマンドを追加設定できるようになったよ。

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


// ALT+N, ALT+P で単語補完
parser.registerAction(KeyParser.MAPPING_INSERT, "HippieCompletion", Command.INSERT, Command.FLAG_SAVE_CHANGES,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.ALT_MASK)))
parser.registerAction(KeyParser.MAPPING_INSERT, "HippieBackwardCompletion", Command.INSERT, Command.FLAG_SAVE_CHANGES,
    new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.ALT_MASK)))

// 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)))

IdeaVIMに未設定なショートカットキー(Ctrl+xxとかALT+xx)を追加した場合は,Settings -> Keymap -> Plug-ins -> IdeaVIM -> Keys に,そのショートカットキーを追加するのをお忘れなく。

このパッチのイマイチな点。

  • IdeaVIMのKeyParserにunregisterが無いので,すでに設定済みのキーストロークを上書きできない。
    • これ超くやしいッ!!
    • そう思うんだったら,KeyParserにunregister()実装するか,registerAction()で上書きしちゃうようにすりゃいいんだけど。:-P
  • _ideavim.groovyの構文がDSLっぽくない。
    • せめてimport文くらいは無くてもいいようにしたいな。
  • Groovyの言語特性上,_ideavim.groovyをドットファイル(.ideavim.groovy)にできない。
    • これは別にいいや。

そんでも,マトモにmapコマンド実装するより遙かに簡単だった。Groovyかっこよす。


ps.
拙いながらも本家に提案してみるかな...。誰か代わりにタレこんでくれてもいい。むしろ頼む。:-P