はじめに
唐突ですが今回が最終回です。今までも好き放題書いてきましたが、最終回はさらに趣味に走ってIdeaVIMプラグイン だけの話をします。
IdeaVIMとは、名前から想像できるようにvim の機能を再現するプラグインです。それなりに再現度が高いこともあり、地味に人気のあるプラグインです。筆者はかれこれ10年以上、このプラグインを愛用しています。
IdeaVIMの歴史
プラグインの中でも古参のほうで、2003年にはすでに存在していました。もともとは一人の有志の方が作ったプラグインでしたが、作者のRick Maddyさんが「Java関係の仕事から離れそう」という事で、後継者を募ったところJetBrains社のOleg Shpynovさんが名乗り出ました。登場時から人気もあり、JetBrains社の人(いわゆる中の人)がコミッタになった事もあって、いつの間にかJetBrains公式プラグインとなりました。ただ、公式プラグインといってもAndroid StudioやIntelliJがvimモードを考慮した仕組みになっている訳ではありません。相変わらず無理を通してvimモードを再現しています。
JetBrains公式プラグインといってもオープンソースです。パッチ提供やバグ報告はいつでも歓迎です。
現在のコミッタは同じくJetBrains社のAndrey Vlasovskikhさんです。とても活発な方で、Twitterで「IdeaVIM~」とかつぶやくと、それが日本語だろうがお構いなしにメンションを打ってきます。どうやらロシア圏の方のようで普段はロシア語でつぶやいているのですが、その時は英語で問いかけてくるので、ビックリしないで相手をしてあげてください。それと一応、IdeaVIM専用のTwitterアカウントもあります(中の人は Andrey さんです) 。
10年以上の歴史をもつプラグインということもあり、vimのエンジン部分はvim6をベースに作られています。世間的にvimが流行りだしたのはvim7からだと思うので、vim7ユーザにとっては若干物足りない実装になっています。それでもText-Objectsなど、ある程度vim7の機能も取り込んでいます。
IdeaVIMは結構まじめにvimっぽい動作をするプラグインですが、どうやっても「がんばって真似てる 」域を脱することはありません。後でIdeaVIMの仕組みを紹介しますが、元々vimモードを考慮して作っていないモードレスエディタを無理矢理vim化しただけでも大したものなので、これを許容できるかどうかがIdeaVIMを使えるかどうかのポイントになると思います。
vimのような歴史あるエディタの愛用者は、それぞれ独自のこだわりを持っています。それ故、vim風、vim互換モードという謳い文句に期待しては落胆を繰り返していると思います。それなりにvimキーバインドの呪いにかかっている筆者が10年近くIdeaVIMを使い続けて得た教訓は「寛容 」です。vim以外のエディタは何をどうしようとvimにはなれません。そこを呑み込んだ上でIdeaVIMに接しましょう。
平たく言うと「IdeaVIMはvimではなくて、vimっぽい操作ができるIdeaVIMという新しいエディタ」なのです。
その他のvimプラグインについて
世の中のvim使いの執念たるや凄まじく、どんな環境にでもvimキーバインドを持ち込もうとしています。探してみると、大抵どのIDEにもひとつはvimプラグインが存在してます。
Eclipse : Vrapper
IDE用vimプラグインの中で唯一 map
コマンドを実装しています。vimscriptはサポートしていませんが、独自に surround.vim
相当の機能を実装しています。
この他にEclim というvimプラグインとしては反則レベルで完成度の高いプラグインがあります(vimからEclipseを使う、逆転発想のプラグインです) 。
NetBeans : jVi
古くはJBuilderのviプラグインだったのをNetBeans用に移植したものです。もともと vi プラグインだったのですが、ここ最近のバージョンアップで vim の機能が追加されています。Ctrl-W
系のウィンドウ分割機能など、割りと細かい点までvim風に仕上げている印象があります。
Visual Studio : ViEmu
今回紹介した中では唯一の有償プラグインです。Visual Studio以外にXcode, Word, OutlookやSQL Serverでも使えるようです。残念ながら筆者は使った事がありません。
Xcode : XVim
Xcode用のVimプラグインです。こちらも筆者は使ったことがありません。
Excel : Vimxls
Excel用のVimプラグインです。ここまで来ると執念すら感じられます。
vimそのものが魅力的なエディタであるのは間違いありませんが、このモードレスエディタ全盛の世の中でvimキーバインドに慣れてしまう事は、他の環境(エディタやIDE)を使う上でかなり不利な状況になりがちです。そんな中、vimだけに籠もらず、モードレスだとかお構いなしに色んな環境でしぶとくvimモードを再現しようと試みている作者の方々の執念には脱帽します。
IdeaVIMのインストールと諸設定
プラグインマネージャ(「 Preferences / Plugins」 )から「IdeaVIM」を選びインストールしてください。インストールが完了すると再起動を促すので、指示に従ってAndroid Studioを再起動します。再起動すると次のようなダイアログが表示されるので、ベースにしたいキーマップを選択します。
図1 「 Vim Keymap setting」ダイアログ
※「Toolsメニュー」の "Reconfigure Vim Keymap " でいつでも再設定できます。
これでIdeaVIMが有効になります。見た目には変化が分かりませんが、Toolsメニューの"Vim Emulator "がONになっていることと、キーマップ設定(「 Preferences / Keymap」 )が"Vim"になっていることでIdeaVIMが有効になっていることがわかります。そうそう、カーソルがIビームからブロックカーソルに変わるので、これでもIdeaVIMが有効になっていることが分かります。
図2 Toolsメニューの"Vim Emulator"
※ IdeaVIMのON/OFFをここから制御できます。
図3 「 Preferences / Keymap」設定画面
このあたりの仕組みについては後で解説するので、まずはIdeaVIMでどんなことができるのか紹介します。
IdeaVIMでできること・できないこと
いわゆる4つのモード(Normalモード、Insertモード、Visualモード、コマンドモード)を備えています。Vimそのものには敵わないにしろ、極力Vimでできることを再現しています。一応、IdeaVIM公式のコマンド一覧があるのですが、困ったことにこれが全てというワケでは無いです。ただ、ここに載っているコマンドはすべて機能するので参考にはなります。
h,j,k,l など基本的なカーソル移動
基本的な操作はVimと遜色ありません。IdeaVIMのもっとも特徴的な機能が、単語区切りでのカーソル移動(Word Motions)が非ASCII文字にも対応していることです。筆者の知る限りでは、Vim本体以外でこの機能を実装しているVimプラグインはIdeaVIMだけです。
図4 IdeaVIMのWord Motionsの例(クリックすると動きがわかります)
Vimとの細かい違いは、IdeaVIMは論理改行間のカーソルの上下移動もj, k
で移動します。つまりIdeaVIMのj, k
は実際のところはgj, gk
扱いということです。
Ctrl-[による編集モードへの復帰
Vimに慣れた人の中にはNormalモードへの復帰にESCキーではなく、Ctrl-[ にクセをつけてしまった人たちが居ます。IdeaVIMも Ctrl-[ でNormalモードへの復帰が可能なのですが、JISキーボードの場合、それが Ctrl+@ に割り当てられています。
JISキーボードでも Ctrl-[ に割り当て直すことは可能です。キーマップに関しては、あとでまとめて説明します。
Visualモード
Android Studioの範囲選択と連動しています。選択範囲は"Cut, Copy "でクリップボードに保存することも、IdeaVIMのYankバッファに保存することもできます。Exコマンドの [range]
にも利用できます。
また、Android Studioの"Column Selection Mode "とは別に専用の矩形選択モード(Ctrl-V )を持ちます。
Text-Objectsのサポート
もともとIdeaVIMはvim6ベースですが、いくつかText-Objectsをサポートしています。VisualモードやNormalモードの演算子未解決(Operator Pending)モード時の範囲指示に使用できます。
サポートしているText-Objectsをリスト1 に示します。残念ながら「at, it
( a tag block, inner tag block) 」はサポートしていません。一応チケットはあがっていますが、長いこと放置されたままです。
また iskeyword
オプションを設定することもできません。
リスト1 IdeaVIMがサポートしているText-Objects
aw, aW, iw, iW : a word/WORD, inner word/WORD
as, is : a sentence, inner sentence
ap, ip : a paragraph, inner paragraph
a[, a], i[, i] : a [] block, inner [] block
ab, a(, a), ib, i(, i) : a block, inner block
a<, a>, i<, i> : a <> block, inner <> block
aB, a{, a}, iB, i{, i} : a Block, inner Block
a", a', a`, i", i', i` : a quoted string, inner quoted string
キーボードマクロのサポート
q
コマンドによるマクロの記録。@
コマンドによる実行をサポートしています。マクロの記録は実際にタイプしたキーだけを記録します。Insertモード時にAndroid Studioのコード補完に頼った場合、補完候補を絞り込むまでにタイプしたキーだけがマクロに記録されます。
ジャンプコマンドのサポート
主立ったジャンプコマンドをサポートしています。ブロック間の移動(%, [{, [(, ]), ]}
)やメソッド間の移動([m, [M, ]m, ]M
)も可能です。
メソッド間の移動に関しては、Android Studioの"Next/Previous Method "より使いやすいです。
/, ? のインクリメンタルサーチ
インクリメンタルサーチはできません。普通の検索のみです(キーワードを入力してEnterキーを押す) 。
*, #でカーソル位置のワードを検索
できます。
検索語のハイライト表示
初期設定を変えてなければ :hls
が有効になっています。/,?
や *, #
で検索語がハイライト表示されている場合、:nohl
でそのハイライトを消すことができます。
Exコマンド
全てではありませんがある程度のExコマンドをサポートしています。IdeaVIMが提供しているExコマンドはリスト2 の通りです。ほとんどはvim由来のものばかりですが、一部にIdeaVIM固有のコマンドがあります。いくつかおもしろいコマンドをピックアップして紹介します。
:class, :find, :symbol : 頭から順に「Navigateメニュー」の "Class...", " File... ", "Symbol... " に対応しています。それなりに便利なのですが、SHIFTキー2回押しの"Search Everywhere "ができてからはありがたみが減ったかも知れません。
:promptfind, :promptrepl : それぞれ「Edit → Findメニュー」の "Find..." と " Replace... " に対応しています。/
, ?
がインクリメンタルサーチに対応していないので :pro
のほうが使い勝手がよいです。:promptrepl
はコマンドを覚えられないので、ほとんど使った事がありません。
:quit, :wq, :exit : このコマンドを実行してもAndroid Studioは終了しません。エディタのタブが閉じるだけですので、ご安心ください。
:w, :wq : イベントが起こるたびにオートセーブするAndroid Studioにはあまり意味の無いコマンドですが、一応 特定のファイルだけセーブすることができます。
:help : ヘルプです。引数に与えたキーワードを vimdoc.sourceforge.net から検索します(Webブラウザが起動します) 。
:dumpline : IdeaVIMのデバッグコマンドです。Android StudioのログにDebugレベルで出力するので、普通は何が起きたかわかりませんし、気にしなくてもよいです。
リスト2 IdeaVIMがサポートしているExコマンド一覧
:ascii(:as), :!, :copy(:co), :t, :delete(:d), :digraphs(:dig),
:dumpline*, :browse(:bro), :edit(:e),
:qall(:qa), :quitall(:quita), :wqall(:wqa), :xall(:xa),
:file(:f),
:class(:cla)*, :find(:fin), :symbol(:sym)*, :goto(:go),
:help(:h), :history(:his), :join(:j), :jumps(:ju),
:mark(:ma), :k, :marks, :move(:m), :next(:n), :nohlsearch(:noh),
:only(:on), :Next(:N), :previous(:prev),
:promptfind(:pro), :promptrepl(:promptr), :put(:pu),
:quit(:q), :close(:clo), :hide(:hid), :redo(:red),
:display(:di), :registers(:reg), :@, :argument(:argu),
:first(:fir), :rewind(:rew), :last(:la), :set(:se),
:<, :>, :substitute(:s), :&, :~, :undo(:u),
:wall(:wa), :write(:w), :wnext(:wn), :wNext(:wN), :wprevious(:wp),
:wq, :exit(:exi), :xit(:x), :yank(:y)
※ カッコ内は省略コマンド名、アスタリスクが付いているのはIdeaVIM固有のコマンドです。
ウィンドウ分割
できません。Android Studioがもともと備えているウィンドウ関連のコマンドに、Vim風なショートカットキーを割り当てることで疑似的に再現することは可能です。それでもVimに比べれば、Android Studioが提供しているウィンドウ分割系のコマンド些細なものばかりなので気休め程度でしかありません。
mapコマンドによるキーアサインの変更
できません。Android Studioがもともと持つ「Preferences / Keymap」でIdeaVIMのキーアサインを 奪い返す ことは可能です。このあたりの仕組みについては後述します。
当然、map
コマンドの要望は高いのですが未だ実装されずにいます。実装の困難さも想像できるので、そう簡単には解決しないでしょう。
VIM-288 Support key mapping commands from .vimrc
vimscript
できません。私の知る限りにおいて、これを実装しているIDE用vimプラグインは皆無です。さすがに、これは無茶振りだろうと皆思うのか、チケットすらあがってません。
筆者は若干(?)IdeaVIMびいきな事もあってかvimscriptをIDEのvimプラグインに求めるのは、そもそもの方向性が間違っているとさえ思ってます。
宣言に移動(Ctrl+])と元居た場所に戻る(Ctrl+T)、Javadocの参照(K)
できます。「 宣言に移動(Ctrl+]
) 」については、ESC(Ctrl-[
)と同じく、JISキーボードの場合は Ctrl+[
に割り当てられています。また gd
や gD
でも「宣言に移動」できます。
カーソル位置のJavadocを参照する "Quick Documentation " は、一見するとメニューバーからはショートカットキーの割り当てが解除されるだけなのですが、ちゃっかり K
コマンドに割り当てられています。まあ、vimらしいキーアサインですね。
タブ移動(gt/gT)
できます。個人的には、Exコマンドの :n, :N
のほうがタイプ数が少ないので好みです。
折り畳み(folding)
zM, zR
( すべて閉じる、すべて開く) 、zc, zo
(閉じる、開く)の4つのみサポートしています。
Projectツールウィンドウで "Reformat Code..." が効かなくなる
IdeaVIMを使っている人にとっては有名なバグなのですが、IdeaVIMを入れるとProjectツールウィンドウのコンテキストメニューから "Reformat Code... " が実行できなくなります(図5 のように不活性状態になる) 。
図5 Projectツールウィンドウで "Reformat Code..." が使えない
困った事に、Toolsメニューの "Vim Emulator " でIdeaVIMを無効にしてもダメで、プラグインマネージャでIdeaVIMをOFFしないと元に戻りません。
だいぶ昔から存在しているバグなのですが、何か根が深い問題があるのか未だに直らずにいます。
エディタ上で "Reformat Code... " を実行することはできます。その時「Reformat Code」ダイアログで「このファイルがあるディレクトリ全体(All files in directory ?) 」を指定すれば似たような事は再現できるのですが、正直面倒です。
IdeaVIMのオプションと .ideavimrc
IdeaVIMもvim同様 :set
コマンドによるオプション設定が可能です。設定可能なオプションとその初期値は表1 の通りです。オプションの意味はvimのものと同じで、省略記法も同じものが使えます。たとえば「hlsearch
」は「hls
」でもOKです。
表1 IdeaVIMで有効なオプションの一覧
オプション名 省略記法 初期値
digraph
dg
nodigraph
gdefault
gd
nogdefault
history
hi
20
hlsearch
hls
nohlsearch
ignorecase
ic
noignorecase
matchpairs
mps
(:),{:},[:]
more
more
more
nrformats
nf
octal,hex
scroll
scr
0
scrolljump
sj
1
scrolloff
so
0
selection
sel
inclusive
showmode
smd
noshowmode
sidescroll
ss
0
sidescrolloff
siso
0
smartcase
scs
nosmartcase
undolevels
ul
1000
visualbell
vb
novisualbell
wrapscan
ws
wrapscan
設定可能なすべてのオプションを参照する方法や、現在の設定値の確認方法もvimと同じく「:set all
」や「:set
」で確認できます。
ここまで同じだと、アレもそうか?と予想できるように初期設定をRCファイルに記述しておくことも可能です。RCファイルは <HOME>
ディレクトリに格納したファイルを上から順番に探していき、見つかったファイルのみを読み込みます(リスト3 ) 。
リスト3 IdeaVIMのRCファイルの候補と読み込み順
<HOME>/.ideavimrc
<HOME>/_ideavimrc
<HOME>/.vimrc
<HOME>/_vimrc
※ 最初に見つけたRCファイルだけを読み込みます。
ここで困った事は、vimのRCファイル(.vimrc
と_vimrc
)も読み込む対象にしていることです。仮にIdeaVIMがvimのRCファイルを読み込んでも、評価できるのは表1 のオプション行のみなので、その他のvim向けの記述がIdeaVIMに悪影響を及ぼすことはありません。唯一の困り事は、そのオプションの解釈がvimとIdeaVIMと若干異なるものがあると言うことです。
IdeaVIMの利用者は高確率でvimも使っているでしょう。IdeaVIMのRCファイルの仕組みを知らないため、意図せずに.vimrc
や_vimrc
をIdeaVIMが読み込んでいるのです。vimもIdeaVIMも同じRCファイルを共有することは、あまり気持ちの良いことではないので 空でも良いので IdeaVIMのRCファイル(.ideavimrc
か_ideavim
)を用意しておくことをオススメします。
selectionモードの解釈違い
それなりにがんばってvimっぽく振る舞っているIdeaVIMですが、selection
の解釈は微妙なズレがあります。IdeaVIMの内部構造を知る者としては「これくらいはそっとしておいてあげよう」と思わざるを得ないのですが、RCファイルをvimと共有すると捨ておく事ができないほど目立つので、IdeaVIM専用のRCファイルはどうしても必要になります。
selection=inclusive
もselection=exclusive
も、それとなくvimと挙動が異なります。ただinclusive
のほうが違いが目立ちません。筆者は exclusive
を好んでいるのですが、IdeaVIMの exclusive
の挙動がガマンできず、IdeaVIMのみ inclusive
になるようIdeaVIMのRCファイルに設定しています。
残念ながら、IdeaVIMの exclusive
は実用レベルとは言い難いです。実際に試してみるとわかりますが、IdeaVIMは selection
をexclusive
にしてもVisualモードでカーソルがIビームになりません(ブロックカーソルのままです) 。そのため、端(はし)の判定がvimより1文字足りなくなります。
図6 selection=exclusiveの選択範囲の違い(IdeaVIMとvim)
行単位で選択する場合は、それっぽく振る舞っていますが、それは行選択限定の振る舞いのようで、文字単位の選択では違いが顕著に表れます。この違い、IdeaVIMを使うほどvimに呪われている皆さんは「たったそんなこと」だなんて思いませんよね。
IdeaVIMの仕組み
前述したとおり、IdeaVIMは「なんちゃってvim」レベルで、vimと全く同じ感覚で使おうとすると違和感を感じる部分が多々あります。この微妙な違いがストレスの元になるので、コアなvimユーザであるほど許しがたく感じます。
気休めではありますが、IdeaVIMの仕組みをある程度理解しておくと、違和感にも納得できる部分がでてきます。一介の利用者が内部の仕組みを意識して、回避策を労するというのもおかしな話ですが、仕組みを知っていれば修正方法もわかるかも知れませんし、そうしたらパッチを送ることもできるでしょう。せっかくのオープンソースなので、不満があるなら直してしまいましょう。それはそれで本末転倒な気もしますが、これがvimユーザの性(さが)なのだと信じています。
能書きが長くなりましたが本題に入ります。IdeaVIMの基本的な仕組みは『Android Studioのエディタに対するキー入力を横取りして、vimっぽく振る舞う 』事です。図7 のように、
Android Studioのエディタ上に薄いIdeaVIMの層があり、
NormalモードやVisualモードの時はIdeaVIMがキー入力をすべて捌き、
Insertモードの時のみ、IdeaVIMの層に穴を空けて直接Android Studioにキー入力を渡す
……というイメージで動いています。そのため、冗談のようなホントの話なのですが、vimの機能をほぼ丸ごと実装しています。これはIdeaVIMに限った事では無く、Vrapper、jViなどの他のvim風プラグインも似たような実装になっています(これを知ったとき、世の中のvim使いの執念を垣間見た気がしました) 。
図7 IdeaVIMの仕組み(概念図)
IdeaVIM導入後に任意のキーマップからVimキーマップを作成するのは、エディタへのキー入力をIdeaVIMが捌くための仕組み作りのひとつです。ここで重要なのはキーマップ名が「Vim 」であることではなく、ショートカットキーの塊をIdeaVIMに割り当てることです。具体例を見た方がわかりやすいのですが、IdeaVIMを有効にすると「Preferences / Keymap」の「Plug-ins / IdeaVIM / Keys」に多数のショートカットキーが割り当てられます。
図8 「 Preferences / Keymap」の「Plug-ins / IdeaVIM / Keys」の設定
※「Keys」は2つありますが、下の方に多数のショートカットキーを割り当てています。
この「Keys」を起点にして、IdeaVIMは多種多様なショートカットキーをvim風に解釈してAndroid Studioのエディタに反映しているのです。IdeaVIMのインストール直後(または"Reconfigure Vim Keymap "実行時)に「Vim Keymap setting」ダイアログで「Vim」キーマップを作成しているのは、「 あるキーマップに、IdeaVIM用の設定―――「Keys」にショートカットキーを割り当てる」ためです。
図9 "Reconfigure Vim Keymap"の仕組み
このような仕込みをしているため「Vim」キーマップはそれなりの意味を持ちます。一応、IdeaVIMはキーマップが「Vim」以外になっていると警告を発します。
図10 「 Vim」キーマップ以外になっていると警告が出る
ただ、本当に意味があるのはキーマップが「Vim」であることではなく、「 Keys」に多数のショートカットキーが割り当てられている事なので、厳密に言えばキーマップが「Vim」以外でもIdeaVIMは機能します。これ、後のキーカスタマイズに重要になるので覚えておいてください。
IdeaVIMの有効範囲
IdeaVIMによるvi/vimキーバインドはAndroid Studioのエディタ部分 に対してのみ有効です。それ以外、例えばツールウィンドウやナビゲーションバーではvimキーバンドは使えません。
ただ、落とし穴というか引っかけ的なトラップがあります。IdeaVIMが作用するのはAndroid Studioのエディタ部分です。もっと細かく言うと、Android Studioのエディタコンポーネントに対して作用します。このエディタコンポーネントがクセ者で、主にエディタ部分に使われているのですが「ぱっと見、テキストフィールドぽい部分も実はエディタコンポーネントだった」なんて事がよくあります。
IdeaVIMは、エディタ部分以外でエディタコンポーネントを使っている場合、初期状態をInsertモードにしているため、その事実に気付くことは稀です。一番分かりやすいのは「Commit Changes」ダイアログの「Commit Message」のテキストエリアでしょう。このエリアがまさにエディタコンポーネントで初期状態がInsertモードの典型です。
図11 「 Commit Meesage」エリアはIdeaVIMのコマンドが使える(クリックすると動きがわかります)
「Commit Message」エリアもIdeaVIMの影響下にあるため、ESCキーでNormalモードに移行することができます。意味があるかどうかは別としてExコマンドも実行できます。
このような部分が他にもいくつかあります(どこでエディタコンポーネントを使っているかは、Android StudioやベースのIntelliJの都合で変わります) 。ときおり入力フィールドにフォーカスが当たっているのにキー入力が一切受け付けない状況になった場合は、実はそこがIdeaVIMの影響下で知らないうちにNormalモードになっているだけかも知れませんよ(a
やi
を押すと入力できるようになったりします) 。
現状のIdeaVIMでできるキーカスタマイズ
IdeaVIMにmap
コマンドは提供されていませんが、まったくキーカスタマイズができないかというとそんなことはありません。IdeaVIM内のキーアサインは変更できませんが、IdeaVIMに奪われたキーバインド(ショートカットキー)をAndroid Studioに奪い返すことはできます。
たとえば、筆者はWindows版のgVimを普段使いしているのですが、クリップボード操作に Ctrl-X, C, V
を使いたいため mswin.vim が欠かせません。IdeaVIMでも同様にしたい場合、そのショートカットキーをAndroid Studioの本来の機能に再定義するのが手っ取り早いです。
IdeaVIMから奪い返したショートカットキーは、IdeaVIMの影響を受けなくなるのでNormalモード、Insertモードに関わりなく機能します。IdeaVIMはモードによってショートカットキーに複数の機能を割り当てているので、どのショートカットキーを奪い返すかは厳選してください。また、なんでも感でも奪い返せるわけでは無いので、何度か試行錯誤する必要があります(この時点ですでに魔改造なのです) 。
筆者がIdeaVIMから奪い返したショートカットキーは、だいたい表2 の通りです。
表2 IdeaVIMから奪い返して再定義したショートカットキーの例
ショートカットキー 再定義したコマンド
Ctrl-[
"Escape "
Ctrl-A
"Select All "
Ctrl-X
"Cut "
Ctrl-C
"Copy "
Ctrl-V
"Paste "
Ctrl-Z
"Undo "
Ctrl-T
"Back "
Ctrl-]
"Declaration "
Ctrl-W
"Select Word at Caret "
そう滅多にやらない操作だと思いますが "Reconfigure Vim Keymap " を実行すると「Vim」キーマップが初期化されるため、ショートカットキーを奪い返す操作は「Vim」キーマップに対してではなく、「 Vim」キーマップを別のキーマップにコピーしてから行う事をオススメします。
IdeaVIMの魔改造のすすめ
ショートカットキーをAndroid Studioに奪い返すだけでは満足できない人の最後の手段がIdeaVIMの魔改造です。極論ですが、IdeaVIM自身がオープンソースなのでその気になればナンデモできます。何を隠そう筆者もIdeaVIMの魔改造に手を染めたひとりです。
意外というか当然というか、IdeaVIMをforkして自分用のIdeaVIMを作っている人はそれなりに居るようで、IdeaVIMユーザの中では決して珍しい事ではありません。
実際、ショートカットキーを変更するだけならば、それほど大変ではないです。IdeaVIMのキー設定は RegisterActionsクラス に集約されており、ここの parser.registerAction()
でコマンドとショートカットキーの割り当てを行っています。
リスト4 がRegisterActions
クラスの抜粋になります。これはカーソルを下に移動する機能の割り当てなのですが、"VimMotionDown"
というコマンドにj, ↓(VK_DOWN), Ctrl-J, Ctrl+N
の4つのショートカットキーを割り当てています。
リスト4 RegisterActionsクラスの一部
parser.registerAction(KeyParser.MAPPING_NVO, "VimMotionDown", Command.Type.MOTION, Command.FLAG_MOT_LINEWISE, new Shortcut[]{
new Shortcut('j'),
new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_J, KeyEvent.CTRL_MASK)),
new Shortcut(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)),
});
parser.registerAction()
の第二引数(リスト4 の例だと "VimMotionDown"
)がAndroid Studioに登録しているコマンド名になります。コマンド名が "Vim~"
ではじまるものはIdeaVIMが新規に登録したコマンドで、それ以外はAndroid Studioが元々持っているコマンドになります。
さらに加熱すると独自のExコマンドを開発することもできます。Exコマンドは com.maddyhome.idea.vim.ex.handerパッケージ に格納されており、CommandParserクラス を介してIdeaVIMに登録します。ソースコードを覗いてみるとわかりますが、そんなに難しいことはやっていません。
参考までに、筆者が調べていたIdeaVIMの内部情報を提示しておきます。これで味を占めて、IdeaVIM本家にパッチを送っていただけると大変ありがたいです。
さいごに
Androidにほとんど触れず、ひたすらAndroid Studioの操作ばかりしてきた本連載も今回でおしまいです。「 10ヵ月も連載してれば、Ver1.0も出るだろう」とタカを括っていましたが、ようやっと半分のVer0.5.0を過ぎたところです。このペースで開発していたら、ベースにしているIntelliJ IDEAの次のバージョン(ver14)が出てしまいそうなのですが、Android Studioはどこで向かおうとしているのでしょうね。
Android Studioが登場してから、ずっとGoogleの開発ペースに振り回されている感はありますが、Android Studioの元になったIntelliJやビルドシステムに使っているGradleは、それ単体で見れば 良いツールなのは間違いありません。きっとGoogleもより良いAndroid開発環境を整備しようと試行錯誤しているのだと思います。
「正式リリースはまだか」とはやる気持ちもありますが、未だ「EARLY ACCESS PREVIEW」が取れずにいるので、もうしばらくはGoogleと一緒に人柱の気分を味わう心の余裕が要りそうです。