bonar note

京都のエンジニア bonar の技術的なことや技術的でない日常のブログです。

vimで効率的にコードを書くための小技

vimは使いこなしている人は超人のように使いこなしているのですが、「たまにconfファイルいじる時だけ使うよ。まあ、普段はemacsだけどね」という人は、vi時代の機能のみ使っているのをたまに見かけます。

そこで、通ぶって恐縮なのですが、僕が普段vimを使っていてとっても便利で効率が上がると思う操作を紹介したいと思います。また、僕自身が Mac OS X な環境なので、「外部コマンドとの連携」などでWindowsだと再現できないものがあるかもしれません。ごめんなさい。

用語の使い方や理解が間違っている部分があるかもしれませんがその場合はご指摘いただければと思います。あと、「これ抜かしちゃ駄目でしょ!」みたいなのがあればアドバイスお願いします〜。

それでは、

[あとで読む]

vimの基本操作

(知っていると思うので省略)

超概略

挿入モードと編集モード

キー操作 内容
i 挿入モード突入(文字を書く時)
ESC 編集モード突入(カーソル移動の時)


 編集モードの操作

キー操作 内容
h
j
k
l
Ctrl+d 半画面下に移動
Ctrl+u 半画面上に移動
x カーソルの下にある文字を削除
yy カーソルのある行をYank
dd カーソルのある行をキリトリ
p 貼り付け
/$word $wordを検索(nで次の候補、Nで前の候補)
u アンドゥ
Ctrl+r リドゥ
:w $file $fileという名前で保存。指定しなければ上書き保存
:q 終了


等等。

コードを速く正確に書くために

  • 領域選択
  • 複数ウィンドウ
  • ファイルエクスプローラ
  • バッファ
  • レジスタ
  • マーク
  • 折りたたみ
  • 単語補完
  • 外部コマンドとの連携
  • 操作記憶(recording)

を使いこなそう。

領域選択

  v を押してから カーソル移動
  • 編集モードで v を押すと領域選択スタート
  • カーソルを移動するとその範囲が選択される
  • 選択後に y で yank (copy)、d で切り取り
  • 選択後に = で オートインデント(C言語規則)

追記

通常vで範囲選択をスタートさせるのですが、以下のような便利技もあります。

キー操作 内容
Ctrl + v 矩形選択スタート
Shift + v 行選択スタート

以下のようなカーソル移動コマンドと合わせると便利

キー操作 内容
$ 行末に移動
^ 行頭に移動
w 次の単語に移動
b 前の単語に移動
f(文字) 今カーソルがある行のその(文字)に移動
F(文字) 今カーソルがある行のその(文字)に移動(逆向き)
% 対応する括弧に移動

複数ウィンドウ


vimではひとつの画面で複数のファイルを同時に開くことが可能です。僕は大体画面を2つに割ってソースとテンプレートと見比べながら編集、みたいなことをよくやっているのですが、複数のファイルを見ながらの編集はかなり便利です。もちろん開いたwindow間で文字列のYank/Pasteが可能です。

キー操作 内容
:new $filename 新規window作成(垂直方向)
:vnew $filename 新規window作成(水平方向)
:e $filename 今いるwindowにファイルを開く
そのwindowで :q windowの削除
そのwindowで :hide windowを隠す(バッファには残る)
  • ファイル名を指定しないと空のバッファが作成されます
  • window分割後にさらに分割も可能

window間の移動

以下の操作で複数のWindowを言ったり来たりすることが可能です。
Ctrl+w を押した後に通常の移動キーですね。

キー操作 内容
Ctrl+w h
Ctrl+w j
Ctrl+w k
Ctrl+w l
Ctrl+w r 左右/上下のwindowを入れ替え

file explorer

vimでディレクトリを開くと file explorer になります。

  :e /path/to/some/directory/

複数のファイルを同時並行で編集したり参照したりする必要がある場合(よくありますよね)には、vimを一旦suspendして他の文書を開きなおすよりも、vnew等で横に file explorer を開いて目的にファイルを探すほうが速いです。一度開けば次からはバッファ番号でそのファイルを呼び出すことが可能です。

  " ============================================================================
  " Netrw Directory Listing                                        (netrw v98)
  "   /usr/local/apache2/conf/original/extra
  "   Sorted by      name
  "   Sort sequence: [\/]$,*,\.bak$,\.o$,\.h$,\.info$,\.swp$,\.obj$
  "   Quick Help: :help  -:go up dir  D:delete  R:rename  s:sort-by  x:exec
  " ============================================================================
  ../
  ./
  httpd-autoindex.conf
  httpd-dav.conf
  httpd-default.conf
  httpd-info.conf
  httpd-languages.conf
  httpd-manual.conf
  httpd-mpm.conf
  httpd-multilang-errordoc.conf
  httpd-ssl.conf
  httpd-userdir.conf
  httpd-vhosts.conf
  • 通常のvimの移動と同じ操作でファイルを選択できる(hjkl, Ctrl+d, Ctrl+u...)
  • ディレクトリの行でリターンを押すとそこへ移動
  • ファイル名の行でリターンを押すとそのファイルを編集

その他の操作:

キー操作 内容
- ひとつ上のディレクトリに移動
c 今いるディレクトリをカレントに指定
i 詳細情報を表示
s (詳細表示モードの時) カーソルがある行でソート

参考:

キー操作 内容
:cd $path カレントディレクトリを $path に設定
:pwd カレントディレクトリを表示

buffer(バッファ管理)

vimは一度開いたファイルは終了するまで覚えています。undo履歴やカーソルの位置までも!
一度開いたファイルをわざわざファイルのパスを指定しなくても、一覧に表示される番号を使用して出したり引っ込めたり自由にできます。

キー操作 内容
:ls バッファ一覧を表示

表示例)

  :ls
    3  a=  "/usr/local/apache2/conf/original/extra/httpd-info.conf" line 1
    4  a=  "/usr/local/apache2/conf/original/extra/httpd-userdir.conf" line 1
    5 %a=  "/usr/local/apache2/conf/original/extra/httpd-autoindex.conf" line 1


一番左がバッファ番号。バッファに対する操作は以下の通り。
#$buffnumはバッファ番号

キー操作 内容
:b $buffnum 今いるwindowに特定のバッファを呼び出す
:bd $buffnum そのバッファを削除
:bn 次のバッファに移動
:bp 前のバッファに移動

register(レジスタ管理)

レジスタは26種類の文字列が格納できるクリップボードのようなものです。文字列をyankしたり、特定の操作を文字列として保存したり。
レジスタ名は a 〜 z までの26文字のアルファベットが使用できます。

レジスタに文字列を保存する

キー操作 内容
"ay 選択範囲をレジスタ a に保存
"ayy 今いる行をレジスタ a に保存
"ap レジスタ a の内容をカーソル位置にペースト
:reg レジスタに格納されている情報を一覧表示

mark(マーク)

マークはカーソル位置を記憶する機能です。特定のカーソル位置を記憶しておりて、いつでもその場所にジャンプできます。長いソースを呼んでいて、いくつかの関数を行ったりきたりする際に超便利!
マーク名は a 〜 z までの26文字のアルファベットが使用できます。

キー操作 内容
ma 現在のカーソル位置をマーク名 a に保存
'a マーク名 a の位置に移動
:marks マークの一覧を表示する

folding(折りたたみ)

テキストの中の特定の領域を非表示にする(折りたたむ)機能です。ソースの先頭を見ながら特定の関数を編集したい、みたいなときに便利。

折りたたみ方:

    折りたたみたい範囲を領域選択してから zf

展開方法: 折りたたみ行でスペース

word completion(単語補完)

単語を途中まで入力すると、その後に続く文字列をvimがバッファの中からさがしてきて補完する機能。長い変数名や関数名等が一気に補完されるので、typoも減ってスピードも上がります。また、開いている全てのバッファを検索するので超便利!

入力モードで関数名等を途中まで書いて、

キー操作 内容
Ctrl+p 単語補完(前方検索)
Ctrl+n 単語補完(後方検索)

上記を複数回入力すると、次々と候補が表示されます。

外部コマンドとの連携

vimは編集中に外部コマンドを実行したり、その結果を取り込んだり出来ます。領域選択後に実行すると、選択範囲が外部コマンドの標準入力に入るので、自作のプログラムをvimのフィルタとして使用できます。perltidy等でソースを整形したり、外部のウェブサービスに内容をポストしたり、色々な用途が考えられそうです。そういった大掛かりなものでなくとも、例えばソース中のちょっとした計算を行ったり(bc)、tsv等のデータを特定の項目で並び替えたり(sort)といった局面でかなり威力を発揮します。

キー操作 内容
:!${command} 外部コマンドの実行(領域指定している場合は出力も取り込む)
:r!${command} 外部コマンドを実行してその出力をカーソル位置に挿入

こんな使い方が

    :r!date   現在の時刻を挿入
    :r!pwd    カレントディレクトリを挿入

例)特定のフィールドでソートする(Unix限定)

  drwxr-xr-x  2 root root  4096  4月  1  2006 .                
  drwxr-xr-x  3 root root  4096  4月  1  2006 ..                
  -rw-r--r--  1 root root  2835  4月  1  2006 httpd-autoindex.conf 
  -rw-r--r--  1 root root  1648  4月  1  2006 httpd-dav.conf   
  -rw-r--r--  1 root root  2344  4月  1  2006 httpd-default.conf 
  -rw-r--r--  1 root root  1103  4月  1  2006 httpd-info.conf              
  -rw-r--r--  1 root root  5040  4月  1  2006 httpd-languages.conf 
  -rw-r--r--  1 root root   800  4月  1  2006 httpd-manual.conf   
  -rw-r--r--  1 root root  3782  4月  1  2006 httpd-mpm.conf 
  -rw-r--r--  1 root root  2186  4月  1  2006 httpd-multilang-errordoc.conf 
  -rw-r--r--  1 root root 10253  4月  1  2006 httpd-ssl.conf 
  -rw-r--r--  1 root root   815  4月  1  2006 httpd-userdir.conf  
  -rw-r--r--  1 root root  1453  4月  1  2006 httpd-vhosts.conf 

上記を領域選択して、

  :!sort -n -k5

すると、

  -rw-r--r--  1 root root   800  4月  1  2006 httpd-manual.conf
  -rw-r--r--  1 root root   815  4月  1  2006 httpd-userdir.conf
  -rw-r--r--  1 root root  1103  4月  1  2006 httpd-info.conf
  -rw-r--r--  1 root root  1453  4月  1  2006 httpd-vhosts.conf
  -rw-r--r--  1 root root  1648  4月  1  2006 httpd-dav.conf
  -rw-r--r--  1 root root  2186  4月  1  2006 httpd-multilang-errordoc.conf
  -rw-r--r--  1 root root  2344  4月  1  2006 httpd-default.conf
  -rw-r--r--  1 root root  2835  4月  1  2006 httpd-autoindex.conf
  -rw-r--r--  1 root root  3782  4月  1  2006 httpd-mpm.conf
  drwxr-xr-x  2 root root  4096  4月  1  2006 .
  drwxr-xr-x  3 root root  4096  4月  1  2006 ..
  -rw-r--r--  1 root root  5040  4月  1  2006 httpd-languages.conf
  -rw-r--r--  1 root root 10253  4月  1  2006 httpd-ssl.conf

と綺麗にソートされます。

recording(操作記憶)

特定の操作を文字列として記憶し、再生する機能です。決まりきった作業は一度やればOKで、記憶した操作は文字列としてレジスタに記憶されます。操作の記録は文字列なので、ファイルに保存しておけば何度でも使えます。

テキスト処理では単純な反復作業が結構あると思います。で、それ用のスクリプトを書くほどでもないみたいな場面が結構あるのですが、そういったときにrecordingはかなり便利です。1行分の作業を記録しておいて、あとはその作業内容(操作の記録)を他の全ての行に対して実行すれば完了です。簡易マクロですね。

操作開始:

qa 操作の記録を開始し、レジスタ a に保存する

操作開始:

q 操作の記録を終了する

再生:

@a レジスタ a に保存された操作を再生する
5@a レジスタ a に保存された操作を5回再生する

※a の部分には任意のレジスタ名を入れる

行ごとの処理を行うときには、処理後にひとつ下の行に移るようにしておくと 10000@a の様に繰り返しで大量に処理できて便利。
単純な変換作業はスクリプトを書かなくてもこれでOK

まとめ

以上、いかがでしたでしょうか。知っている人には当たり前のことかもですが、この辺の操作を使いこなせるとかなり楽になる気がします。特に mark, recording はかなり便利ですね。mark,foldingはソースを読む時、recordingはHTML作成等の単純なテキスト処理を反復する場合等にかなり効率があがると思います。