Vim幼稚園からVim小学校へ

  • 2631
    いいね
  • 18
    コメント
この記事は最終更新日から1年以上が経過しています。

emacsキーバインドに慣れ親しんだせいで長らくVim幼稚園のままだった私が来ましたよ。キーバインドを一度に覚えようとすると挫折しやすいので、以下のように少しずつボキャブラリーを増やすのがたぶん吉。

特記しない限りノーマルモードが前提。後、.vimrcでの設定については最小限にしか触れない (emacsでつい設定ファイルをいじってしまいがちだった反省から) ので各自好きにしてください。

Level 1

最小限の使い方だけ覚えて、ぶっつけでサーバーの設定ファイルを更新したりしていた。10年以上この状態。

  • iでその場でインサートモード
  • aで直後の文字にインサートモード
  • :wqで保存終了
  • :q!で保存せずに終了
  • 移動はひたすらカーソルキー
  • xでカーソル下の文字を削除
  • 困ったらEscキーを連打

上はもともと、vimの先祖でずっと機能の少ないviの操作なのだけど、viならほぼどんなたいていのUnix系環境にプレインストールされている。逆に言えば、最小限これだけ覚えれば初めてのサーバーや古代遺跡から発掘された世界遺産クラスのサーバーでもおそらく作業できる。

Vimはめちゃくちゃ巨大なファイルでもあっさり開けるという隠れたメリットがあることを知る (たいていのエディタは巨大ファイルを食わせると数十分押し黙るかコケる)。

Level 2

  • /で検索できることがわかった。
  • h左、j下、k上、l右のvim移動をおそるおそる覚える
  • ggで最初の行、Gで最終行にジャンプできる
  • ctrl-fで1ページ後、ctrl-bで1ページ前に移動
  • 大文字のHMLはそれぞれ画面の最上部・真ん中、最下部の行にカーソルを移動する
  • =でその行のインデント位置を自動修正できる
  • uでアンドゥ、ctrl+rでリドゥ
  • ddで行全体を削除
  • yyp (コピペ) と ddp (カットしてペースト) を覚えた

見てのとおり、まだVimのいいところを全然使っていない。スクロールもカーソルキーでもたもたやってたりする。

Level 3

Vim魔神と出会う。教えのレベルが高すぎてなかなかついていけないので、じわじわと体に染み込ませている。

vimのモード

vimのモードを整理しよう:
- ビジュアルモード (vキー) がたぶん初心者に一番わかりやすいとのこと
- インサートモード (iaキーなど)
- ノーマルモードは基本となるモード
- コマンドモード (:) で各種コマンドを実行

オペレータとモーション

vimのキー(主にノーマルモードについて)は、大きく分けて「オペレータ」と「モーション」の2種類がある。これを把握することが大事。

  • オペレータ: 動詞として動作を指定する。主要なものは4つなのでここから覚えよう
  • モーション: 対象範囲を指定する

オペレータは意味のあるキーバインドになっているので、以下のような感じで覚えよう:

  • c : change (変更)
  • d : delete (削除)
  • y : yank (ヤンク: コピーと同義)
  • g : go (移動全般)

ノーマルモードでは基本的に最初にオペレータを入力し、その後に範囲指定を行う(CUI的発想)が、ビジュアルモードでは範囲を最初に選んでそれからオペレータを入力する (GUI的発想)という違いがある。

なお、Vim魔神に言わせると、Vimは日本語文書の編集にはあまり向いてないそうだ。多分スペース分かち書きされる英語でないといろいろつらいかも。

Level 4

だんだんVimらしい技を覚え始めた。

  • ^または0で行頭へジャンプ、$で行末へジャンプ。正規表現と同じにしたということだけど、自分はemacsのctrl-actrl-e操作に慣れきっていたのと、キー配列で^が右で$が左というふうにジャンプ方向と逆になっているのが直感に反していて、これは今でも個人的にいただけない感じ。あまり使わないようにしてる。
  • oを打つと次の行を空けてインサートモードになる。Oを打つと前の行を空けてインサートモードになる。これは現在のカーソルがその行のどこにあっても関係なく実行できる。これを知って、初めてVimがうらやましくなった。
  • 単語の上で*を押すといきなりその単語を検索して全部ハイライトしてくれる。nで次の検索結果、Nで前の検索結果にジャンプ。ハイライトを消すには:noh(no highlightのことだろう)と打つ。
  • 一文字だけ置き換えたいときはその文字の上でr(replace)キーを打ち、差し替えたい語を打つだけでいい。差し替え後自動的にノーマルモードに戻るので、いちいちiでインサートモードに入ってdeleteで削除してEscでノーマルモードに抜けるより早い。
  • wを打つと次の単語の頭に、bを押すと前の単語の頭にジャンプする。大文字のWBは記号を単語の一部とみなすのでジャンプ距離が伸びる。これは単なるショートカットではなく、wはこの後いろいろと応用が効く。行内での左右移動は基本これにするのが吉。
  • eを打つと次の単語の末尾にジャンプ。ところで前の単語の末尾にジャンプってあるんだろうか(追記: geだそうです)。
  • 追記: eaと打つと、現在の単語の直後でインサートモードになる。これも地味に便利。

Level 5

  • ""で囲まれている中にカーソルを置いて、ci"(change inner quoteと覚えよう)と打つと、""の中身を消してインサートモードに変わってくれる。""の末尾までカーソルを移動してiを押して""の中身をdeleteで1つずつ消して、とやるより早い。これを覚えて、俄然Vimがよさげに見えてきた。このciなんちゃらは応用が効く。たとえばciwとすれば、カーソルがある単語だけが消えてインサートモードに変わるし、ci'とすれば''で囲まれたところで同じことができる。
  • 追伸: 最近覚えたcitは、HTMLタグに挟まれた要素をまるっと消してインサートモードになってくれる。
  • 魔神いわく、インサートモードのEscjjにバインドしておくとめちゃ便利だそうだ。.vimrcにinoremap <silent> jj <ESC>と書けばよい。jjという文字の並びはまず出てこないので実用上支障はない。
  • .は直前に行った「一連」の操作を繰り返す。単なるRedoと違い、上で説明したci"のような塊を繰り返してくれる。カーソル移動などのモーションは繰り返されない。.はうまく使うと、操作をガンガン半自動化できるらしいので、今後の研究課題。
  • レコーディング機能を使うと一種のスニペットのように使える (もっと強力な使い方もあるらしい)。qに続けて打った文字に登録される(登録できるのは1文字なのでアルファベット26文字と数字といくつかの記号ぐらいしか使えない)。以後の操作は記録され、再度qを押すとレコーディング終了。再生するには、@に続けてそのキーを押す。とりあえず自分はRubyのshebangとGolangのテンプレートを登録してみた。

Level 6

何だかこの自虐的な記事が妙に多くの人にストックされてしまった。続きを別の記事にしようかと思ったけど、この記事に書き足すことにする。

  • Level 4で「行末へのジャンプ$が押しにくくてつらい」と書いた。しかし考えてみれば行末や行頭に行くときはどうせそこで何かを挿入するのだから、Aで「行末移動&インサートモード」、Iで「行頭移動&インサートモード」の方が圧倒的に押しやすく、しかも押すキーが1つ減る。これで$とおさらば。通常のエディタだと「そこに行ってから挿入」という2アクションになるのが、Vimだと1アクションになる。

  • そろそろビジュアルモードというものも使ってみよう。選択部分のインデントを揃える方法:

  1. ggVGで全選択する。ggは行頭移動、大文字のVは行選択、大文字のGで行末移動なので、これを一気に実行できる。なお、小文字のvggvGとすると、最終行が微妙に全選択されそこなう。
  2. =を押すとインデントが一気に揃う。以上。
  • 選択範囲をコメントアウトする方法:
  1. 開始地点でCtrl-vを押し、ビジュアルモードの矩形選択を始める
  2. jで下に降りてコメントアウトしたい範囲を選択する
  3. 大文字のIを押して行頭挿入を開始し、その言語に合ったコメントアウト文字(#とか)を挿入
  4. escを押すと、選択範囲に一気にコメントアウト文字が追加される。

これについてはSublimeやRubyMindの⌘+/の方が楽だと思う。コメントアウト文字を言語ごとに思い出さなくても済むので。

  • http://qiita.com/okuramasafumi/items/50c64825cf365e8f6e78 でいいコマンドを覚えた。大文字のS(slaughterと覚えた)を押すと、いきなり現在の行を全削除してインサートモードになる。今までは一行消してから書くためにddで削除してiでインサートモードになって改行を挿入してそれから1つ上に戻って...と相当無駄なことをしていた。

  • 同じく大文字のC(cutと覚えた)を押すと、現在の位置から右を全削除してインサートモードになる。大文字のDで右を全削除までは知ってたけど、インサートモードにまでなるので1ステップ節約できる。

  • 追伸: 小文字のsは、カーソル下を1文字だけ消してインサートモードになる。一見使い道なさそうだけど、スタブの#をURLに置き換えるときとかいいんですよね。こんな特等席のキーバインドをこれに与えるのはちょっともったいない気がしないでもないけど。

*保存して終了を大文字のZZで行なうと、:wqより通っぽいかも。

Level 7

魔神からまた教わる。

  • vimは実はzipファイルやgzipファイルを解凍せずにそのまま開ける。
  • dGとすると、カーソルのあるところから最下部までを一気に削除する。vGdより1つ少ない。
  • sはカーソル上の文字を削除してかつインサートモードになる。xを押してiを押すより早い。Level 6の大文字Sとペアで覚えるとよい。
  • 大文字のKを押すと、外部コマンドを呼んで検索してくれる。何も設定していなければmanコマンドが発行されるのでmanを引くことができる。カスタマイズしたければ、.vimrcにset keywordprg=コマンドという要領で書けばいい。manの代わりに英和辞書を指定したり好きな言語のリファレンスを指定したりなどできる。
  • g;と打つたびに、直前の変更箇所にジャンプする。戻るときはg,だそうだ。

Level 8

  • インサートモードで行頭に何か入力してctrl+xctrl-lと押すと、そのファイルの中にある行のうち入力とマッチした行がずらりと下に表示されて補完できる。つまり「行補完」。ちょうどExcelのセル入力時に上のセルの内容がドロップボックスに表示されるようなあれ。
  • インサートモードで何か入力してctrl+pを押すと、現在vimで開かれているすべてのファイルに出現した単語が補完候補として表示される。
  • ファイルパスを入力しかけてctrl-xctrl-fを押すと、現在の環境でのファイルパスを補完してくれる。/etcと打ってからこのキーを押せば/etc/passwdなどの候補が表示される。
  • とここまで書いておいて何だけど、neocomplete というプラグインを入れておくと入力するだけでどんどん補完候補が表示される(ファイルパス補完も行われる)。インストール方法はググればすぐ見つかる。

Level 9

そろそろ小学3年生ぐらいにはなっただろうか。

  • :r! コマンドとすると、その場でシェルのコマンドを実行して結果をそこに貼り付けられる。たとえば:r! lsとすればカレントディレクトリのファイルの一覧を貼り付けられる。これはシステム管理者的に非常にありがたい機能だと思う。
  • ctrl-xctrl-oはオムニ補完と言って、文脈に合った候補を表示してくれるのだそうだ。詳細と設定はググってください。
  • 魔神いわく、vimで一番重要な機能といってもよいスニペットはぜひとも導入すべきであると。これに比べればvimの他の機能などおまけのようなものだとまで言い切ってた。ということでneosnippet ( https://github.com/Shougo/neosnippet.vim )というものを導入しましょう。そして定型化可能な入力は片っ端からスニペットに登録して瞬時に呼び出せるようにしましょう。詳細と設定はググってください。
  • 書こうと思って忘れていたのを久しぶりに追加。gjgkと入力すると、改行のない長い段落の中を普通に1行ずつ上下移動できる。いつものjkだと、1行ずつではなく1段落の上下移動になってしまうので。なぜかこれをすぐ忘れてしまう。

Level 10

  • http://easyramble.com/join-lines-with-vim.html で紹介されている複数行を一気に結合する技がいい。ノーマルモードで大文字のJを打つと次の行との間の改行がスペースに置き換わって1行に結合される(英語向き)。さらにgJにすればスペースに置き換えずに結合される(日本語向き)。これを応用して5Jとすれば現在位置からの5行を一気に結合できる。そういえばこの数字を最初に指定して操作するのをあんまりやってこなかった。もっとやろう。
  • こちらの記事 http://qiita.com/jnchito/items/57ffda5712636a9a1e62 にもう少し応用系の技がある。
  • http://itchyny.hatenablog.com/entry/2014/12/25/090000 も読んどくと幸せになれそう。大文字系のDとかCとかYとか知らなかった。

Level 11 -- 横道にそれる

と、ここまで進んできて自分の中にジレンマが生じる。IDEやSublime Textも使っている自分は、Vim以外のところでも同じスニペットを使用したい。でもVimのスニペットはVimの外で使う仕様ではない。その一方、Gitコミットメッセージの書き込みなどはVimが一番安定しているのでVimもこのまま使い続けたい。

どうしよう。

すると、今までヘルプ検索にしか使ってなかったDash ( http://kapeli.com/dash )というドキュメント検索アプリのスニペット機能が実は優れものだったということに気付き、むしろこれを中心にエディタ環境を整備し直すことにする。

DashのスニペットはMacのどこからでも呼び出せる。誤動作を防ぐため;などの記号をスニペット名の頭に付けるのがよい。

以下を.vimrcに追記してvimからもK呼び出しができるようにした。Dash.vimを導入してもいいかもしれない。

" Dash integration for objc and nimrod.
command! DashNim silent !open -g dash://nimrod:"<cword>"
command! DashDef silent !open -g dash://"<cword>"
nmap K :DashDef<CR>\|:redraw!<CR>
au FileType nim  nmap K :DashNim<CR>\|:redraw!<CR>

そしてSublime TextもキーバインドをVim式に変更し、Dashdocをインストールしてctrl-hでDashを参照できるようにした。Vim小学校3年の自分からみて、Sublime TextのVimキーバインド再現率は8-9割ぐらいという感じ。

Sublime TextをVimキーバインドにしてみると、⌘-sなどの普通のMacのコマンドキーが使えてありがたい。保存のために:wとかいちいち打つよりやっぱり便利。⌘-/で言語にかかわらずコメントを付け外しできる機能とか待ってましたという感じ。VimではMacのコマンドキーがまったく前提にないのが不自由なのだけど、カスタマイズしてコマンドキーを使うようにしたところでキーバインドを考えるのも変えるのも面倒だし、環境が変わればズタボロになってしまうので、VimはVimで完結させておくことにした。

ということで、当面Sublime TextでVimモード+Dashでやってみます。何だかVim小学校からVim養護学級へ移籍した感があるけど。

追伸

この先のレベルがどこまであるのか知らないけど、Level 50 ぐらいはありそう。そこまでくると天下一Vim武闘会で優勝するクラス。

なお、魔神作のマークダウン編集用Vimプラグイン https://github.com/yaasita/ore_markdown が一部で異様に評判がいい。自分はまだインストールしてないけど。