跳至主要内容

[Vim] Terminal Vim

TL;DR

包含在terminal使用vim時的一些其他功能。不一定可以完美對應vsc上的vim。

參考資料

圖片所有權

本篇有些圖片取自高見龍老師在IT幫的鐵人賽文章中。

僅供紀錄學習用途,如有不妥麻煩告知。

相關連結


Buffer/Window/Tab的差異

如果使用:h window去查詢會得到下面的回覆  window

buffer可能比較難理解,代表一個儲存在記憶體中的文字檔案
window就是顯示一個檔案的視窗(也就是上面的分割畫面)
而tab是window的集合,也就是一個tab裡面可以有很多個windows(當然只有一個window也沒有問題)

簡單來說
  • buffer用來保存資料的
  • window用來展示資料
  • Tab用來排版佈局

buffer編號

如果要觀看buffer裡面的檔案可以使用:ls來觀看,%a的地方代表目前所在的分頁的位置,且左邊會有buffer的編號

Buffer編號

a代表其他分頁中目前停留的地方,所以如果使用gt切換tab的話,buffer1的位置就會變成%a

目前buffer3旁邊有一個#代表上一個開啟的buffer,可以使用:b <buffer number>來切換buffer(eg: :b1)

ctrl+^可以快速在%a與#中間切換!

:b <部分檔名> 也可以開啟已經存在ls中的buffer檔案(只要配對到唯一一個輸入部分檔名也可以開啟)

:bn可以切換到下一個buffer(next的意思),:bp可以切換到前一個buffer(previous)

:bl可以跳到最後一個buffer(last),:bf可以跳到第一個buffer(front)

:bdelete可以關掉buffer,或簡稱:bd

:tab ball (all的意思),可以一口氣展開全部目前開啟的buffer成tab,也可以簡寫成:tab ba

雖然感覺還是使用tab比較直覺,但是buffer用習慣也很好用,看個人使用習慣囉~

key mapping

vim另一個強大的地方是他的輸入映射,可以將目前輸入的內容替換成其他內容(或是指令)

mapping所使用主要有四種常見的指令

命令Normal ModeVisual ModeInsert Mode
mapVV
nmapV
vmapV
imapV

可以看到不同的指令分別對應到的模式也不同,可以根據想使用的狀況去選用

這邊很常會用到的一個資源是 :h key-notation

Image

key-notation可以查詢各種對應的鍵

舉例來說,輸入:vmap <C-c> y代表會設定在visual模式之下,將<C-c>(利用key-notation查詢到代表這是ctrl+c的意思)替換成y,也就是說,如果已經選取了,使用ctrl+c(如同我們平常在其他軟體所使用的)可以複製所選的內容! 並且在其他模式會沒有效果,僅在visual模式下才會有效(詳見上表格)

又或者是想在輸入模式下,輸入jj就會跳回一般模式(雖然並不推薦)。這邊使用的指令是:imap jj <Esc>

使用:map可以查詢到目前所有的mapping,裡面可能會有許多plugin所增加的內容,可能不是我們自己增加的

Image

如果要取消目前的mapping,可以使用:unmap <欲清除map>、nunmap <..>、vunmap <..>、iunmap <..> 來清除已存在的mapping,或是使用:mapclear清除所有自己設定的mapping(不包含plugin的)

tip

為了讓自己使用vim的時候可以減少手指離開鍵盤,可以關掉上下左右的所有功能,這時候就可以使用mapping來關閉

noremap <UP> <NOP>
noremap <DOWN> <NOP>
noremap <LEFT> <NOP>
noremap <RIGHT> <NOP>
inoremap <UP> <NOP>
inoremap <DOWN> <NOP>
inoremap <LEFT> <NOP>
inoremap <RIGHT> <NOP>

可以注意到這邊使用的都是noremap而不是map,nore代表的是no recursive,代表不會循環參照。

避免造成a map到b,b map到c,c又map到a 形成回圈的狀況。

所以只要是需要映射都使用noremap,當然如果要指定模式只要在前面加上n/v/i即可(eg::inoremap X X)

  • noremap、nnoremap、vnoremap、inoremap

如果想要的功能已經被使用了,可以在前面加一個<leader><leader>預設是\,可以透過設定來將<leader>更改成,

設定的方式參考這裡

例如:nnoremap <leader>h j可以將,h變成j(向下),其實效果等同於:nnoremap ,h j,但是也有使用<leader>的好處的

使用<leader>的好處在於,如果之後想要將leader改成別的按鍵可以一次將所有mapping更改完成(有點像是變數的概念

Auto Command (Autocmd)

Autocmd類似JS中的事件監聽(EventListener),可以預先註冊某個自動命令,當符合註冊的情境的時候,會執行後面的內容。

如果要查詢有哪些事件(例如進入window,離開buffer等),可以使用:h autocmd-events

Image

以下利用三個範例來了解自動命令

  1. 切換視窗的時候顯示cursorline
  2. 刪除每行最後多餘的空白
  3. 按下f5之後執行程式

  1. 切換視窗的時候顯示cursorline

    平常我們如果使用vnew開啟一個新的window的時候,通常兩個window都會有cursorline

    如果我們想要只在目前所在的window才顯示cursorline,可以做以下設定

    :autocmd WinEnter * setlocal cursorline
    :autocmd WinLeave * setlocal cursorline

    第一行意思是指說,在進到一個新的視窗(WinEnter)事件發生時,做後面的事情。也就是設定有cursorline。 另外一行是設定離開Window的時候,將目前這個Window的cursorline給取消。

    tip

    setlocal跟set的用法是一樣的,只是差別在setlocal只會在目前所在的window,而不會在其他的window中套用。

  2. 刪除每行最後多餘的空白

    這邊需要搭配正規表達式(Regex)來達到功能

    輸入以下設定即可

    :autocmd BufWritePre * :%s/\s\+$//e

    BufWritePre事件,代表在寫入Buffer之前要做後面的事情。

  3. 按下f5之後執行程式

自訂設定

  1. 按下f5之後重新整理目前的排版
nnoremap <f5> migg<S-v>G='i

設定檔案(~/.vimrc)

設定檔預設會存在在~/.vimrc中。這樣只要之後使用vim的時候會自動去讀取這個.vimrc設定檔案

如果想要讀取其他的設定檔案,可以使用:source <設定檔路徑>這個指令。

在vim設定檔中,如果需要註解,則需使用符號。且在設定檔案中不需使用:

例如需要設定行號只要在.vimrc檔案中加入一行set nu即可

vimrc

基礎設定

設定行號

開啟行號:

  • set number
  • set nu

關閉行號:

  • set nonumber
  • set nonu

設定剪貼簿共用

vim使用的是暫存器,如果要將外部程式剪下的剪貼簿貼在vim編輯器中,需要特別設定共用指令 如果想瞭解更多可以:h clipboard

  • set clipboard=unnamed

設定游標所在處顯示底線

  • set cursorline

設定不要自動產生swap檔案

有時候程式會意外中斷,vim為了避免這種狀況導致檔案丟失,會自動生成一個swap檔案。這時候回去開啟意外中斷的檔案時,vim會發現有一個swap檔,這時候就會詢問你是不是要利用這個swap檔案回覆內容。 雖然這個功能目的是為了解決檔案意外丟失的問題,但是不利於版本控制,可能需要將swap產生的檔案丟到ignore中,如果不小心忽略了這個動作,導致將swap檔案一起丟到網路上,可能會有風險(使用cat指令可以看到swap檔案內容中仍有資訊) 所以這邊選擇關閉swap自動生成檔案

  • set noswapfile

搜尋設定

設定搜尋的時候會有highlight

  • set hlsearch

設定搜尋的時候忽略大小寫差異

  • set ignorecase

我們平常在搜尋的時候,需要使用/ <欲搜尋的字>或是? <欲搜尋的字>來搜尋,但是需要等到輸入完指令才會出現 如果我們開啟漸進式搜尋,只要每多打一個字,就會重新根據目前已經輸入的內容搜尋

  • set incsearch

有開啟漸進式搜尋的話,可以每鍵入一個字就會動態顯示目前搜尋的內容 :set incsearch

沒有開啟漸進式搜尋的搜尋狀況,需要完整輸入完enter之後才會顯示 :set noincsearch

縮排設定

縮排是在寫程式很重要的一個功能,<tab>空白鍵雖然都可以縮排,但是兩者的內容其實不一樣。我們可以透過設定,來更改每次輸入tab會轉換變成空白鍵的數量(還是空白比較統一啦~),或是可以更改>> & <<縮排以及取消縮排的距離(也是空白數量)

設定每次使用>><<所會縮排的距離(visual模式中只需要輸入一次><)即可

這邊設定距離為兩個空白的家離

  • set shiftwidth=2

設定輸入tab會轉化的空白數量

只要開啟此功能,tab就會自動轉化成空白,如果需要輸入真正的tab,則需使用ctrl+V<tab> 這邊設定轉換成2個空白

  • set softtabstop=2

設定將目前的tab都軟化成對應數量的空白

如果已經有設定softtabstop好像就不用再設定這個了,不過不確定還是設定一下比較好,設定完之後需要搭配:retab來將目前已存在的tab重新規劃(成空白)

  • set expandtab

分割視窗設定以及分頁設定

分割視窗設定

設定新的分割視窗預設位置 如果沒有設定,預設:new會分割出新視窗在上方,:vnew會分割出新視窗在左邊 需要加上以下設定來將預設的視窗設定在下方以及右邊

  • set splitbelow
  • set splitright

分頁設定

如果只有一個分頁,則預設是不會顯示分頁視窗。如果在僅有一個分頁(tab)的狀態下也要顯示分頁,就需要設定 可以使用:h showtabline來查詢

  • set showtabline=2

開啟顏色設定&語言辨識縮排外掛等設定

在vim編輯器中編輯不同的語言的時候,有時候會需要讓他偵測不同的語言,這個跟syntax以及filetype有關

打開語法偵測

  • syntax on
  • colorscheme <C-d>來去選擇目前有的顏色風格 (<C-d>代表ctrl+d)
note

有可能在設定colorscheme的時候,不一定每台電腦都有該顏色設定 這時候就可以使用try…catch…endcatch來設定例外狀況

try
colorscheme desert
catch
colorscheme default
endtry

這樣如果電腦有desert這個顏色設定,就會套用。但是當沒有的時候會套用到default這個顏色設定。 (不一定只能設定顏色??? 待查證)

開啟filetype辨識語言

需要另外開啟filetype,否則vim無法辨識目前寫的是哪種語言 可以查詢:h filetype

偵測檔案類型

  • filetype on

根據目前檔案類型進行縮排

  • filetype indent on

自動使用常用外掛

  • filetype plugin on

其他設定

更改預設的<leader>

  • let mapleader = ",”

設定Vi模式

Vi跟Vim其實是不同的,可以設定變成只有Vi的模式

  • 設定成Vim模式(預設):set nocompatible
  • 設定成Vi模式:set compatible

觀看目前所有自訂的設定檔案

  • :set

觀看所有vim有的設定檔

  • :set all

設定座標(目前所在位置)

  • set ruler

自動換行

預設是會自動換行的(但是仍是在同一個行號)

  • set nowrap 取消自動換行
  • set linebreak 可以根據文字長度自動摺行(避免同一個word被拆成兩行顯示)

顯示目前模式

預設是顯示的,也可以關掉

  • set noshowmode

顯示目前指令

預設應該也是顯示的,可以手動關閉

  • set noshowcmd

智慧搜尋嚴格模式

設定搜尋時只要有混合大小寫,強制一定要完全相同(即使已經開啟ignorecase了也是)

  • set smartcase

預先滾動緩衝

設定滾動時不會到最後一行才滾動,會有一小段距離就開始滾動(以3行為例)

  • set scrolloff=3

顯示隱藏字元(e.g:換行符)

  • set list (開啟看到隱藏字)
  • set nolist(關閉看到隱藏字)

設定檔整理

雖然也可以只用~/.vimrc 一個檔案來放設定檔,但是會不好維護。

最簡單的方式是根據內容分別創建好幾個設定檔,接著再在$HOME/.vimrc這支檔案中使用source引入,但是有更好的方式所以這邊只是簡單介紹 e.g:先在$HOME創建一個settings.vim,並在裡面寫上set number等設定 接著再在.vimrc內加入一行source $HOME/settings.vim,則當vim開啟去讀取.vimrc這支設定檔的時候 一行一行讀取,讀到source $HOME/settings.vim這行的時候會去路徑上尋找settings.vim中的內容,並載入.vimrc中 (有點類似css使用link的感覺)

另一種方式是使用vim官方推薦的分類方式!也是我們主要要使用的方式!!

Image

例如說這邊先建立一個colors的資料夾 mkdir colors,接著創建一個mycolor的檔案,雖然以我們目前的能力可能要自己做一個color theme有點困難,但是這邊是要示範只要按照vim所建議的資料夾去規劃,就可以很輕鬆做到管理。

Image

Image

接著進到vim環境中,使用:colorscheme <C-d>就可以看到裡面有一個myColors的配色。

Image

或是建立一個plugin的資料夾mkdir plugin,在這裡面建立一個mySettings.vim的檔案。這樣雖然沒有在.vimrc中引入這個檔案,但是vim預設會去抓取.vim/plugin下的設定。所以這邊的設定仍然會生效。

Image

像是這邊我在mySettings.vim中寫了一個key mapping,就算.vimrc中沒有source到這個檔案,仍然會生效

Image

如果建立一個ftplugin的資料夾mkdir ftplugin,根據文件,這個資料內的檔案會根據目前的檔案是哪種語言去執行對應的內容

如果建立一個myType.vim的話,只要之後檔案類型是myType這種語言(當然這邊是亂打的,沒有這種檔案類型。通常檔案類型會是js,C等等),他會自動執行myType.vim裡面的內容

Image

Image

myType.vim檔案中只有一行,echo代表要回覆後面的文字(類似console.log?)

如果沒辦法判斷是哪個filetype,可以使用:set filetype=xxx來設定檔案類型。

使用上面指令確定完filetype之後,就會顯示myType.vim中設定的內容,也就是回覆指定文字

在ftplugin檔案中建立一個vim.vim檔案,前面的vim代表之後只要副檔名或是檔案類型是vim檔的話,就會執行以下內容

內容中輸入:

Image

接著只要存擋,重新進入vim.vim(vim vim.vim)檔案之後,因為這個檔案的副檔名也是vim,所以就會自動執行剛剛設定的內容

Image

我們還可以使用套件管理工具來協助我們管理套件

以前在使用套件的時候很麻煩,需要將檔案一個一個放到正確的位置。

但是現在我們可以使用套件管理的套件!!這樣管理套件的時候就很簡單了。

這邊推薦三種外掛管理工具

  • VimPlug

https://github.com/junegunn/vim-plug

  • Pathogen

https://github.com/tpope/vim-pathogen

  • Vundle

https://github.com/VundleVim/Vundle.vim

❗我們以下使用VimPlug來操作

套件整理

Vim套件推薦

可以參考Vimawesome這個網站,裡面根據不同用途有很多套件可以參考

VimPlug

首先先在terminal上輸入以下指令(根據官網資料)

    curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Image

跑完之後可以看到以下資訊,代表安裝完成

Image

可以再去check看看,發現多了一個autoload的資料夾。並且裡面有一個已經寫好的plug.vim檔案

(可以在這邊先上傳一個git版本)

Image

接著只要在~/.vim/.vimrc檔案中新增一塊區域,內容照著規定的方式寫。就可以使用:PlugInstall的指令來安裝.vimrc中所有寫的套件

call plug#begin()
//要安裝的套件放這邊
//Plug 'github上從github.com/的後面這邊都要複製'
//e.g: Plug 'ap/vim-css-color'
call plug#end()

接著打開一個新的css檔案(好像預設只有.css會顯示)

Image

可以看到已經有剛剛那個css-color套件的功能了!

Image

也可以看到在.vim下面有一個plugged的資料夾。裡面會有所有已經安裝的套件。

vim-airline

Vim-airline是一個可以下方快速顯示功能區的套件

vimairline.gif

因為已經有下方的狀態列了,所以我們可以將原本的showmode給關掉

Image

第一行將showmode改成noshowmode 第二行則是將下方自行改成有尖角 第五行將上方tab改成有尖角

相關設定可以參考Github頁面內說明

這邊我們統一在.vim/plugin/裡面創建一個該套件名稱的設定檔案

(e.g:如果是vim-airline套件,設定檔名稱就會是vim-airline.vim)

因為是在plugin資料夾內,所以設定檔案會自動生效。

nerdtree

nerdtree可以讓我們在目前的頁面旁邊顯示一個檔案系統,並且可以在裡面新增檔案或更改檔案名稱等等。也可以利用nerdtree創建一個資料夾。是一個必裝的套件!

Image

我們在.vim/plugin/nerdtree.vim設定檔案中,新增上圖右邊的內容

平常我們如果要設定打開nerdtree,需要輸入:NERDTreeToggle的指令,我們設定在normal模式下,使用f2就可以輸入指令並送出,這樣就可以使用f2切換nerdtree的開關了

接著使用官方的方式(第二、三行),當目前的頁面是最後一個的時候,:q離開會連同nerdtree一起關閉

最後一行是設定nerdtree顯示欄位的最精簡模式(避免上方出現一些其他的提示)

nerdtree有其他相關的指令,例如

  • 使用m可以在下方叫出選單 Image 如果輸入m可以在這邊修改檔案名稱,或是輸入a可以新增一個檔案,f可以在finder中顯示,d可以刪除等等
  • I可以顯示隱藏的資料
  • o可以展開資料夾內容
  • u可以退到上一層(也就是cd ..),C可以進到資料夾中

ctrlp

  • ctrlp Github 顧名思義使用的時候就是使用<C-p>,其用途為快速搜尋目前目錄下的檔案,並且快速切換。

這邊需要加上一些設定,讓使用上更符合我們需求

一樣在.vim/plugin/新增一個ctrlp.vim設定檔案,接著在裡面輸入

let g:ctrlp_by_filename = 1
let g:ctrlp_custom_ignore = {
\ 'dir': '\v[\/]\.(git|hg|svn)$|tmp$',
\ 'file': '\v\.(exe|so|dll)$',
\ 'link': 'some_bad_symbolic_links',
\ }

if executable('ag')
set grepprg=ag\ --nogroup\ --nocolor
let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
let g:ctrlp_use_caching = 0
endif

第一行是設定,為了讓我們搜尋出來的目錄依照nerdtree指向的地方為基準,避免搜尋到外面我們不需要的資訊

接著設定忽略掉的資訊(例如dir中我們不需要tmp$ //$代表結尾)的資料夾出現在搜尋畫面中

最後一個設定是可以使用更快的搜尋方式(Silver Searcher)

如果需要使用Silver Searcher則需另外安裝

  • 使用ctrl+d可以搜尋到file name only取代full path search
  • ctrl+p可以呼叫出ctrlp的視窗

Image

官方文件基本操作

emmet

  • vim emmet Github 自動補全的一個套件,在VS Code是內建的功能,但是在vim上面需要額外再安裝

因為最常使用的地方是在html,css當中,如果是在撰寫其他的語言的時候,反而會不希望他自動補全

官方有給出一個建議的設定如下(這邊我們一樣在.vim/plugin/創建一個emmet.vim

Enable just for html/css

// 官方提供的建議
let g:user_emmet_install_global = 0
autocmd FileType html,css EmmetInstall

我們這邊多加了一些設定。除了css以外,我們很常在編輯css以前會有一個scss檔案,這邊也一起加入

並且我們將平常需要輸入指令的方式映射到tab上,讓我們可以利用tab直接展開emmet(原本預設是ctrl+y+,

let g:user_emmet_install_global = 0
autocmd FileType html,css,scss,sass EmmetInstall
autocmd Filetype html,css,scss,sass imap <silent> <expr> <tab> emmet#expandAbbrIntelligent("\<tab>")

Image

我們所做的設定

vim-surround

可以快速的在所選範圍外插入或是修改,,tag等等

這邊需要記幾個指令

先進入visual模式之後,使用S+想要在左右加上的東西,即可自動增加,例如viw+S*

如果不想要先選取,也可以使用ys當作動詞,例如ysiw"

如果已經有符號了,可以使用cs<原符號><欲改符號>來修改,將符號改成新的符號,例如cs”*可以將改成*

當然也可以使用tag

如果需要知道更多可以參考官網,這個套件真的很好用!!

如果要使用.來重複上一個操作,則需安裝另一個套件

vim-snipmate

可以利用少少的指定文字,創建出已經預先設定好的內容。

如果原本內預設的內容不夠,也可以自己新增(例如在使用bootstrap的時候,可以將需要的內容先儲存起來

之後就可以利用bs前綴詞,生出需要的元件等等。

預設儲存的檔案內容會位於plugged/vim-snippets/snippets內,會依照filetype去分類

自己新增的方式是在.vim/下面新增一個snippets的資料夾,並且在裡面根據filetype來設定檔案名稱。

例如想要設定的是html的話,就需要建立一個.vim/snippets/html.snippets檔案,並且在裡面撰寫

撰寫格式如下

snippet <簡寫>
<real-Tab>想要生成的文字

e.g:
snippet justtest
justtest=${1:yaaya},${2:haha},${4:i'm 4th},${3:i'm 3th}

這邊的${1:yaya}代表預設這會是第一個跳到的位置,且預設詞(placeholder)會是yaya,接著會跳到${2}的位置,再來會跳到最後面的${3},最後才是回到第三個的${4}

當在insert模式的時候,可以使用<C-r><Tab>來查看有哪些snippets可以使用

並且使用<C-n>&<C-p>來切換

vimsnipmate

i進入insert mode,type ab,ctrl+r+tab叫出視窗顯示有哪些snippets可以使用,ctrl+n下一個,ctrl+p上一個,shift+n設定展開snippets,再按一次shift+n跳到下一個placeholder的位置

tagbar

  • tagbar Github 可以快速查看目前可以使用的方法(不太會用…之後再看看)

寫了一個tagbar.vim的設定檔案,並將f3映射到開啟tagbar功能

ack

可以快速查詢目前檔案的內容(支援ag)

在ack.vim設定檔案中,設定了如果可以使用ag查詢就用ag查詢

並且設定一個mapping讓我們可以使用FF開啟ack搜尋

vim-indent-guide

生成輔助線,讓我們可以方便看html的層級

手動設定顏色(關閉自動顏色設定)let g:indent_guides_auto_colors = 0

既然已經設定關閉自動顏色設定,就要手動自己指定。在裡面新增以下內容

autocmd VimEnter,Colorscheme * :hi IndentGuidesOdd   ctermbg=176
autocmd VimEnter,Colorscheme * :hi IndentGuidesEven ctermbg=56

Image

將indent guides設定成預設打開let g:indent_guides_enable_on_vim_startup = 1

做一個key mapping讓我們可以使用f2就切換是否打開功能nnoremap <f1> :IndentGuidesToggle<Enter>

設定寬度為一個字元let g:indent_guides_guide_size = 1

其他設定可以使用:h indent-guide查詢

改變自訂顏色

先提供三個別人已經設定好的顏色設定檔案,需要將檔案加入到.vim/colors的資料夾內

也可以自己手動去更改顏色,如下影片

高見龍老師的影片

其他參考資料

map(vimcn簡體中文)資料