Vimのコマンドラインモードでできること

こんにちわ

[ゴリラ.vim](https://gorillavim.connpass.com/)を運営しているゴリラです。

みなさんvimでコマンドをよく使っていますか？
ぼくは基本的にそんなにコマンドを使わないので、どんなことができるのかを調べてみました。
[日本語マニュアル](https://vim-jp.org/vimdoc-ja/cmdline.html)を見ればどんなことができるのか知れるので見ておくと勉強になると思います。

# コマンドラインモードとは？
vimでバッファをファイルに書き込むときによく`:w`を打つと思いますが、これが`:`でコマンドラインモードに移行し、続けてコマンドを入力して実行しているだけです。
コマンドラインモードで実行できるコマンドは`Exコマンド`です。

# よく使うExコマンド
一般的によく使用すると思われるExコマンドは次の表になります。
`:`はモード切り替えキーなので省いてあります。

| コマンド | 操作 |
|:---|:---|
| new | 新規バッファを作成する |
| tabnew | 新規タブを作成する |
| e | ファイルを編集する |
| r | 入力をバッファに挿入する |
| w  | 現在のバッファを開いているファイルに書き込む  |
| q  | vimを終了する  |
| wq  | バッファをファイルに書き込んでvimを終了する  |
| q! | vimを強制終了  |
| %s/置換対象文字/置換する文字/g  | 文字を置換する  |
| reg | レジスタ一覧を表示  |
| his | コマンド履歴を表示  |

すべてのExコマンドは[こちらのマニュアル](https://vim-jp.org/vimdoc-ja/vimindex.html#ex-cmd-index)を参照してください。

# コマンドラインモードでの編集
コマンドラインモードでは、単語ごとの移動、削除、履歴の呼び出しなどを行うことができます。
次の表の操作を覚えておくとよいでしょう。

| コマンド | 操作　 |
|:--|:--|
| <kbd>shift</kbd> + <kbd>→</kbd> | 次の単語に移動  |
| <kbd>shift</kbd> + <kbd>←</kbd> | 前の単語に移動  |
| <kbd>ctrl</kbd> + <kbd>w</kbd> |  １単語削除 |
| <kbd>ctrl</kbd> + <kbd>u</kbd>  |  カーソルより前の単語すべて削除 |
| <kbd>ctrl</kbd> + <kbd>e</kbd> | 最後尾に移動  |
| <kbd>ctrl</kbd> + <kbd>b</kbd>  | 先頭に移動  |
| <kbd>ctrl</kbd> + <kbd>p</kbd> もしくは <kbd>n</kdb> | 履歴の呼び出し  |
| <kbd>ctrl</kbd> + <kbd>f</kbd>  | コマンドラインウィンドウを開く  |
| <kbd>ctrl</kbd> + <kbd>r</kbd> + レジスタ(0-9a-z"%#:-=.) | レジスタの内容を挿入する  |

# コマンドラインウィンドウについて
コマンドラインウィンドウでは、コマンド履歴選択して<kbd>enter</kbd>で再実施したり、履歴を編集して再実施が可能です。
モードが適用され、<kbd>i</kbd>で入力モードに切り替えて編集でき、<kbd>ctrl</kbd> + <kbd>c</kbd>もしくは<kbd>esc</kbd>で入力モードを抜けることができます。

![cmdwindow.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/8acd5615-93e2-6df1-7fa4-954ab9a57de7.gif)

# 外部コマンド実行
よく知られていることですが、コマンドラインモードでは`!`を先頭につけることで、外部コマンド（lsコマンドなど）を実行することができます。
ちなみに、`r!ls`でコマンドの実行結果ををバッファに書き込むことができます。

![ls.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/781d70c9-78a2-4d47-84fd-4ec2404bcb7e.gif)

また、`w !xargs echo`でバッファを標準入力として外部コマンドにわたすことができます。

![wecho.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/932812e5-d56c-c03b-c27c-8ff5700ef6ff.gif)

# 置換について
普段、皆さんはファイル全体に対して、置換を行う時は`%s/{pattern}/{string}/g`を実行していると思います。
ぼくは完全に呪文として覚えていましたが、実はそれぞれの構文にはちゃんと意味があります。

| 単語 | 意味 |
|:-:|:-:|
| %  | 範囲指定コマンド、ファイル全体を指定する  |
| s/{pattern}/{string}  | sはsubstituteの略で行にある{pattern}を{string}に置換するコマンド。デフォルトは最初に出現した{pattern}を置換する  |
| g  | 行内で複数の{pattern}がある場合、すべて{string}に置換する  |

つまり、ファイル内のすべての行に出現する{pattern}を{string}に置換するという意味になります。
`g`はフラグと呼ばれていて、他にもいろんなフラグがあるようです。

# 範囲
置換の時に使用する`%`は範囲指定と先ほど説明しましたが、
他にも範囲指定する方法があります。

| コマンド | 範囲 |
|:-:|:-:|
| .  |  現在行を指定する |
| 10 | 10行目を指定する |
| $  | ファイル最終行を指定する  |
| 10,20  | 10行から20行を指定する |
| '<,'>  | 選択モード(visual)で選択した範囲 |

このように、範囲と置換を組み合わせることで、任意の範囲内の文字列を置換することができます。
例えば`'<,'>s/world/gorilla/g`は選択した範囲内にある`world`を`gorilla`に置換できます。

もちろん置換以外もコマンドも実行できます。

# 編集
コマンドラインモードでは置換以外にヤンク・コピー・削除・ペーストもできます。

| コマンド | 操作 |
|:-:|:-:|
| y  |  指定した行をレジスタにヤンク、指定がなければ基本的に無名レジスタに保存される |
| pu  | 指定した行にレジスタからペースト、指定がなければ基本的に無名レジスタからペーストされる  |
| d  | 指定した行を削除してレジスタに保存する、指定がなければ基本的に無名レジスタに保存される  |
| t  | 指定した行を指定した行の下にコピーする  |

コマンドと先程紹介した範囲指定を組み合わせることで次の様にコマンドラインモードでも任意の範囲を編集するできます。

![operate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/5cbea8e6-71b9-32ae-840f-513c4387970c.gif)

# ノーマルモードのコマンド実行
コマンドラインモードでノーマルモードのコマンドを実行できます。
`normal`のあとにスペースを開けて、コマンドを入力することでコマンドを実行できます。

次のgifでは`%normal v=`でファイル全体を整形しています。

![normal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/4e89a963-7d46-c7d0-e0a5-a028ec0b9abc.gif)

# 笑顔になれるコマンド
vimにはユーザが笑顔になれる`smile`コマンドが用意されています。
実行すると次の様になります。
ちなみに、ぼくは笑顔になれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/1529aa2e-a912-9c2e-66f8-da3c413cb8dc.png)

# まとめ
vimには実践的なコマンドから`smile`のようなユーモアのあるコマンドまで、たくさんあって面白いなと思いました。
TwitterのDMでもリプでも構わないので、他にこのコマンド便利だよというのがあればぜひ教えてください。

ではみなさん、よいvimライフを〜