2013/12/18

サーバ管理に役立つVim技10選

本記事は Vim Advent Calendar 2013 の18日目です。17日目は cocopon さんの オシャレ派Vimmerのあなたへ。こだわりのカラースキームギャラリーを贈ります。 | ここぽんのーと でした。

ここではサーバ管理作業などで知っていると捗るだろうなと思っている Vim の使い方を 10 個ほど紹介したいと思います。

1. EDITOR 環境変数

まずはじめは EDITOR 環境変数。いきなり vim の使い方ではありませんが、自分が普段使うエディタをシステムに宣言しておくことは非常に重要です(かなり)。

UNIX 系 OS ではファイルを編集する際に使用するプログラムとしてこの値を参照するアプリケーションがいくつかあります。

例えばバージョン管理システム。CVS や Subversion、Bazaar、Mercurial、Git など多くの VCS ではコミットメッセージを書く際のプログラムとして、それ用の環境変数よりも前に参照されますね。(CVSEDITORSVN_EDITORBZR_EDITORHGEDITORGIT_EDITOR

例えばページャ。morelesslv などのページャでファイルを閲覧していてふと編集したくなったときは v を押しますが、その時に EDITOR 環境変数のプログラムが使用されます。(ちなみにこの場合は VISUAL 環境変数が先に評価されます)

例えば crontab。何かのジョブを登録/変更しようとしたときに、分・時・日・月・曜日・コマンド、の各列がシンタックスハイライトされて打ち間違いによる実行ミスが減るかも知れません。

などなど Vim を常用する上では設定しておいてソンのない環境変数です。今すぐ設定しましょう。シンタックスハイライトされないような設定、あるいは tiny バージョンしか入っていない場合は、システム管理者の不幸を願いましょう。

え?Vim を使うのは黒い画面だからハイライトされると余計見づらい?そんなアナタには以下の記事が役に立つかも知れません。

余談ですが Vim から VCS を手軽に扱えるプラグインの紹介もしていますので興味のある方はどうぞ。

2. アクティブバッファのファイルパス省略記法(%)

ノーマルモードで : を入力することで移行するコマンドラインモードでは、文字 % がアクティブバッファのファイルパスとして使用できます。

これを利用して編集中のバッファを別名で保存したいときは :save %.yyyymmdd:!cp -p % %.yyyymmdd とか、:save %<TAB> としてファイルパスを展開してから少し変更するとか、いろいろできます。

この文字にファイル名修飾子を組み合わせるとさらに幅が広がります。

  • :p ファイル名の完全パス
  • :~ ファイル名のホームディレクトリからの相対的なパス
  • :. ファイル名のカレントディレクトリからの相対的なパス
  • :h ファイル名のディレクトリ名部分のパス(head)
  • :t ファイル名のファイル名部分のパス(tail)
  • :r ファイル名の最後の拡張子を除いたもの(root)
  • :e ファイル名の拡張子(存在する場合)(extension)
  • :s?pat?sub? ファイル名の最初に一致した pat を sub に置き換えたもの
  • :gs?pat?sub? ファイル名の pat に一致した全てを sub に置き換えたもの
例えば
% cd ~/.vim/bundle/vundle
% vim autoload/vundle.vim
としてファイルを開いたときは、
  • %:p は /Users/yoshikaw/.vim/bundle/vundle/autoload/vundle.vim
  • %:~ は ~/.vim/bundle/vundle/autoload/vundle.vim
  • %:. は autoload/vundle.vim
  • %:h は autoload
  • %:t は vundle.vim
  • %:r は autoload/vundle
  • %:e は vim
  • %:p:s?Users?home? は /home/yoshikaw/.vim/bundle/vundle/autoload/vundle.vim
  • %:~:gs?vundle?neobundle? は ~/.vim/bundle/neobundle/autoload/neobundle.vim
となります。(詳しくは :h filename-modifiers)

余談ですが :h:t などは C シェル(cshtcsh) や zsh では変数展開制御編集子として使いますので、その考え方は覚えていてソンのないものだと思います。

% echo ${SCREEN_EXCHANGE_KEY}
/Users/yoshikaw/screen/exchange.key

% echo ${SCREEN_EXCHANGE_KEY:h}
/Users/yoshikaw/screen

% echo ${SCREEN_EXCHANGE_KEY:t}
exchange.key

% echo ${SCREEN_EXCHANGE_KEY:r}
/Users/yoshikaw/screen/exchange

% echo ${SCREEN_EXCHANGE_KEY:e}
key

3. * による検索

ノーマルモードで * を押すと、カーソル位置にある単語で前方検索が行われます。n で次の単語、N で前の単語、というのは通常の / による検索と変わりません。単語を入力せずに検索できるのでとても楽できます。なお # だと後方検索になります。あわせて覚えておきたいです。

検索を終了したあとにも検索した単語(@/)がハイライトされていて目障り、と感じるときは :noh と素早くタイプして検索パターンのハイライトをオフにしましょう。オンにしたければ :hls です。(詳しくは :h hlsearch)

余談ですが @/ は変数の値としても参照できますので、それをこんな風に使う事もできます。

4. gf コマンドでファイルを開く

編集しているファイルに記述されている別のファイルを編集したい場合は結構あると思いますが、そのような時はそのファイルパスにカーソルを移動して gf で開くことができます。(Goto File)

例えば以下のようなファイルを編集している場合、/etc/init.d/functions のどこかにカーソルがあるときに gf とすればそのファイルが開けます。( . にカーソルがあるとディレクトリが開かれます)

# vim /etc/rc.d/init.d/crond
...
# Source function library.
. /etc/init.d/functions
. /etc/sysconfig/crond
...

プログラミング言語の include 文などで異なる場所にあるファイルを開きたい場合は、path オプションにそのディレクトリを指定しておくと検索対象となりますので、そこに見つかれば開けるようになります。

以下の例だと <linux/ktime.h> のどこかにカーソルがあるときに gf で ktime.h が開けます。

% vim /usr/share/systemtap/runtime/time.c
:se path+=/usr/src/kernels/2.6.18-371.3.1.el5-x86_64/include
...
#ifdef STAPCONF_KTIME_GET_REAL
#include <linux/ktime.h>
#endif
...

また拡張子が省略されている場合は suffixesadd オプションに拡張子を設定しておくと、それを補完したものが見つかれば開けるようになります。

以下の例だと @@spcuser のどこかにカーソルがあるときに gf で(同じディレクトリにある)spcuser.sql が開けます。

% vim $ORACLE_HOME/rdbms/admin/spcraete.sql
:se suffixesadd+=.sql
...
--
--  Create PERFSTAT user and required privileges
@@spcusr
...

5. netrw プラグインを使う

Vim には標準でファイルシステムを探索できる netrw プラグインが同梱されています。これを使う事で目的とするファイルを手軽に開けます。

プラグインであるため使うには以下の設定が必要です。デフォルトではだいたい使えるようになっていると思います。なっていない場合はシステム管理者の(以下略

set nocompatible
filetype plugin on

一番手軽な netrw の起動方法はファイル名にディレクトリを指定することです。何ができるかは Quick Help の説明で把握できると思います。この画面そのものもバッファなので vim の移動や検索コマンドが使えますので素早く目的としたファイルが選択できます。

" ============================================================================
" Netrw Directory Listing                                        (netrw v125)
"   /home/yoshikaw
"   Sorted by      name
"   Sort sequence: [\/]$,\.h$,\.c$,\.cpp$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by  x:exec
" ============================================================================
../
.mozilla/
.bash_history
.bash_logout
.bash_profile
.bashrc
.emacs
.lesshst
.viminfo
.zshrc

netrw のもう一つの便利な起動方法として Explore コマンドがあります。

  • :Explore :E カレントファイルのディレクトリを開く
  • :Hexplore :He 水平分割した右下のウィンドウで Explorer を実行
  • :Sexplore :Se 水平分割した左上のウィンドウで Explorer を実行
  • :Vexplore :Ve 垂直分割した左上のウィンドウで Explorer を実行
  • :Texplore :Te 新しくタブページを開いてそのウィンドウで Explorer を実行
それぞれコマンド末尾に !(bang) を付けると開くウィンドウの分割方向が変更できます。(詳しくは :h Explore)

さらに netrw は URI を指定してファイルを開くこともできます。これが地味に便利。手元のカリカリにチューンした Vim でネットワークの向こう側にあるファイルが編集できます。scp による編集はよく使います。

:e scp://[username@]hostname/path/to/file

6. 手早く diff

ファイルの変更点を確認するときは diff コマンドを使いますが、ある程度大きな変更になると見比べるのはなかなかしんどいです。そのようなときには vim の差分モードで編集を開始する vimdiff コマンドを使うと手慣れた vim で見比べることができます。

% vimdiff file1 file2 [file3 [file4]]

開いているバッファ(ファイル)に対しても diff 機能を使うことで差分の確認、取り込みなどの作業が楽にできます。詳しくは :h diff や Vim Advent Calendar 2012 に詳しい記事がありますので参照ください。

余談ですが単に変更前後の差分が色分けされていればいい、という使い方なら view コマンドとして vim をシンタックスハイライトツールとしても使えます。

% diff -u file1 file2 | view -
さらに余談ですがこの場合 zsh を使っているならグローバルエイリアスを定義しておく楽です。
alias -g V '| view -'
% svn diff V

7. ビジュアルモードを使う

Vim にはビジュアルモードというバッファ内のテキストを選択して操作を行えるモードがあります。これを有効に使う事でテキスト編集の効率が上がります。

ノーマルモードから次に挙げるキーを押すことで各種ビジュアルモードに切り替わります。
  • v 文字指向のビジュアルモードの開始・終了
  • V 行指向のビジュアルモードの開始・終了
  • Ctrl-V ブロック指向のビジュアルモードの開始・終了

文字指向のビジュアルモードでは、開始したカーソル位置の文字からカーソルを移動した位置までが選択状態になります。例えば d3w とした場合にどこまで削除されるか不安なときなど、v3w で対象範囲を確認(または微調整)してから d とすることで確実に操作できます。

行指向のビジュアルモードでは、開始したカーソル位置の行から選択範囲となります。そこから 10j /\.$ などの移動モーションで選択範囲を確認したあとに、d で切り取って別の場所に貼り付けたり、J で行を連結したり、> で右にシフトしたり等できます。

ブロック指向のビジュアルモードでは、開始したカーソル位置がいわゆる矩形選択の開始位置になります。矩形選択の説明は文章だけでは難しいので『実践Vim』から例をいくつか拝借します。

(p.75) 次のようなテキストがあり、テキスト列の区切りに | を使いたい場合を考えます。(説明の都合上、Chapter と Page の間にある | は操作開始のカーソル位置としています)

Chapter     |  Page
Normal mode      15
Insert mode      31
Visual mode      44
1 行目で区切りを入れたい位置にカーソルを移動します。Ctrl-V でブロック指向のビジュアルモードを開始して 3j で区切りを入れたい位置を確認して、r|<ESC> で選択範囲を | に変更します。

(p.77) 次のようなスタイルシートがあり、sprite.png の場所が image ディレクトリから components ディレクトリに移動になった時を考えます。

li.one   a { background-image: url('/image/sprite.png'); }
li.two   a { background-image: url('/image/sprite.png'); }
li.three a { background-image: url('/image/sprite.png'); }
1 行目の /image の i にカーソルを移動します。Ctrl-V でブロック指向のビジュアルモードを開始して、jje で 3 行目の image までを矩形選択して ccomponents<ESC> で components に変更します。

(p.78) 次のようなコードがあり、行末にセミコロンを追加したい場合を考えます。

var foo = 1
var bar = 'a'
var foobar = foo + bar
1 行目の 1 にカーソルを移動します。Ctrl-V でブロック指向のビジュアルモードを開始して、jj$ で 3 行目の bar までを矩形選択して A;<ESC> で行末に ; を追加します。

ここに挙げた例ではそれぞれ qar|jq3@a:%s!/image/!/components/!A;<ESC>j.j. などとマクロや置換、繰り返しを使っても実現できますが、視覚的に移動モーションによる対象範囲を確認しながらオペレータによる変更ができるという点でビジュアルモードは便利です。

余談ですがビジュアルモードで o を押すと現在のカーソル位置を選択範囲の開始点にしつつビジュアルモードを開始した位置にカーソルを移動できますが、GNU Screen のコピーモードにおける領域の選択でも同じような操作ができます。

8. コマンドラインウィンドウを使う

ノーマルモードから : で ex コマンドなどを入力できるコマンドラインモードに移行しますが、少し前に入力したコマンドの履歴を Ctrl-P などでひとつずつ遡るより Ctrl-F でコマンドラインウィンドウを開いてそこから選択したほうが早い場合があります。

コマンドラインウィンドウでは通常のバッファと同じようにカーソル移動や検索、編集などができ、その行で <Enter> を押すとそのカーソル行の ex コマンドが実行できます。履歴に保存される数は history で指定できますので、この値を大きくしておくとよく使う ex コマンドが再利用しやすくなって捗ります。

またコマンドラインウィンドウは ex コマンドの履歴だけではなく、検索履歴も表示することもできます。こちらもよく使う検索パターンを呼び出すときに便利です。

  • q: ex コマンド(:)の履歴をコマンドラインウィンドウに表示
  • q/ 検索コマンド(/)の履歴をコマンドラインウィンドウに表示
  • q? 検索コマンド(?)の履歴をコマンドラインウィンドウに表示
  • Ctrl-F コマンドラインモードからコマンドラインウィンドに切り替え
カレントウィンドウを閉じるコマンド :q と似ていますので意図せずコマンドラインウィンドウが呼び出されてイラッとすることが一度はあるかと思いますが、とても便利な機能ですので使いこなしたいものです。

9. ウィンドウを分割する

Vim ではバッファを表示している領域(ウィンドウ)を複数開くことができます。同じファイルの特定の箇所を別ウィンドウに表示しつつもう一方のウィンドウで編集する、別のファイルを表示しながら編集する、など一つの画面を複数のウィンドウに分割することで編集効率が上がります。

よく使うウィンドウの操作コマンドは次のようなものがあります。

ウィンドウの分割。

  • Ctrl-W s カレントウィンドウを水平分割する(:split)
  • Ctrl-W v カレントウィンドウを垂直分割する(:vsplit)
ウィンドウのクローズ。
  • Ctrl-W c カレントウィンドウを閉じる(:close)
  • Ctrl-W o 他のウィンドウを全て閉じてカレントウィンドウのみ表示する(:only)
ウィンドウ間のカーソル移動。2 つめのキーは最後を除いて Ctrl を押した場合でも同じ動きになります。
  • Ctrl-W h カーソルをカレントウィンドウの左のウィンドウに移動
  • Ctrl-W j カーソルをカレントウィンドウの下のウィンドウに移動
  • Ctrl-W k カーソルをカレントウィンドウの上のウィンドウに移動
  • Ctrl-W l カーソルをカレントウィンドウの右のウィンドウに移動
  • Ctrl-W t カーソルを一番左上のウィンドウに移動
  • Ctrl-W b カーソルを一番右下のウィンドウに移動
  • Ctrl-W w カーソルをカレントウィンドウの右あるいは下のウィンドウに移動。なければ左あるいは上のウィンドウに移動
  • Ctrl-W W カーソルをカレントウィンドウの左あるいは上のウィンドウに移動。なければ右あるいは下のウィンドウに移動
ウィンドウの分割サイズの変更
  • (n)Ctrl-W - カレントウィンドウの高さを n 行分低くする
  • (n)Ctrl-W + カレントウィンドウの高さを n 行分高くする
  • (n)Ctrl-W > カレントウィンドウの幅を n 桁分増やす
  • (n)Ctrl-W < カレントウィンドウの幅を n 桁分減らす
  • Ctrl-W = 全てのウィンドウのサイズを等しくなるように変更

ウィンドウの分割やカーソル移動などの操作がどのように機能するかは Think IT 連載にある図がとても分かりやすいです。

10. 自動補完

Vim の挿入・置換モードでは、既にバッファに入力されているキーワードなどを用いて入力を補完する機能があります。

補完候補とするソースごとに異なる呼び出し方がいくつも定義されていますが、どんなときでも気軽に呼び出せる次の 2 つを覚えておけばとりあえず事足りると思います。
  • Ctrl-N 入力途中の単語と同じ文字で始まるものを前方検索
  • Ctrl-P 入力途中の単語と同じ文字で始まるものを後方検索
コードを入力しているときの変数名などは同じバッファで既に入力している可能性が高いですので、数文字タイプしたあとに、バッファの前のほうに入力したことがあるなと思えば Ctrl-P 、後ろかなと思ったら Ctrl-N 、仮にそれが逆だったとしても続けて Ctrl-P または Ctrl-N を入力し続ければ次の候補が選ばれて入力されますので、楽できます。

おわりに

ここで紹介した技の多くは単に :h vim-additions のいくつかのさわりを紹介しただけに過ぎませんが、Vim によるファイルの読み書きがある程度できるようになった頃、こういうのを知っていたら良かったなぁという観点で並べてみました。こうして見るとあまりサーバ管理は関係ありませんね。後半は息切れして単に説明だけになっていますし。。。それでも何かひとつでも Vim 力向上のヒントになれば幸いです。

ところで『実践Vim』は Vim を使い慣れた方も、使い始めの方にもオススメできる書籍です。読んでいて途中途中で新たな発見がありました。

明日は @orga_chem さんです。楽しみですね。

0 件のコメント:

コメントを投稿