# [Vim] 常用按鍵整理
###### tags: `VIM` `Editor`
## 基礎移動
1. `w/W` 往前一個詞
- `W` 會到下一個用空白區隔的詞
2. `b/B` 往後一個詞
- `B` 會到前一個用空白區隔的詞
3. `{` 往上跳一個段落
4. `}` 往下跳一個段落
5. `gg` 到檔案的最上端
6. `G` 到檔案的最下段
7. `0` 移動到該的開頭(即使開頭為空白也會過去) / `^` 會移動到該行第一個字(只會到字那,所以不會移到開頭的空白)
9. `$` 移動到該行的最後
10. `數字G` 移動到對應的數字行(13G = 飛到第 13 行)
## 模式轉換
![](https://i.imgur.com/dU5MTzw.png)
### insert 模式
1. insert 模式按下 `esc` / `control` + `[` 會到 normal 模式
### normal 模式
1. `i` 直接在游標那切換至 insert 模式
2. `a` 游標會往後一格再進入 insert 模式
3. `o` 會在游標下插入一行空白,游標進入空白後進入 insert 模式
### visual 模式
==複製貼上專用的模式==
游標移動至哪裡就選取至哪裡。
![](https://i.imgur.com/FBBRbGD.png)
1. 在 normal 模式中按下 `v` 進入 visual 模式
2. `y`(yank) 複製選取的東西
3. `p`(paste)貼上選取的東西(可搭配量詞,如 `5p` => 貼上五次) => 如果 `yy` 整行 `P` 可以貼在游標的上一行(就不用像之前一定要讓游標跑到貼上目的地的上方)
4. `yy` = `Y` 直接複製該行
## 搜尋
1. `/x` + `enter` 在檔案中搜尋 x => 常搭配 `:set hlsearch` + `enter` 將搜尋結果高亮化 (取消高亮化 `:set nohlsearch`)
2. `n` 移動到下一個搜尋結果
3. `N` 移動到上一個搜尋結果
4. `fx` 跳到該行下一個最近的 x(游標會在 x 之上)
5. `Fx` 跳到該行前一個最近的 x(游標會在 x 之上)
6. `tx` 跳到該行下一個最近的 x(游標會在 x 之前)
7. `Tx` 跳到該行前一個最近的 x(游標會在 x 之前)
8. `?查找字串` 查找目前游標之上的字串
9. `/查找字串` 查找目前游標之下的字串
## 快速移動
1. `%` 會移動到該行的 ()
2. `e` 游標移動到該詞的最後一個字
3. `control f` 移動到下一頁
4. `control b` 移動到上一頁(當程式碼很多的時候很好用!!,就不用 `{` `}` 慢慢跳段落)
## 快速刪除
1. 在 normal 模式中按下 `diw` 會刪除目前游標的字區
2. 游標於 `'', {}, ()` 內按下 `di '' / {} / ()` 會刪除 `'', {}, ()` 的所有東西
```javascript=
function testing () {
console.log('_hi!');
游標
}
// normal 模式按下 `di'`
function testing () {
console.log('');
}
```
3. `db` 快速刪除游標前的所有字
### 快速刪除至關閉的 `}`, `]` or `)` 之前
1. 可以用 `] + 任一個關閉的 }, ] or )` + 動詞 `d` -> `d]}`
2. 或者套用搜尋的功能(`f` / `t`) -> `dt)` ---> `df)` 會刪掉關閉的 ),因為 `f` 會把游標移到要找尋的東西之上, `t` 游標則會停在要找的東西之前。
```javascript=
(2,'cursor' 3, 4)
// d])
(2,)
(2, 'cursor' 3, 4)
// dt)
(2,)
// df)
(2,
```
### 快速刪除有相同文字的行(Deleting Lines Containing a Pattern)
1. 只刪除目前 file 內
```javascript=
:g/{pattern}/d
- g: global
- {pattern} 被搜尋的文字
- d: delete
```
```javascript=
console.log()
11111
console.log()
22222
// g:/console/d
11111
22222
```
[How to Delete Lines in Vim / Vi](https://linuxize.com/post/vim-delete-line/)
## 快速複製
1. 在 normal 模式下按下 `yiw` 會快速複製選取的字區
2. 游標於 `'', {}, ()` 內按下 `yi '' / {} / ()` 會快速複製 `'', {}, ()` 的所有東西
3. `yy` 可以快速複製一整行,所以 `p` 的時候會自動貼在游標的下面一整行(不用自己先 `o` 新增一行)
## 快速更改 / 刪除目前的字詞
1. 在 normal 模式按下 `diw` 可快速刪除目前的詞
2. 在 normal 模式按下 `ciw` 可快速更改目前的詞(跟上面的差不多 XDD)
3. 只要更改現在游標的字,在 normal 模式可以按 `r`(replace)後輸入要改的字即可
4. 在 normal 模式下案 `C` 會自動刪除含游標後的所有文字並直接進入 insert 模式
5. 在 normal 模式下案 `cB` 會自動刪除游標前的所有文字並直接進入 insert 模式
## 搜尋取代
1. `:s/<搜尋文字>/<取代為>/g`
- `g` 代表 global(整個 file)
- `i` 代表 ignore(不區分大小寫,預設是 Case sensitive)
- 所以 `:s/FOO/iii/gi` -> foo 也會被更改
2. 增加範圍(行數)`:<startLine>,<endLine>s/Foo/iii/g
- `:10,15s/Foo/iii/g`(注意行數之間不用空白)(10-15 行之間的 Foo 會被改為 iii)
3. all lines `:%s/Foo/iii/g`(整個檔案的 Foo 改為 iii)
4. 特殊符號用 `#`:
- `/aaa.bbb` 想要改成 `aaaccc` 怎麼改?
- `:%s#<搜尋的文字>#<取代為>`(以 `#` 代表開始/結束)
- `:%s#/aaaa.bbb#aaaccc`(注意不用下 `g` flag
[How to include forward slash in vi search & replace](https://stackoverflow.com/questions/11823616/how-to-include-forward-slash-in-vi-search-replace)
## 游標移到上一個地點
1. `control + o` 讓游標快速回到上個位置
## 連續多行輸入
1. 按下 `control + v` 進入 visual block 模式,接下來可以使用 `hjkl` (左下上右)控制游標選取的位置。按下 `I` 不管游標移到哪裡,回到一開始 visual block 的起始位置進入 insert 模式。==按下 `A` 則會在游標後方進入 insert 模式==,就可以多行輸入了。
![](https://i.imgur.com/sTvut1C.png)
*`control + v` 進入 visual block 後使用 `j` 往下選取*
![](https://i.imgur.com/5GCW3vm.png)
*按下 `A` 在游標後進入 insert 模式*
## 快速更改 / 刪除同樣的字
normal 模式搜尋特定的字詞,按下 `cgn`(會更改目前游標的字詞),更改完畢後按下 .(Dot)會持續更新下一個相同字,如果想要跳過一個,按下 `n`。`dgn` 道理相同,但就會變成刪除。
### `.(dot)` 在 vim 裡面代表重複執行上一個執行的動作
![](https://miro.medium.com/max/1206/1*xrEmsNKaOguADXWAKkeSEA.gif)
## 快速更改 / 刪除 parenthesis (), "", {}, []
在 normal 模式中游標指到 parenthesis
1. 按下 `c` `s` `原本的 parenthesis` `想要改的 parenthesis`,就可以快速更改 parenthesis
![](https://i.imgur.com/d8RplfG.png)
*游標指向()後按下 `c` `s` `(` 坐下角出現 --SURROUND INPUT-- 等待輸入想要改成的 parenthesis*
![](https://i.imgur.com/C8W4sky.png)
*之後按 `[` 原本的 () 變成 []*
2. 按下 `d` `s` `parenthesis` 可以馬上刪除目前游標指向的 parenthesis
## 快速在 html 標籤中修改 / 複製 文字
1. `cit`
> c = change
> i = inner(in)
> t = tag(html tag)
2. `yit`
> y = yank
> i = inner(in)
> t = tag(html tag)
3. `dit`
> d(會剪下) = delete
> i = inner(in)
> t = tag(html tag)
以上都不用讓游標進入 tag,只要在該行按下即可
![image alt](https://i.giphy.com/media/VfDvTq4lIcH1kKd6K0/giphy.gif)
## 縮排
1. normal 模式下在該行按下 `>>` 會增加空白
2. normal 模式下在該行按下 `<<` 會退空白
3. 也可以搭配量詞使用,比方來說 `3>>`,代表從游標(含游標行)算三行都會增加空白
4. 透過 `V` 進入 Visual Line 模式,透過 `jk` 選要的行後按下 `=`,這時 VIM 會自動根據上下文縮排
## 快速選取 / 編輯 / 刪除
1. `vi 什麼` 可以快速選取 什麼 裡面的東西(同理 `ci 什麼` 可以快速編輯 什麼 裡面的東西;`di 什麼` 可以快速刪除 什麼 裡面的東西)
> v = visual
> i = inner
![](https://i.imgur.com/iu5Qn5H.png)
*`vit` 快速選取 a tag 裡面的字*
![](https://i.imgur.com/ND9yaoj.png)
![](https://i.imgur.com/fP3ne0y.png)
*`vi{` 快速選取 `{` 裡面的東西*
2. `va 什麼` 可以快速選取 什麼 及 什麼附近的東西(同理 `ca 什麼` 可以快速編輯 什麼 及 什麼附近的東西;`di 什麼` 可以快速刪除 什麼 及 什麼附近的東西)
> v = visual
> a = aroud
![](https://i.imgur.com/AZ4qGTL.png)
*`va'` 快速選取 'str'*
![](https://i.imgur.com/vvYl6Xm.png)
![](https://i.imgur.com/MmfiTfm.png)
*`va{` 快速選取 {...}*
![](https://i.imgur.com/aB6up3y.png)
*`vat` 快速選取 文字及文字的 tag(也就是 <>...<>)*
3. `v {` / `v }` 可以快速選取游標至上一個 / 下一個段落的東西(同理 `c {` / `c }` 可以快速編輯游標至上一個 / 下一個段落的東西;同理 `d {` / `d }` 可以快速刪除游標至上一個 / 下一個段落的東西)
## 大小寫互換
1. 在 normal 模式下游標選取字再按 `~` 會大小寫互換
## macros 錄製,錄製一個動作後重複執行數次
1. 在 normal 模式下按下 q + 任一個英文(大小寫有差)即可開始錄製
> 在左下角會出現 recording @a(剛才按下的英文字母)
2. 接下來做的指令就會被錄製,結束錄製時按下 q 即可(便會回到 normal 模式)
3. 在 normal 模式中按下 `@a(剛才啟動錄製時的英文字)`便會執行剛才錄製的指令
> 也可使用 Text Object,`5@a` -> 執行五次剛才 `a` 的記錄指令
[How to use Vim macros](https://www.youtube.com/watch?v=aPL_7FTAGCc)
```javascript=
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
123 = '22'
// 想要變成
22
1. 先開始錄製模式:q + a
2. j 往下移動至第一行 123 = '22'
3. ^ 確保我在開頭
4. daw 刪除 123
5. daw 刪除 =
6. ds' 刪除 '22' 的單引號
7. q 結束錄製
8. 10@a 重複執行 a 的錄製記錄 10 次
// 就會變成
22
22
22
22
22
22
22
22
22
22
22
```
## 視窗大小調整
https://vi.stackexchange.com/questions/514/how-do-i-change-the-current-splits-width-and-height
## Text Object
vim 的大多數按鍵都是以 Text Object 的概念為基礎,所以能夠理解這個觀念日後在輸入的按鍵的時候就可以了解這組按鍵的意思了。
基本上分為四種:動詞、範圍、名詞、量詞
### 動詞
常見的動詞為:
- `y` = yank(複製)
- 'd' = delete(但會儲存在剪貼簿裡面)
- 'c' = change
- 'p' = paste
這些動詞如果沒有配合其他詞的組合是沒有很大的幫助的。
### 名詞
常見的名詞為:
- 'w' = word
- 'p' = paragraph
- 't' = tag(比方來說 HTML tags)
- 's' =
- 單、雙引號
- 小括號()
- 中括號[]
- 花括號{}
### 範圍
常見的範圍詞為:
- 'i' = inner
- 'a' = around
### 量詞
就只是數字
### 使用組合技吧!
組合技能的使用遵循著 {動詞}{範圍}{名詞} 的排列順序,所以 `ci(` 就是 change inner () => 改變 () 裡面的文字; `di(` 刪除 () 裡面的文字; `yiw` 就比較需要一些想像力了, yank inner word => 會複製游標當前的整個字詞(因為游標在整個字詞裡面,所以會複製到整個字詞)。還有很多範例,比如說 `V{` VISUAL-LINE 往上選取到上一個段落, `V}` 則是往下選取一個段落等等。
==總之記得 {動詞} + {範圍} / {名詞} + {範圍} 才可以使用快速的 combo 技能==
## 參考資料
1. [即將失傳的古老技藝 Vim](https://www.youtube.com/playlist?list=PLBd8JGCAcUAH56L2CYF7SmWJYKwHQYUDI)
2. [Vim Cheat Sheet](https://vim.rtorr.com/)
3. [You don’t need more than one cursor in vim](https://medium.com/@schtoeffel/you-don-t-need-more-than-one-cursor-in-vim-2c44117d51db)
4. [Quickest way to change a pair of parenthesis to brackets in vim](https://stackoverflow.com/questions/25405072/quickest-way-to-change-a-pair-of-parenthesis-to-brackets-in-vim)
5. [你應該擴充的 text object](https://amikai.github.io/2020/09/22/vim-text-object/) => 找時間回來看會更理解 vim text 指令的意涵
6. [10 Vim + VSCode tips that will supercharge your productivity](https://dev.to/jw_baldwin/10-vim-vscode-tips-that-will-supercharge-your-productivity-504e)