読者です 読者をやめる 読者になる 読者になる

Vimマニュアル(基本編)

前回の記事で、Vimを使う上で最低限必要だと思われる操作を紹介しました。しかし、Vimにはまだまだたくさんの機能があります。今回は、もう少し踏み込んだ内容について紹介していきたいと思います。
*1


設定ファイルについて

Vimの設定ファイルは、ホームディレクトリ *2.vimrc(Windowsでは_vimrc)という名前で置いておきます。このファイルの詳細は今回は説明しませんが、とりあえず以下の設定だけ書いておくといいと思います。"(ダブルクォーテーション)以降は行末までコメントになります。

set number                      "行番号を表示する
set backspace=indent,eol,start  "Backspaceキーで改行などを削除できるようにする
set autoindent                  "自動インデントを有効にする
set smartindent                 "C言語系などで使える高度な自動インデントを有効にする
set tabstop=4                   "タブ幅の設定(好みで調整してください)
set shiftwidth=4                "インデント幅の設定(タブ幅とは別の数値を指定できます)
set ignorecase                  "検索時の大文字小文字を無視する(無視しない場合は noignorecase としてください)
syntax enable                   "シンタックスハイライト(構文強調)を有効にする

Vimユーザの中には、設定に凝りすぎて、.vimrc が数千行に及ぶ人もいます。

特殊キーについて

Vimでのコマンドは、打ち込む文字列をそのまま表します(例えば、dwは D、W と順番に押します。.(ドット)や*(アスタリスク)などの記号も、そのまま見た目どおりに打ち込みます)。しかし、それだとEnterキーなどを表すことができません。Enterと指定されたら、Shift-E、N、T、E、R と順番に押すことを意味するからです。このため、EnterキーやCtrlキーによる修飾などの特殊なキーを表記する方法が存在します。特殊キーを表すには、<>で囲って表します。この表記では大文字小文字は区別しません

Vimでの特殊キーの表記(一部)

Vimでの表記 実際のキー
<CR> Enterキー(CR は Carriage Returnの略。<Enter>や<Return>でも可)
<Space> スペースキー
<ESC> Escキー
<C-x> Ctrlキーによる修飾(xは任意のキー。<C-Space>なども可)

Ctrl-Aは、<C-a>と表します。ShiftやAlt(Meta)も同様の方法で表しますが、あまり使われません *3
Ctrlキーによる修飾と<CR>はよく使われるので覚えておいてください
上に上げたものはほんの一部ですが、<>に囲まれた表記を見たら、特殊キーを表すんだなと考えれば良いと思います。
じゃあ<とか>ってコマンドは存在しないのか? と思われるかもしれませんが、実はちゃんと存在します。そして、これと区別するための方法もちゃんとありますが、話がややこしくなるので説明はしません。とりあえず < と > で囲まれているのを見たら、特殊キーだと思ってください。
以降、特殊キーを表すときには、上のような表記を使っていきます。

カウント指定について

多くのVimのコマンドは、直前に数字を入力することで、その回数のコマンドを一度に実行できます。これをカウントと言います。

VIM - Vi IMproved
↑ここにカーソルがあるとする。10lを押す
VIM - Vi IMproved
          ↑10文字分右に移動した。6hを押す
VIM - Vi IMproved
    ↑6文字左に移動。2dwを押す
VIM IMpproved
    2単語(- と Vi)が削除された

巨大な数値の指定もできます *49999kとすれば、9999行上に移動します。9999行もあるファイルは稀ですので、たいていは1行目に移動すると思います。

コマンド 動作
/文字列<CR> 文字列を前方検索(forward search:下方向に検索)
?文字列<CR> 文字列を後方検索(backward search:上方向に検索)
* カーソル下の単語 *5 を前方検索
# カーソル下の単語を後方検索
n 直前の検索を繰り返す
N 直前の検索を逆方向に繰り返す(直前の検索が後方検索なら前方検索を行う)

検索には、/(スラッシュ)を使います

hoge fugafuga
↑ここにカーソルがあるとする。/fuga<CR>を実行
hoge fugafuga
     ↑ここに移動

/のすぐあとに検索したい文字列を入力し、最後にEnterキーを押すと、その文字列が編集中のファイル内に見つかればそこへ移動します。見つからなければエラーが表示され、特に移動はしません。逆方向の検索には、/の代わりに?を使用します。検索を途中でやめるには、<Esc>を押します。
ノーマルモードのほか、ビジュアルモードでも使用できます(ノーマルモードで使えるコマンドは、ビジュアルモードでも使えることが多いです)。

検索する文字列をわざわざ入力するのがめんどくさい! と思うこともあると思います。Vimでは、カーソル下の単語を直接検索する方法があります。検索したい単語の上にカーソルを持ってきて、おもむろに*(アスタリスク)を押してください次にその単語がある場所に移動します。

hoge fuga hogehoge hoge
  ↑ここにカーソルがあるとする。*を押す
hoge fuga hogehoge hoge
                  ↑ここに移動する

後方検索をする場合は#を押します。
*が星に見えることから、super star と呼ばれているそうです。非常に便利なコマンドですので、使用する機会は多いです。
上の例でも示しましたが、*#は、例えば「live」で検索をして「alive」にヒットさせるということはできません。このような検索をしたい場合にはg*g#を使います。

検索の繰り返し

一度検索した文字列を再び検索したいケースも多いと思います。nを押すと、直前の検索を繰り返します。Nは逆方向に繰り返します。

hoge fuga hoge fuga hogehoge
↑最初はここ。「/hoge<CR>」を実行
hoge fuga hoge fuga hogehoge
         ↑ここに移動。n を押す
hoge fuga hoge fuga hogehoge
                   ↑ここに移動。さらにnを押す
hoge fuga hoge fuga hogehoge
                       ↑ここに移動。今度はNを押す
hoge fuga hoge fuga hogehoge
                   ↑ここに移動

nを押すだけでポンポンとテンポ良く検索できます。同じ単語がたくさん出現するときや、.で同じ操作を繰り返したいときなどに特に威力を発揮します。
?#などによる方検索のあとにnを押すと方検索、Nを押すと方検索をします。混乱しやすいので注意してください。

移動コマンドあれこれ

前回は hjkl による1文字移動のみを紹介しましたが、Vimには、さらに別の単位での移動コマンドが豊富に用意されています。hjkl で1文字ずつちまちま移動するよりも、こういったコマンドで大きく移動して、目的の場所の近くまで来たら hjkl を使うという方法を使った方が、効率は上がると思います(と言いつつ、私はついつい hjkl の連打で移動してしまいますが)

単語移動

コマンド 動作
w 次の「単語の先頭」に移動
b 前の「単語の先頭」に移動
e 次の「単語の末尾」に移動
ge 前の「単語の末尾」に移動
実際の動作
     b         w
very important message
  gee
     現在位置

ややこしいように見えますが、慣れの問題です(わかりにくくてすみません。実際、慣れればさくさく移動できます)。
wbegeは対になっていて、それぞれ逆の動きをします。また、単語の先頭にいる場合のbは、前の単語の先頭に移動します。同様に単語の末尾にいる場合のeは、次の単語の末尾に移動します。

単語の先頭にいる場合
b←            w
very important message
  ge         e
単語の末尾にいる場合
     b         w
very important message
  ge               →e

行頭/行末へ移動

コマンド 動作
$ 行末へ移動
^ 空白文字以外の最初の文字へ移動
0 *6 空白文字も含めた最初の文字へ移動
0   ^               $
    int func(int n) {

行の最初や最後に移動するためのコマンドです。
^では、インデントなどの空白がある場合に1列目に移動できません。常に1列目に移動するには0を使います
^$は、正規表現でそれぞれ行頭、行末を表すことにちなんでいます

画面スクロール

コマンド 動作
<C-e> 1行下にスクロール
<C-y> 1行上にスクロール
<C-d> 半ページ下にスクロール
<C-u> 半ページ上にスクロール
<C-f> 1ページ下にスクロール
<C-b> 1ページ上にスクロール

画面をスクロールさせるコマンドです(カーソルの移動ではありません)。大きなファイルを編集中に、すばやく目的の場所に移動できます。
d と u は down/up、f と b は forward/backward を意味するので、コマンドを覚えるときの参考にしてください。

特定の行へ移動

コマンド 動作
gg 1行目へ移動
G 最終行へ移動
数字G 指定した行へ移動
<C-o> 行移動や検索で移動した後、移動する前の行へ戻る
<C-i> または <Tab> <C-o>で戻った行から元の行へ進む

行移動です。移動したい場所が何行目かわかっているときに、一瞬で移動できます。
<C-o><C-i>は、ブラウザの「戻る」/「進む」みたいなものだと思ってください。検索や行移動といった大きな移動 *7 をした時に、戻ったり進んだりできます。

編集コマンドあれこれ

テキストをノーマルモードで編集するコマンドには、前回紹介したdから始まるものや、yから始まるもののほかに、cから始まる、対象範囲のテキストを削除してから、即座に挿入モードに入るコマンドが存在します。

コマンド 動作
dw 1単語を削除する
cw 1単語を削除してから挿入モードに入る
yw 1単語をヤンクする
dd 1行削除する
cc 1行削除してから挿入モードに入る
yy 1行ヤンクする
D カーソル位置から行末まで削除する
C カーソル位置から行末まで削除してから挿入モードに入る
Y 1行ヤンクする(yy と同じ *8

dwなどと一緒に表にしてみました。
cwccは、dwddののちにiを押して挿入モードに入るのとほぼ同じです。
大文字のDCは、(1行全体ではなく)カーソル位置から行末までの範囲に対して削除などを行います。Yyyと同じく行全体をヤンクしますYDCと揃っていない理由は不明です。オリジナルである vi との互換を保つためだそうですが、じゃあなぜ vi で行全体をヤンクするのかって話です。誰か教えてください。

操作+移動

dcyから始まる各コマンド、よく似ていることに気づくと思います。d を y と変えても、削除がヤンクに変わるのみで、対象となるテキストの範囲は同じです。
これらのコマンドは、2つの部分から構成されています。前半の d や y は、行う操作の種類を表し、後半部分は操作を適用するテキストの範囲を表します *9
dcyのようなコマンドをオペレータといい、これらを入力するとオペレータ待機モードというちょっと特殊なモードに入ります *10。このモード中に移動コマンドを押すと、本来カーソルが移動するはずの範囲のテキストに対して、コマンドが実行されるのです。例えば、c$を実行すると、現在のカーソル位置から行末($)までのテキストを削除したうえで、挿入モードに入ります(大文字のCと同じです)。

移動としての検索

/*などによる検索コマンドは、実はカーソル移動コマンドに相当します。そのため、オペレータに続けて検索コマンドを実行することで、文字列が見つかるまでの範囲のテキストを対象とした処理をすることができます。
行移動なども同じように使えます。ただし、画面スクロールはカーソル移動ではないため、このような処理には使えません。

その他の編集コマンド

そのほか、以下のようなコマンドもあります。

コマンド 動作
s 1文字削除してから挿入モードに入る
S 1行削除してから挿入モードに入る(cc と同じ)
r文字 カーソル位置にある1文字を、r の後に入力した文字で置き換える
R 置換モードに移行
x カーソル位置の単語を削除(入門編から再掲)
X カーソル前の単語を削除

sは、カーソル上の1文字を削除したあと、即座に挿入モードに入りますcから始まるコマンドとよく似ています。
rは、rの次に押した1文字で、カーソル位置にある1文字を置き換えるコマンドです。sは挿入モードに入るのに対し、rは文字を置き換えたあとはノーマルモードを維持します。
Rは、置換モードに移行します。置換モードとは、ほかのエディタによくある Insert キーを押したときの状態と同じように、カーソル上の文字列を書き換えるモードです。ノーマルモードに戻るには<Esc>を押します。私はほとんど使ったことがありませんが、人によっては使うかもしれないので挙げておきました。

キーボードマクロ

同じ作業を何度も繰り返すのは面倒ですよね。入門編で紹介した.も便利ですが、.で繰り返せるのは直前の操作ひとつだけです。複数の操作を繰り返し行いたい時のために、Vim にもキーボードマクロが用意されています。

コマンド 動作
q英数字 キーボードマクロの記録を開始する。指定した英数字に記録(英大文字の場合は追記)される
(上のマクロ記録実行中に)q キーボードマクロの記録を終了する
@英数字 指定した英数字に記録されているマクロを実行する
@@ 直前に @ で実行したマクロを繰り返す

qの後に英数字1文字を押すと、キーボードマクロの記録が開始されます。
マクロを保存する場所は、指定した1文字の名前がついたレジスタです。レジスタとは、入門編でもちらっと触れましたが、文字列を保存できる、Vim 専用のクリップボードのようなもので、本来は編集操作に使用しますが、マクロではこれを流用しています。名前が指定できる(と言っても1文字ですが)ことからわかるように、複数のレジスタが用意されています。
指定するレジスタ名は、基本的には a-z の小文字にしてください。記録を開始したら、普段と同じように編集をします。そして、記録を終了するためには、もう一度qを押します

qa/hoge<CR>dwq
    レジスタ a に コマンド(「hoge」を検索して削除する)を記録

記録したキーボードマクロを実行するには、@に続けて記録したレジスタ名を指定します。また、@@を押すと、直前に実行したマクロを繰り返すことができます。これらのコマンドにも、カウントを指定することが可能です。
キーボードマクロに記録されるコマンドは、qが押されるまで実行されたコマンド全てです。移動、挿入モードでの入力、繰り返しなども含まれます

文字列としての Vim のコマンド

Vim のコマンドの流れは文字列として表すことができるため、実際にレジスタに記録されるのはqqの間に入力された文字列です *11。文字列として表すことが可能ということは、逆に文字列をコマンドとして解釈して実行することもできるということなので、キーボードマクロの実行とは、ただ単にレジスタに書き込まれた文字列としてのコマンドを実行するだけです *12。Vim のマクロはこのような仕組みで働いています。

ihoge<Esc>cgepiyo<Esc>
    挿入モードに入り(i)、「hoge」 と入力し、ノーマルモードに戻り(<Esc>)、
    「hoge」を削除して挿入モードに入り(cge)、「piyo」と入力しノーマルモードに戻る(<Esc>)

*13

まとめ

基本編は以上になります。
基本編といいつつ、あまりまとまりがなかったり、けっこう難しいところまで解説してしまった気がします(オペレータとか)。基本編じゃなくて踏込編とでもした方が良かったかもしれません。おかげで、かなり長くなってしまいました。すみません。
もしここまで読んでくれたなら、感謝です。お疲れ様です。

入門編で紹介したコマンドと合わせれば、かなり効率よくテキストの編集ができるようになるのではないでしょうか。

まだまだ書いていくつもりなので、次回以降もよろしくお願いします。

*1:今回紹介するコマンドは、すべてノーマルモードでのコマンドです

*2:Windowsでは、C:\Users\ 以下の各ユーザ毎のフォルダ

*3:Shift-Aの場合、「<S-a>」と表記するのではなく、「A」とすることが多いです

*4:内部的にはC言語のint型を使っているようなので、intの最大値を超える値は指定できません。また、-(ハイフン)はコマンドの一種なので、負の数の指定もできません

*5:Vimでいう単語(word)とは、識別子なら識別子、記号なら記号のひとかたまりを指す。識別子の定義はプログラミング言語によって異なるため、オプションで設定できるようになっている。デフォルトは英数字と _(アンダーバー)

*6:数字の 0 。数字だが、カウントではなくコマンド。0 以外の数字に続けて 0 を押すと、カウントとみなされる

*7:複数ファイルをまたいだ移動も含みます。複数ファイルの扱いについては、今回は解説しません

*8:何故か D や C と揃っておらず、行末までヤンクではないことに注意

*9:表に挙げたコマンドは例外の方が多いですが(汗

*10:見た目の上ではノーマルモードとほとんど変化はありません

*11:<CR> や Ctrlキーに修飾された文字などの特殊キーは、制御コードが記録されます(Vim でこれをコマンドではなく制御コードとして入力するには、挿入モードで <C-v> に続けて入力したいキーを押します)。<> による表記は、特殊キーではなく、<> も含めた一連のコマンドとして解釈されます

*12:レジスタに意図的にコマンド文字列を書き込んで実行することも可能です。詳細は例によって割愛します

*13:<Esc> は、上の脚注にもある通り、^[ という制御コードが記録されます。ここでは、わかりやすさを優先して <Esc> としました