Vim？iniファイルの編集とかでちょっと触るけど…を卒業する

なんとなくで使っていたVimについて学んだので、簡単にまとめます。  

学習前の私は、移動はカーソルキー、入力は「i」キーという典型的な人でした。  
意図せずVisualModeに入ってしまい、  
「i押しても入力出来へんし、なんやこれ・・・？」  
というレベルです。  

学んでみて、これは楽になったな、と感じたコマンドを紹介していきます。  
できれば、便利っぽいかも？と思ったものは手元で試しながら読んでいただけると嬉しいです。  

※[]で囲んでいるのは何を入力するかを記載しているので、実際コマンドを打つ際は[]は省いてください。

## Vimの４つのモード

Vimには４つのモードがあります。  
|Mode|概要|モードへの入り方|
|:-:|:-:|:-:|
|Normal Mode|他モードへ移行。テキスト内の移動やコピペ、削除や置換など|ESC, ctrl + [|
|Visual Mode|テキストの選択|v|
|Insert Mode|テキストの編集|a, A, i, I ,...etc|
|Command Mode|新しいファイルやタブを開く。SaveやExitなど。|:|

`vim [ファイル名]`で開いたら、Normal Modeで起動します。  

始めはこれを覚えていただき、操作していく上で自分はどのモードで操作しているのかがわかることが第一歩目です。  

vscodeでも、teraterm等のターミナルでも、画面下に現在のモードが表示されているはずです。

![mode表示例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518748/d1399c7e-bc24-53b5-318c-74335827c8a6.png)


## 覚えてほしいコマンド

### 移動編

自分もずっと、カーソルキーに頼りっきりでした。  
学習後も、思わずカーソルキーに指を伸ばしてしまうこともあります。  

それでも、`h,j,k,l`へ矯正することに決めました。  
慣れれば指の移動距離が短いので楽になること、キーボードにカーソルキーがないケースにもいずれぶつかることだと思うからです。  

とはいえ、１文字ずつしかカーソルが移動させられないのでは不便ですね。  
そこで、いくつか移動コマンドを紹介します。  
（※hjklがそれぞれ、左下上右に対応しているのは表から省きます。）  


#### w e b W E B

単語単位での移動ができます。  
日本語に対してだと、直感的でない部分がありますが、英文やプログラミング時には使いやすいです。  
|Command|概要|
|:-:|:-:|
|w W|次の単語の先頭へ移動|
|e E|単語の末尾へ移動|
|b B|前の単語の末尾へ移動|

小文字入力の場合、ハイフンやカンマ、句読点などの記号を区切り文字として移動します。

```python:小文字
#        ↓にカーソルがあったとして 
 print(datetime.datetime(2023, 8, 8, 23, 15, 30, 2000))
#      ↑      ↑↑wでここ
#      |      |eでここ
#      |bでここ
```

大文字になると、ハイフンヤカンマ、句読点を無視し、空白を区切りとみなして移動します。  

```python:大文字
#        ↓にカーソルがあったとして 
 print(datetime.datetime(2023, 8, 8, 23, 15, 30, 2000))
#↑                           ↑ ↑Wでここ
#|                           |Eでここ
#|Bでここ
```

#### ^ 0 $

現在カーソルのある行の先頭や末尾に移動できます。  
正規表現を元に作られているとのことなので、納得です。  
|Command|概要|
|:-:|:-:|
|^ 0|カーソルのある行の先頭へ移動|
|$|カーソルのある行の末尾へ移動|

#### m[a-zA-Z] :marks

さくらエディタなんかを使った事がある方であれば理解しやすいと思うのですが、ブックマークができます。  
mの後にa~zを打つことで、ブックマークを付けられます。  
|Command|概要|
|:-:|:-:|
|m[a-zA-Z]|カーソルのある場所へマークを付ける|
|`[a-zA-Z]|対応するa~z A-Zのマーク位置へ移動|
|'[a-zA-Z]|対応するa~z A-Zのマークがある行頭へ移動|
|``|ジャンプ元へ移動|
|''|ジャンプ元の行先頭へ移動|
|:marks|ブックマークのリストを表示|

小文字でのマークは`ローカルマーク`と呼ばれ、開いているファイルがスコープになります。  
大文字でのマークは`グローバルマーク`と呼ばれ、ファイルまで覚えています。  
そのため、マークを付けたファイルが閉じられていても、開いてくれます。  

#### /[検索文字列] ?[検索文字列] * n N

ctrl + fのような機能になります。
|Command|概要|
|:-:|:-:|
|/[検索文字列]|検索文字列をハイライトし、検索時のカーソル位置の次の検索文字列へ移動|
|?[検索文字列]|検索文字列をハイライトし、検索時のカーソル位置の前の検索文字列へ移動|
|*|カーソル位置の単語を検索し、ハイライト|
|n|次の検索文字列へ移動|
|N|前の検索文字列へ移動|

自分的には、`*`がかなり便利だな～と感じます。  

#### G gg

ファイルの先頭、末尾に移動します。  
|Command|概要|
|:-:|:-:|
|G|ファイルの末尾へ移動|
|gg|ファイルの先頭へ移動|

Linuxのlessコマンドなんかでlogファイルを開いて、最新を見たい時なんかに`G`で末尾に移動みたいな使い方を自分はよくしています。  

### 編集編

#### i a I A

カーソル位置への挿入（i insert）、カーソル位置の後ろへの追加（a append)を行います。  

|Command|概要|
|:-:|:-:|
|i|カーソル位置でInsert Modeへ遷移|
|a|カーソル位置の後ろでInsert Modeへ遷移|
|I|カーソル行の先頭でInsert Modeへ遷移|
|A|カーソル行の末尾でInsert Modeへ遷移|

#### o O

いちいち末尾に移動してからInsert Modeにし、改行して次の行を編集…のような面倒なことをしてはないでしょうか？  
このコマンドで解消できます。  
|Command|概要|
|:-:|:-:|
|o|カーソル行の下に空行を挿入し、挿入した行でInsert Modeへ遷移|
|O|カーソル行の上に空行を挿入し、挿入した行でInsert Modeへ遷移|

#### x X

削除コマンドになります。  
これは、Insert Modeへ遷移はしません。  

|Command|概要|
|:-:|:-:|
|x|カーソルの当たっている文字を削除|
|X|カーソルの当たっている前の文字を削除|

Xについては、特に覚える必要はなさそうですね。  

#### y yy

コピーコマンドになります。  
Insert Modeに遷移しません。  

|Command|概要|
|:-:|:-:|
|y[w/e/etc...]|yに続けるコマンドに応じてコピー|
|yy|カーソル行のコピー|

`y`については、`ye`のように使用し、１単語コピーするのように使用します。  
`y3`のようにし、３文字コピーなんかもできます。  

同様に、`yy`においても、`yy5`のようにすると、５行コピーができます。  

#### p P

yでコピーしたものをペーストします。  
Insert Modeに遷移しません。  

|Command|概要|
|:-:|:-:|
|p|カーソル位置の後ろにペースト|
|P|カーソル位置の前にペースト|

#### d dd

削除コマンドになります。  
Insert Modeに遷移しません。  

|Command|概要|
|:-:|:-:|
|d[w/e/etc...]|dに続けるコマンドに応じて削除|
|dd|カーソル行の削除|

`y`での説明同様に使用することができます。  

#### c cc C

`d`と同様に削除コマンドになります。  
ただし、こちらはInsert Modeに遷移します。  

|Command|概要|
|:-:|:-:|
|c[w/e/etc...]|cに続けるコマンドに応じて削除後、Insert Modeに遷移|
|cc|カーソル行の削除後、Insert Modeに遷移|
|C|カーソル位置以降の行内を削除後、Insert Modeに遷移|

後述しますが、`c`コマンドは組み合わせでかなり強力な操作ができます。  

#### r R

文字列の置換コマンドになります。  
Insert Modeに遷移しません。  

|Command|概要|
|:-:|:-:|
|r[任意の文字]|カーソル位置の文字を置換|
|R|Replace Modeに遷移し、その間に入力に合わせ、カーソル位置の文字列が置換。ESCでMode終了。|

3r[任意の文字]のようにも使用できますが、この場合、任意の１文字にカーソルから３文字置換という動作になります。  

#### s S

`r`コマンド同様、置換コマンドになります。  
ただし、こちらはInsert Modeに遷移します。  

|Command|概要|
|:-:|:-:|
|s|カーソル位置の文字を削除し、Insert Modeに遷移|
|S|カーソル行の削除後、Insert Modeに遷移|

前述の`cc`と`s`の違いがわからないのですが、`s`の方が操作は早いかもしれません。  

#### v V

Visual Modeへの遷移コマンドになります。  

|Command|概要|
|:-:|:-:|
|v|Visual Modeへの遷移|
|V|Visual Line Modeへの遷移|

単独で使用するケースは無いと思っています。  
`v`の場合、カーソル位置から選択が開始されます。  
その後、今まで学んだコマンドを使用し、選択したい範囲を指定していき、削除や置換、コピペ等を行います。  

#### u U ctrl+r

ここまで色々な編集方法を学びましたが、操作ミスした時に戻るコマンドはないのか？  
ctrl+zのような操作は、`u`で行います。  

|Command|概要|
|:-:|:-:|
|u|変更を１つ戻す|
|U|最近変更された行の１行の中で変更された最近の変更を全て戻す|
|ctrl+r|戻した操作を取り消す|

### ファイル操作系

#### :q :q! :w :wq ZZ ZQ

`:`で始まるコマンドはCommand Lineに入って使用するコマンドです。  
ファイルを閉じてしまっていい場合には、`ZZ`や`ZQ`を覚えておくと早いです。  

|Command|概要|
|:-:|:-:|
|:q|ファイルを保存せず閉じる|
|:q!|変更があるファイルを保存せず閉じる|
|:w|変更を保存する|
|:wq|変更を保存し、ファイルを閉じる|
|ZZ|変更を保存し、ファイルを閉じる|
|ZQ|保存せず、ファイルを閉じる|

### 特に便利だと思う組み合わせ紹介

`c`コマンドで後述すると記載していました。  
`cw`や`ciw`がかなり便利だなと感じています。  

```python:cw ciw
#        ↓にカーソルがあったとして 
 print(datetime.datetime(2023, 8, 8, 23, 15, 30, 2000))

# cwを使うと
 print(da.datetime(2023, 8, 8, 23, 15, 30, 2000))
#        ↑カーソル位置から単語の末尾まで削除してInsert Modeに遷移します。

# ciwを使うと
 print(.datetime(2023, 8, 8, 23, 15, 30, 2000))
#      ↑カーソル位置の単語を削除してInsert Modeに遷移します。
```

このような編集は、コードを書いていてよくあるので、使用頻度も高い組み合わせに思います。  

また、更に応用が効き、`ci"`や`ci(`なんか知ったときは、ちょっとした感動すら覚えました。  

```python:ci" ci(
# ↓にカーソルがあったとして
"test"
# ci"を使うと
""
#↑""で囲まれた中を削除し、Insert Modeに遷移します。
 
#                ↓にカーソルがあったとして
 print(datetime.datetime(2023, 8, 8, 23, 15, 30, 2000))
# ci(を使うと
 print()
#      ↑()で囲まれた中を削除し、Insert Modeに遷移します。
```

ちゃんと、対になるものを解釈して、その中を消したうえでInsert Modeに遷移してくれます。  
非常に楽ができるコマンドだと感じています。  

## さいごに


今回の記事を書くに当たって知ったコマンドも多く、自身のVim操作は学習開始時からとても楽ができるようになりました。  
読んでいただいた方に、一つでも便利だなと思っていただけるようなコマンドがあれば嬉しいです。

ここまで見ていただき、ありがとうございました。  

## 参考

https://qiita.com/hachi8833/items/7beeee825c11f7437f54

https://qiita.com/JpnLavender/items/fabcc79b4ab0d52e1f6d