Vimを学びたい時に見る記事

## はじめに
本記事は、vimの基本的なコマンドを学ぶための問題集です。
実際に手を動かしながら進められるようテキストを用意してありますので、お手元にご用意してから読み進めてください。

## 準備
[こちら](https://github.com/yu-saito-ceres/vim_practice) からテキストをcloneしてください。

## 問題


### Level1 基本操作

#### Q1 Vimでテキストを開いてください。
<details><summary>答え</summary>
vim vim_practice.txt
</details>

#### Q2 案内の通りにカーソルを移動してください。
（条件）矢印キーは使用不可。
<details><summary>答え</summary>
h,j,k,lで移動
</details>

#### Q3 インサートモードに入ってください。
<details><summary>答え</summary>
ノーマルモード時 'i' キー
</details>

#### Q4 ノーマルモードに入ってください。
<details><summary>答え</summary>
'esc' キー
</details>

#### Q5 ビジュアルモードに入ってください。
<details><summary>答え</summary>
ノーマルモード時 'v' キー
</details>

#### Q6 コマンドモードに入ってください。
<details><summary>答え</summary>
ノーマルモード時 ':' キー
</details>

#### Q7 いらない単語を削除してください。
（条件）ノーマルモードの状態のまま削除。
<details><summary>答え</summary>
ノーマルモード時 'x' キー
</details>

#### Q8 間違っている文字を修正してください。
（条件）ノーマルモードの状態で上書きをする。
<details><summary>答え</summary>
'r'キーで上書きモードに変更後、正しい文字を入力する。
</details>

#### Q9 いらない行を削除してください。
（条件）ノーマルモードの状態で削除
<details><summary>答え</summary>
'dd'キーで現在の行を削除
</details>

#### Q10 undo（変更を1つ戻す）をしてください。
（条件）Ctrl + Z は使用不可
<details><summary>答え</summary>
'u'キーでundo
</details>


#### 基本コマンド一覧
| コマンド | 概要 |
|---------|---------|
| j  | 下に移動   |
| k   | 上に移動  |
| h   | 左に移動   |
| l   | 右に移動   |
| i   | インサートモードに移行   |
| v   | ビジュアルモードに移行   |
| esc   | ノーマルモードへ移行   |
| : | コマンドモードへ   |
| r   | 上書き（）   |
| x   | 後ろの文字を削除   |
| u   | undo   |
|Ctrl + r|redo|


:::note
Vimには大きく4つのモードが存在します。
:::
##### ノーマルモード
`esc`キー押下で遷移
移動やファイル操作のコマンドを実行する
##### インサートモード
ノーマルモード時 `i` キーを押下
主には文字入力を行う
##### ビジュアルモード
ノーマルモード時 `v` キーを押下
文字・行単位などでの選択を行う
##### コマンドモード
ノーマルモード時 `:`キーを押下 
ファイルの保存などのコマンドを実行する



### Level2 カーソル移動

#### Q11 次の単語の先頭に移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'w'キーで移動
</details>


#### Q12 次の単語の先頭に移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'e'キーで移動
</details>

#### Q13 前の単語の先頭に移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'b'キーで移動
</details>

#### Q14 前の単語の末尾に移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'ge'コマンドで移動
</details>


#### Q15 指定の行まで移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'[数字]G'コマンドで移動
</details>


#### Q16 ファイルの先頭まで移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'gg'コマンドで移動
</details>

#### Q17 ファイルの末尾まで移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'G'コマンドで移動
</details>

※ `105G`コマンドで次の問題に移動できます。

#### Q18 行の先頭まで移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'0' or '^' キーで移動<br>
もしくは'shift + i' で先頭まで移動してインサートできます。
</details>

#### Q19 行の末尾まで移動してください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'$' キーで移動<br>
もしくは'shift + a' で末尾まで移動してインサートできます。
</details>

#### Q20 行番号を表示してください。
<details><summary>答え</summary>
':set nu' コマンド
</details>

#### Q21 エラー文を基に指定の行数、文字数へ移動してください。
（条件）2コマンドで移動

<details><summary>答え</summary>
'134G' で128行目へ移動。<br>
'47|' で47文字目へ移動。
</details>

#### Q22 対応する括弧にジャンプしてください。
（条件）1コマンドで移動
<details><summary>答え</summary>
'%' キーでジャンプ。 
</details>


#### Q23 この行にマークをつけてください。
<details><summary>答え</summary>
'm[a-zA-Z]' で任意の文字のマークを付ける。 
</details>


#### Q24 現在のマークの一覧を確認してください。
<details><summary>答え</summary>
':marks' をノーマルモードで実行。
</details>

#### Q25 'Q23'で付けたマークへジャンプしてください。
（条件）行数を指定したジャンプは使用不可。
<details><summary>答え</summary>
'[a-zA-Z] 
</details>

#### Q26 'Q23'で付けたマークを削除してください。
<details><summary>答え</summary>
':delmarks[a-zA-z]'
</details>


#### Q27 マーク's'と'e'で定義される範囲の文章を全て削除してください。（マーク行も含む）
（条件）削除する範囲は必ずマークを用いて指定する。
<details><summary>答え</summary>
'ms' と 'me' にマークを作成する。
:'s,'e d で2つのマーク間を削除
</details>


#### Q28 登録されているマークを全て削除してください
<details><summary>答え</summary>
:delmarks!
</details>


#### Q29 'Level3'という文字を検索してジャンプしてください
<details><summary>答え</summary>
'/Level3', '*' などを使用 <br>
'n'で順検索
</details>

#### 単語移動
|コマンド|概要|
|---------|---------|
| w | 次の単語（先頭）へ移動   |
| e　|次の単語（末尾）へ移動|
| b  | 前の単語（先頭）へ移動  |
| ge | 前の単語（末尾）へ移動  |

#### 行移動
|コマンド|概要|
|---------|---------|
| gg  |  ページの先頭へ移動  |
| G   | ページの最後へ移動  |
|10G| 10行目に移動（数字は任意） |
| 0 | 行の先頭へ移動  |
| ^  | 行の先頭へ移動   |
| $  | 行の末尾へ移動  |
| -  | 前の行の先頭へ移動   |
| +  | 次の行の先頭へ移動   |
| Enter  | 次の行の先頭へ移動   |
|5\||今の行の5文字目へ|

#### ジャンプ移動
|コマンド|概要|
|---------|---------|
| %   | 対応する括弧へ移動  |
| (  | 現在の文の先頭へ   |
| )   | 次の文の先頭へ  |
| {  | 現在の段落の先頭へ移動   |
| }   | 次の段落の先頭へ移動  |

#### 画面移動
|コマンド|概要|
|---------|---------|
| Ctrl + f   | 画面を1ページ分上へ  |
| Ctrl + b  | 画面を1ページ分下へ|
| Ctrl + u   | 画面を半ページ分上へ  |
| Ctrl + d  | 画面を半ページ分下へ   |
| zz   | カーソルが画面の中央になるように移動  |
| H  | ウィンドウの上端行に移動   |
| M   | ウィンドウの中央行に移動  |
| L   | ウィンドウの下端行に移動  |
| *   | カーソル位置の単語を下方向に検索  |
| #   | カーソル位置の単語を上方向に検索  |
| /[文字列]   | 文字列を下方向に検索する  |
| ?[文字列]   | 文字列を上方向に検索する  |
| n   | '/'や'?'で検索を行った後、下方向に次の検索結果に移動  |
| N   | '/'や'?'で検索を行った後、上方向に次の検索結果に移動  |

#### マーク
|コマンド|概要|
|---------|---------|
| :marks  | マークの一覧を表示   |
|m[a-zA-Z]|現在のカーソル位置にマークを作成|
| ''   | 直前のマークへ移動  |
| '[a-zA-Z]   | 指定のマークへ移動  |
| Ctrl + o  | 古いマークへ移動   |
| Ctrl + i   | 新しいマークへ移動  |
| :delmarks[a-zA-Z]  | 指定のマークを削除   |
| :delmarks!   | 全てのマークを削除  |


### Level3 テキスト編集

#### Q30 ここまでの編集を保存してください。
（条件）command + s , control + s  は使用不可
<details><summary>答え</summary>
':w'
</details>


#### Q31 指定した行を削除してください。
（条件）1コマンドで削除
<details><summary>答え</summary>
'dd'
</details>


#### Q32 指定した位置から行末尾までを削除してください。
（条件）1コマンドで削除
<details><summary>答え</summary>
'D' or 'd$'
</details>


#### Q33 指定した行をコピーしてください。
（条件）1コマンドでコピー
<details><summary>答え</summary>
'yy'
</details>


#### Q34 コピーした行をペーストしてください。
（条件）1コマンドでペースト
<details><summary>答え</summary>
'p'
</details>


#### Q35 10行削除してください。
（条件）1コマンドで削除
<details><summary>答え</summary>
'10dd'
</details>


#### Q36 3単語削除してください。
（条件）1コマンドで削除
<details><summary>答え</summary>
'3dw'
</details>

#### Q37 行を結合してください。
（条件）1コマンドで削除
<details><summary>答え</summary>
'gJ' or 'J' <br> 後者の場合は空白が入ります。
</details>

#### Q38 lsの結果を挿入してください
（条件）1コマンドで挿入
<details><summary>答え</summary>
':r! ls'
</details>


#### Q39 vimを開いたままシェルでlsを実行してください。
（条件）Q38のように文字列挿入はしない。
<details><summary>答え</summary>
':! ls'
</details>


#### Q40 画面を垂直分割してください。
<details><summary>答え</summary>
':sp'
</details>


#### Q41 右画面を水平分割してください。
<details><summary>答え</summary>
':vsp'
※左画面にいる場合は 'Ctrl + w , l'で右に移動後
</details>


#### Q42 左の画面に移動してください。
<details><summary>答え</summary>
'Ctrl + w , h'
</details>


#### Q43 画面を統合してください。
<details><summary>答え</summary>
':only'
</details>


#### Q44 インクリメントしてください。
<details><summary>答え</summary>
'Ctrl + a'
</details>

#### Q45 指定範囲を整形してください。
<details><summary>答え</summary>
'V' で行選択<br>
'=' で整形
</details>



#### 基本の文字列操作
|コマンド|概要|
|---------|---------|
| dd  | 行を削除  |
| D   | カーソル位置から行末までを削除  |
| cc  | 行を削除してインサートモードへ  |
| C   | カーソル位置から行末までを削除してインサートモードへ |
| o  | 現在の位置の下に行を追加しインサートモードへ   |
| O  | 現在の位置の上に行を追加しインサートモードへ   |
| yy  | 現在の行をコピー  |
| p  | カーソル後にペースト  |
| P  | カーソル後にペースト  |
| J  | 現在の行に下の行を結合する（空白を挟む）  |
| gJ  | 現在の行に下の行を結合する（空白を挟まない）  |



#### ファイル操作
|コマンド|概要|
|---------|---------|
| :q  | Vimを終了する   |
| :w   | ファイルを保存する  |
| :wq  | ファイルを保存してVimを終了する   |
| :q!   | 変更を破棄してVimを終了する  |
| :e [ファイル名]  | ファイルを開く   |
|:E|カレントディレクトリを開く|
|:r[ファイル名]|カーソルの後ろに、指定したファイルの文を挿入|
|:r!|カーソルの後ろに、指定したコマンド結果を挿入|
|:!|シェルでコマンドを実行する|
| ZZ   | ファイルを保存してVimを終了する  |
| ZQ  | 変更を破棄してVimを終了する   |

#### 画面操作
|コマンド|概要|
|---------|---------|
| :sp   | 画面の水平分割  |
| :vsp  | 画面の垂直分割   |
| Ctrl + w , Ctrl + w   | 画面の切り替え  |
| Ctrl + w , h / j / k / l   | 画面の移動（任意の方向の画面へ）  |
| :only  | 開いている画面を1つに  |
| :q   | 開いている画面を閉じる  |
| :qa  | 開いている全ての画面を閉じる  |
| :set nu  | 行番号を表示  |
| :qa  | 行番号の表示を解除  |




### Level4 品詞を伴うコマンド
#### vimの品詞
:::note
vimのコマンド体系は、基本的に`動詞` + `修飾子` + `名詞` で構成されます。
:::
※ 単体で使用するコマンドもあります。
【参考】
https://yanpritzker.com/learn-to-speak-vim-verbs-nouns-and-modifiers-d7bfed1f6b2d

##### 動詞
|コマンド|概要|
|---------|---------|
| v  | 文字を選択する（ビジュアルモード）   |
| c   | 削除してインサート  |
| d   | 削除   |
| y   | ヤンク（コピー）   |

##### 修飾子
|コマンド|概要|
|---------|---------|
|  i  | カーソルが含まれる   |
|  a  | 1つの|
|  t  | 次の検索文字まで（検索文字を含まない）   |
|  f  | 次の検索文字まで（検索文字を含む）   |
|  /  | 次の検索単語まで（検索単語を含まない）   |

##### 名詞
|コマンド|概要|
|---------|---------|
| w  | 単語   |
| s   | 文章（ピリオドまで） |
| p   | 段落（空白行まで）   |
| b   | ブロック（小括弧の中）   |
| t   | タグ（htmlタグなどの中）   |

<br>

#### Q46 カーソル下の単語を削除してください。
<details><summary>答え</summary>
'dw' など 'diw' 
</details>


#### Q47 if文の条件部分（括弧内）を削除してください。
（条件）1コマンドで削除。
<details><summary>答え</summary>
'di('
</details>


#### Q48 for文の処理部分（中括弧内）を削除してください。
（条件）1コマンドで削除。
<details><summary>答え</summary>
'di('
</details>


#### Q49 bodyタグの中身を削除してください。
（条件）1コマンドで削除, '2dd' や 'Vjd' は禁止
<details><summary>答え</summary>
'dit'
</details>


#### Q50 liタグを複製して3つにしてください。
（条件）移動含め3コマンドまで
<details><summary>答え</summary>
'337G' ulタグの行に移動<br>
'yit' ulタグ配下をヤンク<br>
'2p' ペースト
</details>


#### 組み合わせの例
|コマンド|概要|
|---------|---------|
| dw | カーソル位置から単語末尾までを削除   |
| diw   | カーソル上の単語を削除 |
| cw   | カーソル位置から単語末尾までを削除してインサート   |
| ciw   | カーソル上の単語を削除してインサート   |
| di(   | カーソルがある括弧内を全て削除   |
| ci(  | カーソルがある括弧内を全て削除してインサート   |
| dit   |タグ内のテキストを削除 |
| dt[.]   | カーソル一から任意の文字までを削除   |
| yit   | カーソル上のタグのテキストをコピー   |



### Level5 覚えておくとちょっと便利なコマンド

#### Q51 インデントを揃えてください。
（条件）整形系のコマンドは使用不可。
<details><summary>答え</summary>
'>>' でインデントを深くする。<br>
※逆は '<<'
</details>


#### Q52 定数を大文字にしてください。
（条件）1コマンドで変換, 移動は自由
<details><summary>答え</summary>
定数まで移動。<br>
'gUw','gUiw' 等で大文字にする。
</details>


#### Q53 'a'のASCIIコードを調べてください。
（条件）vimのコマンドを使用する。
<details><summary>答え</summary>
'ga' をaの上で使用する。
</details>


#### Q54 'HTTP_STATUS_SUCCESS'の定義場所にジャンプしてください。
（条件）vimのコマンドを使用する。
<details><summary>答え</summary>
'gD' 
</details>

#### Q55 現在のカーソル位置の情報を出力してください。
（条件）vimのコマンドを使用する。
<details><summary>答え</summary>
'g, Ctrl + g' 
</details>


### Level6 ビジュアルモード

#### Q56 各号車を空白区切りで連結してください。
<details><summary>答え</summary>
'V'で行選択<br>
行を選択<br>
'gJ' で連結
</details>

#### Q57 各行の先頭に '-' を付けてください。
<details><summary>答え</summary>
'Ctrl + v'で矩形選択<br>
行を選択<br>
'I' でインサートへ<br>
'-' を挿入<br>
'esc' でノーマルモードへ
</details>

#### Q58 4個ずつのグループに分けてください。
（条件）矩形選択を1度は使用
<details><summary>答え</summary>
2列目と3列目の間に移動<br>
'Ctrl + v'で矩形選択<br>
下まで選択<br>
'I' でインサートへ<br>
空白を挿入<br>
2行目と3行目の間二移動<br>
'o' で1行挿入
</details>

#### Q59 liのclassを"vim-item"に置換してください。
（条件）2コマンド以内で置換
<details><summary>答え</summary>
'V' でliの行を選択<br>
':s/item/vim-item' で置換<br>
※ '416,420s/item/vim-item' で1コマンドで置換も可能
</details>


#### ビジュアルモードの種類
|コマンド|概要|
|---------|---------|
| v | 単語選択  |
| V   | 行選択 |
| Ctrl + v   | 矩形選択|

### Level7 レジスタ

#### Q60 レジスタの一覧を表示してください。
<details><summary>答え</summary>
':reg'
</details>

#### Q61 名前付きレジスタ'a'に文章を登録してください。
<details><summary>答え</summary>
'"ayy'
</details>

#### Q62 名前付きレジスタ'a'の値をペーストしてください。
<details><summary>答え</summary>
'"ap'
</details>

#### Q63 各行の頭文字を名前付きレジスタ'b'に登録してください。
<details><summary>答え</summary>
'Ctrl + v'で行頭を選択<br>
'"by' でレジスタ'b' に登録
</details>

#### Q64 レジスタに登録されている値をペーストしてください。
（条件）インサートモードの状態でペースト。
<details><summary>答え</summary>
'Ctrl + r  ,  [レジスタ名]'
</details>


#### レジスタの使い方（抜粋）
|コマンド|概要|
|---------|---------|
| yy | 無名レジスタに登録  |
| dd   | 番号付きレジスタに登録 |
| "ayy   | レジスタ'a'にカーソル行の値を登録 |
| "adiw   | レジスタ'a'にカーソル上の単語を登録 |
| "ap   | レジスタ'a'の値をペースト |
| p   | 無名レジスタの値をペースト |



### Level8 マクロ

#### Q65 レジスタ'c' に単語の頭文字大文字にするマクロを登録してください。また、それを駆使してすべての単語の頭文字を大文字に変更してください。
<details><summary>答え</summary>
'qc' レジスタ'c' に登録開始<br>
'v' 頭文字を選択<br>
'gU' 大文字に変換<br>
'j' 下に移動<br>
'q' マクロの登録終了<br>
'@a' マクロの実行<br>
'@@' 繰り返し
</details>

#### Q66 単語をdivタグで囲うマクロを登録し、全ての単語に適用してください。
<details><summary>答え</summary>
'qa' マクロの登録開始
'I' 先頭に移動してインサートへ<br>
divタグを入力<br>
'esc' ノーマルモードへ<br>
'A' 末尾に移動してインサート<br>
divタグを入力<br>
'j' 下に移動<br>
'q' マクロの登録終了<br>
'@a' マクロ実行<br>
'@@' 繰り返し
</details>



#### Q67 前の問で作成したマクロを、strongタグで囲うものに編集してください。
<details><summary>答え</summary>
':put a' 'a' に登録してあるマクロのペースト
divをstrongに書き換える<br>
'"ayy'で更新する<br>
</details>


#### Q68 1行毎にインクリメントして数を表示するマクロを作成してください。
（前提）'0'が最初から記載してあるものとする。
<details><summary>答え</summary>
'qa' マクロの登録開始
'yy' ヤンク<br>
'p' 下にペースト<br>
'Ctrl + a' インクリメント<br>
'q' マクロの登録終了<br>
'@a' マクロ実行<br>
'@@' 繰り返し
</details>



#### マクロの使い方（抜粋）
|コマンド|概要|
|---------|---------|
| qa | 名前付きレジスタaにマクロの登録開始  |
| q   | 登録終了（登録中） |
| @a   | レジスタ'a'のマクロを実行 |
| @@   | 直前に使用したマクロを実行 |

## 最後に
本記事ではvimコマンドの中でも基本的なものをご紹介しました。
vimは今回ご紹介したものよりももっと複雑なコマンドが存在したり、自分独自のキーバインドを設定することができたりもします。
最初はとっつきにくいかもしれませんが、手に馴染むと爆速の開発が可能になるので、ぜひ使ってみてください。