IdeaVIMの適用範囲をテキストエディタ下のEditorのみにしてみた
休み明けとか言っときながら,しんぼうたまらずやっちゃった。:-)
IdeaVIM使ってる人にしかわからんネタだけど,IdeaVIMはIDEAのエディタをホゲるため大抵のエディタ領域でvimモードが有効になるんだけど,ちょっとやり過ぎなところが気になっていた。たとえば,Refactor->Renameの入力エリアやデバッガ中の"Evaluate Expression"や"Set Value"などがそう。ここでvimモードが有効でもうれしい事は無く,むしろ迷惑(だって大抵の場合,ESCキーはキャンセルなんでの)だった。
ためしに,Renameダイアログで":"を入力してみたら,Exモードになったのには笑った。
ちょいと調べてみたら,IdeaVIMが拡張した*1IDEAのコンポーネントはEditorで,主な用途はテキストエディタなんだけど,汎用コンポーネントなんで他でも使われている(それが前述のRename, Evaluate Expression, Set Valueなど)。どうもね,コード補完が必要な入力んときに使ってるみたい。>Editor
そんなわけで,テキストエディタ以外でもvimモードが有効になる理由はわかった。でも「テキストエディタ外じゃ有効になってほしくない」んで,あれこれ調べてみた。結果,IDEAのテキストエディタ部分はFileEditor->TextEditor->Editorという階層構造になっていて,FileEditorにリスナを設定できるってのがわかった。ちょうどIdeaVIMの各種キーイベントハンドラが,「IdeaVIMが有効かどうか?」という判定が入っていたんで,これとFileEditorのリスナを利用して,こんなパッチを当ててみたよ。
Index: src/com/maddyhome/idea/vim/VimPlugin.java =================================================================== --- src/com/maddyhome/idea/vim/VimPlugin.java (revision 1.19.2.12.2.1) +++ src/com/maddyhome/idea/vim/VimPlugin.java Sun Mar 23 12:47:50 JST 2008 @@ -32,6 +32,7 @@ import com.intellij.openapi.editor.event.EditorFactoryEvent; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManagerListener; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; @@ -40,6 +41,7 @@ import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.vfs.VirtualFile; import com.maddyhome.idea.vim.command.CommandState; import com.maddyhome.idea.vim.ex.CommandParser; import com.maddyhome.idea.vim.group.ChangeGroup; @@ -60,6 +62,9 @@ import java.awt.Toolkit; import java.util.ArrayList; +import java.util.Set; +import java.util.Collections; +import java.util.HashSet; /** * This plugin attempts to emulate the keybinding and general functionality of Vim and gVim. See the supplied @@ -79,6 +84,7 @@ public VimPlugin() { logger.debug("VimPlugin ctr"); + editorSet = Collections.synchronizedSet(new HashSet<Editor>()); /* java.net.URL resource = getClass().getResource("/icons/vim32x32.png"); @@ -166,6 +172,8 @@ EditorData.uninitializeEditor(event.getEditor()); event.getEditor().getSettings().setAnimatedScrolling(isSmoothScrolling); DocumentManager.getInstance().removeListeners(event.getEditor().getDocument()); + + editorSet.remove(event.getEditor()); } }); @@ -193,6 +201,14 @@ { FileEditorManager.getInstance(project).addFileEditorManagerListener(listener); } + FileEditorManager.getInstance(project).addFileEditorManagerListener(new FileEditorManagerListener() { + public void fileOpened(FileEditorManager fileEditorManager, VirtualFile virtualFile) { + Editor editor = fileEditorManager.getSelectedTextEditor(); + editorSet.add(editor); + } + public void fileClosed(FileEditorManager fileEditorManager, VirtualFile virtualFile) { } + public void selectionChanged(FileEditorManagerEvent event) { } + }); //DocumentManager.getInstance().openProject(project); @@ -303,6 +319,12 @@ //KeyParser.getInstance().saveData(element); } + private Set<Editor> editorSet; + + public static boolean isEnabled(Editor editor) { + return getInstance().editorSet.contains(editor) && isEnabled(); + } + /** * Indicates whether the user has enabled or disabled the plugin * Index: src/com/maddyhome/idea/vim/handler/key/EditorKeyHandler.java =================================================================== --- src/com/maddyhome/idea/vim/handler/key/EditorKeyHandler.java (revision 1.2.4.3.4.1) +++ src/com/maddyhome/idea/vim/handler/key/EditorKeyHandler.java Sat Mar 22 21:09:16 JST 2008 @@ -52,7 +52,7 @@ { logger.debug("execute"); //if (isEnabled(editor, context)) - if (editor != null && VimPlugin.isEnabled()) + if (editor != null && VimPlugin.isEnabled(editor)) { handle(editor, context); } Index: src/com/maddyhome/idea/vim/VimTypedActionHandler.java =================================================================== --- src/com/maddyhome/idea/vim/VimTypedActionHandler.java (revision 1.1.1.1.4.1.8.1) +++ src/com/maddyhome/idea/vim/VimTypedActionHandler.java Sun Mar 23 12:47:49 JST 2008 @@ -63,7 +63,7 @@ public void execute(Editor editor, char charTyped, DataContext context) { // If the plugin is disabled we simply resend the character to the original handler - if (!VimPlugin.isEnabled()) + if (!VimPlugin.isEnabled(editor)) { origHandler.execute(editor, charTyped, context); return;
ちょっとダーティハックだけど,今んとこ結果オーライで動いている(カーソル形状がブロックカーソルのままなのはご愛嬌)。
(追記)さらに,こんなパッチあててブロックカーソルもなんとかしたよ。
Index: src/com/maddyhome/idea/vim/VimPlugin.java =================================================================== --- src/com/maddyhome/idea/vim/VimPlugin.java Mon Mar 24 14:38:58 JST 2008 +++ src/com/maddyhome/idea/vim/VimPlugin.java Mon Mar 24 14:38:58 JST 2008 @@ -154,12 +154,6 @@ isBlockCursor = event.getEditor().getSettings().isBlockCursor(); isSmoothScrolling = event.getEditor().getSettings().isAnimatedScrolling(); - if (VimPlugin.isEnabled()) - { - event.getEditor().getSettings().setBlockCursor(!CommandState.inInsertMode(event.getEditor())); - event.getEditor().getSettings().setAnimatedScrolling(false); - } - EditorData.initializeEditor(event.getEditor()); //if (EditorData.getVirtualFile(event.getEditor()) == null) //{ @@ -204,6 +198,10 @@ FileEditorManager.getInstance(project).addFileEditorManagerListener(new FileEditorManagerListener() { public void fileOpened(FileEditorManager fileEditorManager, VirtualFile virtualFile) { Editor editor = fileEditorManager.getSelectedTextEditor(); + if (VimPlugin.isEnabled()) { + editor.getSettings().setBlockCursor(!CommandState.inInsertMode(editor)); + editor.getSettings().setAnimatedScrolling(false); + } editorSet.add(editor); } public void fileClosed(FileEditorManager fileEditorManager, VirtualFile virtualFile) { }
*1:正確にはちょっと違う