[TOC]
# 關於VIM
## 基本指令介紹
### 命令模式
#### 模式切換
* ***i*** : 切換到插入模式(光標位置)
* ***I*** : 切換到插入模式(當前行首)
* ***a*** : 切換到插入模式(光標後一格)
* ***A*** : 切換到插入模式(當前行尾)
* ***o*** : 切換到插入模式(開啟新的下一行)
* ***O*** : 切換到插入模式(開啟新的上一行)
* ***s*** : 刪除光標位置的字元並切換到插入模式
* ***S*** : 刪除整行文字並切換到插入模式
* ***c*** : 刪除光標位置的字元(或一段文字)並切換到插入模式
* ***cw*** : 取代一個單詞(從光標開始)
* ***caw*** : 取代光標所在的整個字串
* ***c$*** : 取代到結尾的文字
* ***cf"*** : 取代到第一個"(該行為限)
* ***C*** : 刪除光標到行尾的文字並切換到插入模式(= ***c$***)
* ***:*** : 切換到底線命令模式,可以在最底一行輸入操作指令
* ***v*** : 切換到視覺模式
* ***V*** : 切換到視覺模式(整行)
* ***ctrl+v*** : 切換到視覺模式(區塊)
* ***ctrl+v 光標移動 shift+i 輸入文字 兩次ESC*** : 一次輸入多行
* ***R*** : 切換到取代模式
#### 刪除
* ***x*** : 刪除光標位置字元
* ***X*** : 刪除光標前一個位置字元
* ***dd*** : 刪除單行
* ***dw*** : 刪除光標開始的字串
* ***daw*** : 刪除光標所在的整個字串
* ***{n}dd*** : 刪除n行
* ***J*** : 刪除\n
* ***{n}J*** : 刪除n個\n
#### 複製
* ***yy*** : 複製單行
* ***{n}yy*** : 複製n行
#### 貼上
* ***p*** : 貼上文字
* ***P*** : 上一行貼上文字
#### 取代
* ***r{a}*** : 取代光標文字為a
* ***{n}r{a}*** : 取代光標後n個文字為a
#### 縮排
* ***>>*** : 右縮排一個tab
* ***{n}>>*** : 右縮排n個tab
* ***<<*** : 左縮排一個tab
* ***{n}<<*** : 左縮排n個tab
#### 查找
* ***n*** : 下一個
* ***N*** : 上一個
* ***shift+**** : 查找光標上的文字
#### 回復動作
* ***u*** : 恢復上一步
* ***ctrl+r*** : 回到下一步
#### 光標移動
* $\uparrow$ **k**
* $\downarrow$ **j**
* $\leftarrow$ **h**
* $\rightarrow$ **l**
* 水平移動
* ***$*** : 移動到行末
* ***0*** : 移動到行首
* ***^*** : 移動到行末(忽略空格符號)
* ***w*** : 移動到下一個單字開頭
* ***W*** : 移動到下一個單字開頭(以空格符號為基準)
* ***e*** : 移動到單字結尾
* ***E*** : 移動到單字結尾(以空格符號為基準)
* ***b*** : 移動到單字開頭
* ***B*** : 移動到單字開頭(以空格符號為基準)
* ***f{a}*** : 移動到下一個字母a
* ***F{a}*** : 移動到上一個字母a
* ***t{a}*** : 移動到下一個字母a的前一個位子
* ***T{a}*** : 移動到上一個字母a的後一個位子
* ***;*** : 重複上一次的查找指令(只適用到同一行結束)
* ***{n}{w,W,e,E,b,B,f{a},F{a},t{a},T{a},l,h}*** : 移動n個...
* 垂直移動
* ***{n}j*** : 向下移動n行
* ***{n}k*** : 向上移動n行
* ***H*** : 移動至畫面頂端
* ***M*** : 移動至畫面中間
* ***L*** : 移動至畫面底端
* ***ctrl+d*** : 向下半頁
* ***ctrl+u*** : 向上半頁
* ***ctrl+f*** : 向下整頁
* ***ctrl+b*** : 向上整頁
* 光標定位
* ***zz*** : 將光標所在行置中於畫面
* ***zt*** : 將光標所在行置於畫面頂端
* ***zb*** : 將光標所在行置於畫面底端
### 底線命令模式
* ***:q*** : 不儲存直接離開
* ***:!q*** : 不儲存強制直接離開
* ***:w*** : 儲存文檔但不離開
* ***:!w*** : 強制儲存文檔但不離開
* ***:w {name}*** : 儲存文檔並命名為name但不離開
* ***:x*** : 存檔並離開
* ***:e*** : 顯示檔名
* ***:e!*** : 放棄所有修改,從上次儲存文件紀錄開始編輯
* ***:0*** : 移動到文件檔案的起點
* ***:{n}*** : 移動到第n行
* ***{n}G***
* ***:$*** : 移動到文件檔案最後一行
* ***/{text}*** : 尋找文件中的text字串
* ***:%s/{search_from}/{replace_to}/gic***
* ***i*** 略過大小寫
* ***c*** 向使用者確認
* ***:50,100s/search_from/replace_to/gc*** 從50-100行進行搜尋取代
* ***tabe: {filename}*** : 開啟分頁
* ***gt*** : 切到下一頁
* ***gT*** : 切到上一頁
### 插入模式
* ***ESC*** 退出插入模式
* ***alt + F***
### 視覺模式
## Plugin 介紹
### 安裝[vim-plug](https://github.com/junegunn/vim-plug)管理插件
* 下載vim-plug
```sh
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```
* 在`.vimrc`中加入需要的插件名稱
```sh
call plug#begin()
Plug 'the Plug-in you need'
call plug#end()
```
### 推薦插件
* [vim-airline](https://github.com/vim-airline/vim-airline)
* [nerdtree](https://github.com/preservim/nerdtree)
* [syntastic](https://github.com/vim-syntastic/syntastic)
* [vim-code-dark](https://github.com/tomasiser/vim-code-dark)
* [jedi-vim](https://github.com/davidhalter/jedi-vim)
* [YouCompleteMe](https://github.com/ycm-core/YouCompleteMe)
## VIM 手動安裝
當初為了滿足[YouCompleteMe](https://github.com/ycm-core/YouCompleteMe)插件要求的版本決定手動安裝,因為真的踩了不少坑,在這邊紀錄一下安裝過程。
1. 從[github](https://github.com/vim/vim)上直接下載
```
$ git clone https://github.com/vim/vim.git
```
2. 安裝相關的package
```
$ yum install gcc make ncurses ncurses-devel python-devel
```
* 這裡遇到的一個坑就是python-devel,原本環境中的python跟python-devel似乎並不相同,要記得確認安裝的版本為何
3. 進入建置目錄與調整版本
```
$ cd vim/src && git checkout v8.1.2269
```
* `checkout`的指令可以視你想要的vim版本進行調整,這裡選擇的是當前[YouCompleteMe](https://github.com/ycm-core/YouCompleteMe)插件支援的版本
5. 設定configure
```
$ ./configure \
--with-features=huge \
--enable-python3interp=yes \
--enable-multibyte \
--enable-cscope \
--with-python3-config-dir=/usr/lib64/python3.6/config-3.6m-x86_64-linux-gnu \
--prefix=/"your home dir"/.local/vim \
--with-python3-command=python3.6 \
--enable-fail-if-missing
```
* 注意這裡的`--with-python3-command=python3.6`跟`--with-python3-config-dir`的python版本必須跟前面提到的python-devel相同。反正如果python設定失敗`--enable-fail-if-missing`就會讓configure終止並報錯
* 如果要重新跑一次configure建議先清空cached再開始
```
$ make clean distclean
```
3. 設定完configure後就可以進行安裝
```
$ make && make install
```
4. 在shell的設定檔中新增vim環境變數以覆蓋原本預設的版本
```sh
if [ -d "$HOME/.local/vim/bin/" ] ; then
PATH="$HOME/.local/vim/bin/:$PATH"
fi
```
5. 安裝完成後在terminal下指令
```
$ vim --version | grep python3
```
* 如果顯示如下的結果(python3前面有個"+"),就代表python有安裝成功
```
+cmdline_info +libcall +python3 +visualextra
Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lm -ltinfo -lelf -lselinux -ldl -L/usr/lib64/python3.6/config-3.6m-x86_64-linux-gnu -lpython3.6m -lpthread -ldl -lutil -lm
```
## Reference
* [【Vim 編輯器 入門指南 (上)】用思維的速度寫程式](https://ithelp.ithome.com.tw/articles/10255325?sc=pt)
* [Vim維基百科](https://zh.wikipedia.org/wiki/Vim)
* [簡明 Vim 文字編輯器操作入門教學](https://blog.techbridge.cc/2020/04/06/how-to-use-vim-as-an-editor-tutorial/)
* [简明 VIM 练级攻略](https://coolshell.cn/articles/5426.html)
:::spoiler My .vimrc
```.vimrc
call plug#begin()
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'preservim/nerdtree'
Plug 'vim-syntastic/syntastic'
Plug 'tomasiser/vim-code-dark'
Plug 'davidhalter/jedi-vim'
Plug 'ycm-core/YouCompleteMe'
call plug#end()
syntax enable
set smartindent
set ai
autocmd FileType make set noexpandtab shiftwidth=8 softtabstop=0
set tabstop=4
set shiftwidth=4
set expandtab
set cursorline
set nu
set hlsearch
set t_Co=256
colorscheme torte
hi CursorLine cterm=none ctermbg=60 ctermfg=White
filetype indent on
"inoremap { {}<LEFT>
"inoremap [ []<LEFT>
"inoremap ( ()<LEFT>
set statusline=%#filepath#[%{expand('%:p')}]%#filetype#[%{strlen(&fenc)?&fenc:&enc},\ %{&ff},\ %{strlen(&filetype)?&filetype:'plain'}]%#filesize#%{FileSize()}%{IsBinary()}%=%#position#%c,%l/%L\ [%3p%%]
hi filepath cterm=none ctermbg=238 ctermfg=40
hi filetype cterm=none ctermbg=238 ctermfg=45
hi filesize cterm=none ctermbg=238 ctermfg=225
hi position cterm=none ctermbg=238 ctermfg=228
nnoremap <leader>n :NERDTreeFocus<CR>
nnoremap <C-n> :NERDTree<CR>
nnoremap <C-t> :NERDTreeToggle<CR>
nnoremap <C-f> :NERDTreeFind<CR>
" Start NERDTree. If a file is specified, move the cursor to its window.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif
" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
" Close the tab if NERDTree is the only window remaining in it.
autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
" Open the existing NERDTree on each new tab.
autocmd BufWinEnter * if getcmdwintype() == '' | silent NERDTreeMirror | endif
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
"set statusline+=%*let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0
"let g:ycm_show_diagnostics_ui = 0
" :SyntasticCheck phpmd
let g:syntastic_aggregate_errors = 1
"let g:syntastic_php_checkers = ['php', 'phpcs', 'phpmd']
"let g:syntastic_php_checkers = ['php', 'phpmd']
" python pylint
let g:syntastic_python_checkers = ['python']
"let g:syntastic_python_exec = 'python'
"let g:syntastic_python_args = ['-m', 'py_compile']
"
"
"
"colorscheme codedark
let g:airline_theme = 'codedark'
set t_ut=
colorscheme codedark
"let g:jedi#use_tabs_not_buffers = 1
let g:jedi#goto_command = "<leader>d"
let g:jedi#goto_assignments_command = "<leader>g"
let g:jedi#goto_stubs_command = "<leader>s"
let g:jedi#goto_definitions_command = ""
let g:jedi#documentation_command = "K"
let g:jedi#usages_command = "<leader>n"
let g:jedi#completions_command = "<C-Space>"
let g:jedi#rename_command = "<leader>r"
autocmd FileType python setlocal completeopt-=preview
:set backspace=indent,eol,start
let g:ycm_global_ycm_extra_conf = "~/.vim/plugged/YouCompleteMe/.ycm_extra_conf.py"
set completeopt-=preview
```
:::