コマンドラインモードについて学ぼう 〜 Vimはいいぞ!ゴリラと学ぶVim講座(4)
前回の記事では挿入モードとビジュアルモードをみなさんに解説しました。今回は筆者が好きなコマンドラインモードについて、便利な機能を解説していきます。特に外部コマンド連携はとても便利なので、ぜひ最後まで読んでみてください。
コマンドラインモード
初回の記事ではVimでファイルを保存したりするのにコマンドラインモードで:wといったコマンドを実行すると解説しました。コマンドラインモードで実行できるコマンドはExコマンドと呼ばれています。Exコマンドは単にファイルを保存したり、Vimを終了したりするだけでなく、他にも新しいウィンドウを作成したり、ヤンクやプットなどを行うことができます。
ウィンドウについて
Vimを使用していると複数のファイルを同時に開いて差分を確認したり、編集したりしたくなる場合があります。Vimは標準で画面(以降ウィンドウと呼ぶ)を分割する機能を持っています。水平や垂直に分割したり、ウィンドウサイズを調整したりすることができます。筆者がよく使用するコマンドを解説していきます。
ウィンドウの作成
ウィンドウの作成方法は、主に次のようになります。
| コマンド | 説明 |
|---|---|
| :new {file} | ウィンドウを水平分割して開く。ファイルが指定されていない場合は空のウィンドウを開く |
| :vnew {file} | ウィンドウを垂直分割して開く。ファイルが指定されていない場合は空のウィンドウを開く |
| :sp {file} | ウィンドウを水平分割して開く。ファイルが指定されていない場合は現在のファイルを開く |
| :vs {file} | ウィンドウを垂直分割して開く。ファイルが指定されていない場合は現在のファイルを開く |
次の動画は:newと:vnewの一例になります。(ウィンドウを分割し、doc/docker.txtを開いています)

次の動画は:spと:vsの一例になります。(ウィンドウを分割し、現在開いているREADME.mdを表示しています)

:sp、:vsは大きな(例えば1000行以上)ソースファイルの先頭にある処理を確認しつつ、新しい関数を実装するときに使用すると便利です。一つのファイルでカーソルを都度移動させなくて良いので効率がよいです。:new、:vnewはちょっとしたメモを書く時や、新しいファイルを作るとき(:w {file}でファイルに保存)に使用すると便利です。
ちなみに、:vsや:new、後述するtabnewではファイルを新しいウィンドウで開くのに、いくつか便利なオプションがあります。それが次になります。
| オプション | 説明 |
|---|---|
| + | 最後の行にカーソルが移動した状態でウィンドウを開く |
| +{num} | {num}行にカーソルを移動した状態でウィンドウを開く |
| +/{pattern} | {pattern}とマッチした最初の行に移動した状態でウィンドウを開く ({pattern}は正規表現) |
次の動画は+/{pattern}を使用して、Dockerfileの”RUN"がある最初の行に移動した状態でウィンドウを開く例になります。

ウィンドウ間の移動
ウィンドウ間の移動は:wincmdを使用することもできますが、標準のキーマップ(ショートカット)を使用すると便利です。主なキーマップは次になります。
| キーマップ | Exコマンド | 説明 |
|---|---|---|
| [N] CTRL-w j | :wincmd j | [N}個下のウィンドウに移動 |
| [N] CTRL-w k | :wincmd k | [N}個上のウィンドウに移動 |
| [N] CTRL-w h | :wincmd h | [N}個左のウィンドウに移動 |
| [N] CTRL-w l | :wincmd l | [N}個右のウィンドウに移動 |
| CTRL-w t | - | 一番上のウィンドウに移動 |
| CTRL-w b | - | 一番下のウィンドウに移動 |
次の動画はウィンドウ間の移動の例になります。

ウィンドウサイズ調整
複数のウィンドウを使用していると、ウィンドウサイズを調整したくなるときがあります。例えば、数行しかないシェルスクリプトを画面半分も使用してしまうのはとてももったいないので小さくした方が効率が良いです。そういったサイズ調整のキーマップが標準で用意されています。主なキーマップは次になります。
| キーマップ | 説明 |
|---|---|
| [N] CTRL-w + | 現在のウィンドウの高さを [N] 行分高くする(デフォルトは1) |
| [N] CTRL-w - | 現在のウィンドウの高さを [N] 行分低くする(デフォルトは1) |
| [N] CTRL-w < | 現在のウィンドウの幅を [N] 桁分減らす(デフォルトは1) |
| [N] CTRL-w > | 現在のウィンドウの幅を [N] 行分増やす(デフォルトは1) |
| CTRL-w = | すべてのウィンドウのサイズの幅と高さをほぼ同じにする |
次の動画はウィンドウサイズの調整の一例になります。

ウィンドウを閉じる
開いたウィンドウを閉じる主な方法は次になります。
| キーマップ | Exコマンド | 説明 |
|---|---|---|
| CTRL-W q | :q | 現在のウィンドウを閉じる(最後のウィンドウの場合はVimを終了する) |
| CTRL-W o | :only | 現在のウィンドウ以外のウィンドウを閉じる |
| CTRL-W c | :close | 現在のウィンドウを閉じる(最後のウィンドウの場合は閉じることができない) |
次の動画はウィンドウを閉じる操作の一例になります。筆者の場合はキーマップよりもExコマンドのが慣れているのでそちらを使用しています。

タブページ
タブページは複数のウィンドウをまとめたものになります。1ファイルを全画面で編集したいときは分割ではなくタブを使用すると良いでしょう。新しいタブページを開くには:tabnew {file}を使用します。ウィンドウの作成の項目で説明した通り:tabnewも+ や+/{pattern}オプションも使用することができます。
次の動画は:tabnewとオプションを使った例になります。

タブページ間の移動は主に次になります。
| キーマップ | 説明 |
|---|---|
| [N]gt | [N] 個目のタブページに移動、[N] を指定しない場合は次のタブページに移動 |
| gT | 一個前のタブページに移動 |
次の動画はタブページ間の移動操作の一例になります。

ヤンク
コマンドラインモードでは:yでテキストをヤンクできます。主な使い方は次になります。
| Exコマンド | 説明 |
|---|---|
| :5y | 5行目をヤンク |
| :4,10y | 4~10行をヤンク |
| :%y | 全体をヤンク(%は全体を意味する) |
| :y | 現在行をヤンク |
4,10や%は範囲を意味します。続けてyを入力してEnterを押下して実行することでその範囲をヤンクするという動きになっています。全体ヤンクはノーマルモードでggyGで同じ様なことができますが、その場合カーソルが移動してしまうので筆者は:%yを使用しています。
コマンドラインモードでのヤンクのメリットは、カーソルを動かさずに離れた場所のテキストをヤンクできるところです。みなさんもぜひ使ってみてください。
次の動画はヤンクの一例になります。(:179yで179行目をヤンク → pでプット → :180,182yで180-182行目をヤンク → pでプット → %yで全体をヤンク → :tabnewで新しいタブを作成 → pでプット)

プット
コマンドラインモードではヤンクだけでなく、プットもできます。主な使い方は次になります。
| Exコマンド | 説明 |
|---|---|
| :pu | 現在行の後にプット(ノーマルモードのpと同様) |
| :pu! | 現在行にプット(ノーマルモードのPと同様) |
| :3pu | 3行目の後にプット |
| :3pu! | 3行目にプット |
プットもヤンクと同じ様な使い方になります。現在のカーソルから離れた場所にテキストをプットできるのがメリットです。次の動画は上記操作の一例になります。

コピー
コピーは:yと:puをまとめて実行するときと同じ様な動きになります。主な使い方は次になります。
| Exコマンド | 説明 |
|---|---|
| :10co. | 10行目を現在行の後にコピー(.は現在行を意味する) |
| :1,5co- | 1~4行目を現在行にコピー(-は-1行を意味する、現在行より1行前の場合は-2) |
| :co10 | 現在行を10行目の後にコピー |
離れた場所にあるテキストをヤンクして指定した場所にプットする、といった一連の操作をまとめて行うときに便利です。ちなみに、coのエイリアスでtというのがあります。こちらでも全く同じ動きになります。筆者はめんどくさがりなので1文字のtを普段から使用しています。
次の動画はコピーの一例になります。

削除
ヤンク、プット以外に削除もできます。基本的にヤンク、プットと同じ様な使い方になります。
| Exコマンド | 説明 |
|---|---|
| :d | 現在行を削除(ノーマルモードのdと同様) |
| :10,15d | 10~15行目を削除 |
| :%d | 全体を削除(%は全体を意味する) |
次の動画は削除の一例になります。

文字列の置換
初回の連載では置換について軽く解説しましたが、ここではもう少し詳しく解説していきます。Vimで文字を置換したい場合は:%s/{pattern}/{string}/gというように実行しますが、%やgにはそれぞれ意味があります。
%は本記事で数回出てきたのでもう分かるかと思いますが、これはファイル全体を指しています。つまり範囲選択ということです。つまり置換する対象範囲が全体だよ、ということを意味します。sはsubstituteの略で日本語に訳すと置換という意味になります。gはフラグと呼ばれるもので、これをつけると{pattern}にマッチした行内すべての要素を{string}に置換します。行内に{pattern}にマッチした要素が複数個ある場合、gがないと1個目の要素のみが置換されます。全体を置換したい場合はgをつける必要があります。
この様にフラグは置換の細かい動作を調整する役割を担っています。他にもいくつかフラグがありますので、興味ある方は:h :s_flagsでヘルプを読んでみてください。(ヘルプについては後述します)
次の動画は文字列の置換の%とgがある・ないの場合の例になります。(この動画ではプラグインを用いて、置換される場所がリアルタイムでわかるようにしています)

ヘルプを引く
Vimの良さの一つはヘルプが充実しているところです。ヘルプにはVimのほぼ全てのことが書かれていますので、ヘルプを読めばVimがどんなことができるのかを知ることができます。ヘルプを引くには:h {sub}を実行します。例えば、挿入モードでCTRL-Wの動きについて詳細を知りたいときは:h i_ctrl-wでヘルプを開くことができます。
ヘルプを引くのは少しコツが要りますが、モードごとにヘルプを引けるように次のルールがあるので、このルールを参考にしてぜひご自身で色々ヘルプを引いてみてください。
| モード種類 | 装飾子 | 例 |
|---|---|---|
| ノーマルモード | なし | :h iw |
| 挿入モード | i_ | :h i_ctrl-w |
| ビジュアルモード | v_ | :h v_c |
| コマンドラインモード | c_ | :h c_ctrl-w |
| Terminal-Jobモード | t_ | :h t_ctrl-w_n |
| Exコマンド | : | :h :w |
:hの詳細については:h helpでヘルプを参照してください。
外部コマンド連携
Vimは外部コマンドとの連携が得意なエディタです。ここで指している外部コマンドとはlsやechoといったシェルコマンドになります。外部コマンドを実行して、その結果をVim上で編集することもできます。こういった外部コマンドとの連携はとても便利です。
コマンドラインモードで外部コマンドを実行するには:!{cmd}というように、!の後にコマンドを入力して、Enterを押下することでコマンドを実行できます。
次の動画では外部コマンドを実行する一例になります。

単にコマンドを実行できるだけではなく、例えば、APIのレスポンス(JSON)をVim上で編集したい、もしくはテストデータの一部として使用したい場合は:rコマンドを使用します。
次の動画はcurlを使用してDocker Engineからイメージ一覧のAPIを叩く例になります。

:rはコマンドの標準出力結果もしくはファイルの中身を現在開いているファイルに追加することができます。この様にコマンドの実行結果を読み込んで編集することができます。とても便利です。
しかし、上記の例ではJSONが一行でとても見づらいです。そこで、%!{cmd}で外部コマンドを使用して中身を整形して見やくします。%!でファイルの全中身を{cmd}の標準入力に渡し、出力結果を反映することができます。%はこれまで説明した通りファイル全体を意味します。%以外にも.も使用することができ、これは現在行をコマンドの標準入力に渡します。:!{cmd}と違い、範囲指定をするとこの様な動きになります。
次の動画ではjqコマンドを使用してJSONを整形する例になります。

このようにVimは外部コマンドと連携して、より高度な編集を行うことができます。ぜひ手元にあるVimで試してみてください。
笑顔コマンド
ここでは説明しませんが、ぜひ手元にあるVimで:smileを実行してみてください。
最後に
コマンドラインモードについて筆者が便利と考えている機能を一通り解説しました。いかがだったでしょうか?どれも筆者が普段から作業で使用しているものばかりです。本記事を読んで少しでもみなさんのVimライフの役に立てればと思います。
次回の記事はVimのTerminal-JobモードとTerminal-Normalモードについて解説します。楽しみにして頂ければと思います。