快速修正(Quickfix)

Nvim 的 :help 頁面,從 原始碼 使用 tree-sitter-vimdoc 解析器產生


本主題在使用者手冊的 30.1 節中介紹。

1. 使用快速修正命令 Quickfix E42

Vim 有一種特殊模式可以加速編輯-編譯-編輯的循環。這是受到 Amiga 上 Manx 的 Aztec C 編譯器的快速修正選項的啟發。其想法是將編譯器的錯誤訊息儲存在一個檔案中,並使用 Vim 一個接一個地跳到錯誤。您可以檢查每個問題並修正它,而無需記住所有錯誤訊息。
在 Vim 中,快速修正命令更廣泛地用於在檔案中尋找位置列表。例如,:vimgrep 尋找模式匹配。您可以使用 getqflist() 函數在腳本中使用這些位置。因此,您可以做的不僅僅是編輯/編譯/修正的循環!
如果您的錯誤訊息在檔案中,您可以使用以下命令啟動 Vim
vim -q filename
在 Vim 內部,執行命令並處理輸出的簡單方法是使用 :make 命令(見下文)。
應設定 'errorformat' 選項以匹配您的編譯器產生的錯誤訊息(請參閱下文的 errorformat)。
快速修正 ID(quickfix-ID)
每個快速修正列表都有一個唯一的識別碼,稱為快速修正 ID,此數字在 Vim 會話中不會更改。getqflist() 函數可用於取得分配給列表的識別碼。還有一個快速修正列表編號,每當向快速修正堆疊新增十個以上的列表時,該編號可能會更改。
位置列表(location-list) E776 位置列表是一個視窗本地的快速修正列表。您會在 :lvimgrep:lgrep:lhelpgrep:lmake 等命令後得到一個位置列表,這些命令會建立位置列表而不是像對應的 :vimgrep:grep:helpgrep:make 一樣建立快速修正列表。location-list-file-window
位置列表與一個視窗相關聯,每個視窗都可以有單獨的位置列表。一個位置列表只能與一個視窗相關聯。位置列表獨立於快速修正列表。
當分割一個具有位置列表的視窗時,新視窗會得到位置列表的副本。當不再有任何對位置列表的參考時,該位置列表將被銷毀。
快速修正變更計數(quickfix-changedtick)
每個快速修正和位置列表都有一個唯讀的變更計數變數,用於追蹤對列表所做的變更總數。每次修改快速修正列表時,此計數都會遞增。這可以用於僅在列表已變更時才執行動作。getqflist()getloclist() 函數可用於查詢變更計數的目前值。您無法變更變更計數變數。
可以使用以下快速修正命令。位置列表命令與快速修正命令類似,只是將快速修正命令中的 'c' 字首替換為 'l'。
E924
如果在處理位置列表命令時,目前視窗被 autocommand 關閉,則該命令將被中止。
E925 E926 如果在處理快速修正或位置列表命令時,目前的快速修正或位置列表被 autocommand 變更,則該命令將被中止。
:cc
:cc[!] [nr] 顯示錯誤 [nr]。如果省略 [nr],則會再次顯示相同的 :[nr]cc[!] 錯誤。當跳轉到另一個緩衝區、目前緩衝區已變更、該緩衝區只有一個視窗且 'hidden''autowrite' 都關閉時,不使用 [!] 則無法運作。當使用 [!] 跳轉到另一個緩衝區時,目前緩衝區的任何變更都會遺失,除非設定了 'hidden' 或該緩衝區有另一個視窗。當跳轉到緩衝區時,會遵守 'switchbuf' 設定。在快速修正視窗中使用時,可以使用行號,包括 "." 代表目前行和 "$" 代表最後一行。
:ll
:ll[!] [nr] 與 ":cc" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cn :cne :cnext E553 ]q :[count]cn[ext][!] 顯示列表中包含檔案名稱的下一個 [count] 個錯誤。如果根本沒有檔案名稱,則跳到下一個 [count] 個錯誤。有關 [!] 和 'switchbuf',請參閱 :cc
:lne :lnext ]l :[count]lne[xt][!] 與 ":cnext" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:[count]cN[ext][!] :cp :cprevious :cprev :cN :cNext [q :[count]cp[revious][!] 顯示列表中包含檔案名稱的上一個 [count] 個錯誤。如果根本沒有檔案名稱,則跳到上一個 [count] 個錯誤。有關 [!] 和 'switchbuf',請參閱 :cc
:[count]lN[ext][!] :lp :lprevious :lprev :lN :lNext [l :[count]lp[revious][!] 與 ":cNext" 和 ":cprevious" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cabo :cabove :[count]cabo[ve] 跳到目前緩衝區中目前行以上的第 [count] 個錯誤。如果省略 [count],則使用 1。如果沒有錯誤,則會顯示錯誤訊息。假設快速修正列表中的項目按其緩衝區編號和行號排序。如果同一行有多個錯誤,則只使用第一個項目。如果 [count] 超過目前行以上項目數,則會選擇檔案中的第一個錯誤。
:lab :labove :[count]lab[ove] 與 ":cabove" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cbel :cbelow :[count]cbel[ow] 跳到目前緩衝區中目前行以下的第 [count] 個錯誤。如果省略 [count],則使用 1。如果沒有錯誤,則會顯示錯誤訊息。假設快速修正列表中的項目按其緩衝區編號和行號排序。如果同一行有多個錯誤,則只使用第一個項目。如果 [count] 超過目前行以下項目數,則會選擇檔案中的最後一個錯誤。
:lbel :lbelow :[count]lbel[ow] 與 ":cbelow" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cbe :cbefore :[count]cbe[fore] 跳到目前緩衝區中目前游標位置之前的第 [count] 個錯誤。如果省略 [count],則使用 1。如果沒有錯誤,則會顯示錯誤訊息。假設快速修正列表中的項目按其緩衝區、行和欄號排序。如果 [count] 超過目前位置之前項目數,則會選擇檔案中的第一個錯誤。
:lbe :lbefore :[count]lbe[fore] 與 ":cbefore" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:caf :cafter :[count]caf[ter] 跳到目前緩衝區中目前游標位置之後的第 [count] 個錯誤。如果省略 [count],則使用 1。如果沒有錯誤,則會顯示錯誤訊息。假設快速修正列表中的項目按其緩衝區、行和欄號排序。如果 [count] 超過目前位置之後項目數,則會選擇檔案中的最後一個錯誤。
:laf :lafter :[count]laf[ter] 與 ":cafter" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cnf :cnfile ]CTRL-Q :[count]cnf[ile][!] 顯示列表中包含檔案名稱的下一個 [count] 個檔案中的第一個錯誤。如果根本沒有檔案名稱或沒有下一個檔案,則跳到下一個 [count] 個錯誤。有關 [!] 和 'switchbuf',請參閱 :cc
:lnf :lnfile ]CTRL-L :[count]lnf[ile][!] 與 ":cnfile" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:[count]cNf[ile][!] :cpf :cpfile :cNf :cNfile [CTRL-Q :[count]cpf[ile][!] 顯示列表中包含檔案名稱的上一個 [count] 個檔案中的最後一個錯誤。如果根本沒有檔案名稱或沒有下一個檔案,則跳到上一個 [count] 個錯誤。有關 [!] 和 'switchbuf',請參閱 :cc
:[count]lNf[ile][!] :lpf :lpfile :lNf :lNfile [CTRL-L :[count]lpf[ile][!] 與 ":cNfile" 和 ":cpfile" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:crewind :cr [Q :cr[ewind][!] [nr] 顯示錯誤 [nr]。如果省略 [nr],則會顯示第一個錯誤。請參閱 :cc
:lrewind :lr [L :lr[ewind][!] [nr] 與 ":crewind" 相同,只是使用目前視窗的位置列表代替快速修正列表。
:cfirst :cfir :cfir[st][!] [nr] 與 ":crewind" 相同。
:lfirst :lfir :lfir[st][!] [nr] 與 ":lrewind" 相同。
:clast :cla ]Q :cla[st][!] [nr] 顯示錯誤 [nr]。如果省略 [nr],則顯示最後一個錯誤。請參閱 :cc
:llast :lla ]L :lla[st][!] [nr] 與 ":clast" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cq :cquit :cq[uit][!] :{N}cq[uit][!] :cq[uit][!] {N} 以錯誤代碼 {N} 結束 Vim。{N} 預設為 1。當 Vim 從另一個程式呼叫時很有用:例如,編譯器不會再次編譯相同的文件,git commit 將中止提交過程,fc (像是 bash 和 zsh 的內建 shell 命令)將不會執行該命令等等。{N} 也可以是零,在這種情況下,Vim 會正常退出。警告:所有檔案的變更都會遺失。它的作用類似於 ":qall!" :qall,除了 Nvim 會以非零或 [count] 退出。
:cf :cfi :cfile :cf[ile][!] [errorfile] 讀取錯誤檔案並跳至第一個錯誤。當 Vim 以 -q 選項啟動時,會自動執行此操作。您可以在編譯時保持 Vim 運行時使用此命令。如果您給定錯誤檔案的名稱,則 'errorfile' 選項將設定為 [errorfile]。有關 [!],請參閱 :cc。如果錯誤檔案的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:lf :lfi :lfile :lf[ile][!] [errorfile] 與 ":cfile" 相同,但使用目前視窗的位置列表,而不是快速修復列表。您不能使用 -q 命令列選項來設定位置列表。
:cg[etfile] [errorfile] :cg :cgetfile 讀取錯誤檔案。與 ":cfile" 相同,但不跳至第一個錯誤。如果錯誤檔案的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:lg[etfile] [errorfile] :lg :lge :lgetfile 與 ":cgetfile" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:caddf :caddfile :caddf[ile] [errorfile] 讀取錯誤檔案,並將錯誤檔案中的錯誤新增至目前的快速修復列表。如果沒有快速修復列表,則會建立一個新的列表。如果錯誤檔案的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:laddf :laddfile :laddf[ile] [errorfile] 與 ":caddfile" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cb :cbuffer E681 :[range]cb[uffer][!] [bufnr] 從目前緩衝區讀取錯誤列表。當給定 [bufnr] 時,它必須是已載入緩衝區的編號。然後將使用該緩衝區,而不是目前的緩衝區。可以指定要使用的行範圍。否則,將使用緩衝區中的所有行。有關 [!],請參閱 :cc
:lb :lbuffer :[range]lb[uffer][!] [bufnr] 與 ":cbuffer" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cgetb :cgetbuffer :[range]cgetb[uffer] [bufnr] 從目前緩衝區讀取錯誤列表。與 ":cbuffer" 相同,但不跳至第一個錯誤。
:lgetb :lgetbuffer :[range]lgetb[uffer] [bufnr] 與 ":cgetbuffer" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cad :cadd :caddbuffer :[range]cad[dbuffer] [bufnr] 從目前緩衝區讀取錯誤列表,並將錯誤新增至目前的快速修復列表。如果沒有快速修復列表,則會建立一個新的列表。否則,與 ":cbuffer" 相同。
:laddb :laddbuffer :[range]laddb[uffer] [bufnr] 與 ":caddbuffer" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cex :cexpr E777 :cex[pr][!] {expr} 使用 {expr} 的結果建立快速修復列表,並跳至第一個錯誤。如果 {expr} 是字串,則字串中以換行符號終止的每一行都會使用 'errorformat' 的全域值進行處理,並將結果新增至快速修復列表。如果 {expr} 是列表,則會處理列表中每個字串項目,並將其新增至快速修復列表。會忽略列表中非字串的項目。有關 [!],請參閱 :cc。範例
:cexpr system('grep -n xyz *')
:cexpr getline(1, '$')
:lex :lexpr :lex[pr][!] {expr}:cexpr 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cgete :cgetexpr :cgete[xpr] {expr} 使用 {expr} 的結果建立快速修復列表。與 :cexpr 相同,但不跳至第一個錯誤。
:lgete :lgetexpr :lgete[xpr] {expr}:cgetexpr 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cadde :caddexpr :cadde[xpr] {expr} 評估 {expr} 並將結果行新增至目前的快速修復列表。如果沒有快速修復列表,則會建立一個新的列表。目前的游標位置不會變更。有關更多資訊,請參閱 :cexpr。範例
:g/mypattern/caddexpr expand("%") .. ":" .. line(".") ..  ":" .. getline(".")
:lad :addd :laddexpr :lad[dexpr] {expr} 與 ":caddexpr" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cl :clist :cl[ist] [from] [, [to]] 列出所有有效的 quickfix-valid 錯誤。如果給定數字 [from] 和/或 [to],則會列出對應的錯誤範圍。負數從最後一個錯誤向後計算,-1 是最後一個錯誤。:filter 命令可用於僅顯示符合提供的模式的快速修復項目。該模式會與項目的檔案名稱、模組名稱、模式和文字進行比對。
:cl[ist] +{count} 列出目前和接下來 {count} 個有效的錯誤。這類似於 ":clist from from+count",其中 "from" 是目前的錯誤位置。
:cl[ist]! [from] [, [to]] 列出所有錯誤。
:cl[ist]! +{count} 列出目前和接下來 {count} 個錯誤行。這對於查看目前行之後無法識別的行很有用。例如,如果 ":clist" 顯示
8384 testje.java:252: error: cannot find symbol
然後使用 ":cl! +3" 顯示原因
8384 testje.java:252: error: cannot find symbol
8385: ZexitCode = Fmainx();
8386: ^
8387: symbol: method Fmainx()
:lli[st] [from] [, [to]] :lli :llist 與 ":clist" 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:lli[st]! [from] [, [to]] 列出目前視窗位置列表中的所有項目。
如果您插入或刪除行,由於使用了隱藏的標記,大多數情況下仍然可以找到正確的錯誤位置。有時,當標記因某種原因被刪除時,會顯示訊息「行已變更」,以警告您錯誤位置可能不正確。如果您退出 Vim 並重新啟動,則標記會遺失,且錯誤位置可能不再正確。
有兩個自動命令可用於在執行快速修復命令(':make'、':grep' 等)之前和之後執行命令。有關詳細資訊,請參閱 QuickFixCmdPreQuickFixCmdPost
QuickFixCmdPost 範例
'encoding' 與地區設定不同時,錯誤訊息的編碼可能與 Vim 使用的編碼不同。若要轉換訊息,您可以使用此程式碼
function QfMakeConv()
   let qflist = getqflist()
   for i in qflist
      let i.text = iconv(i.text, "cp936", "utf-8")
   endfor
   call setqflist(qflist)
endfunction
au QuickfixCmdPost make call QfMakeConv()
另一個選項是使用 'makeencoding'
quickfix-title
每個快速修復和位置列表都有標題。預設情況下,標題設定為建立列表的命令。getqflist()getloclist() 函數可用於分別取得快速修復和位置列表的標題。setqflist()setloclist() 函數可用於分別修改快速修復和位置列表的標題。範例
call setqflist([], 'a', {'title' : 'Cmd output'})
echo getqflist({'title' : 1})
call setloclist(3, [], 'a', {'title' : 'Cmd output'})
echo getloclist(3, {'title' : 1})
quickfix-index
當您使用任何快速修復命令(例如 :cc:cnext:cprev 等)跳至快速修復/位置列表項目時,該項目會成為目前選取的項目。可以使用 getqflist()/getloclist() 函數取得快速修復/位置列表中目前選取項目的索引。範例
echo getqflist({'idx' : 0}).idx
echo getqflist({'id' : qfid, 'idx' : 0}).idx
echo getloclist(2, {'idx' : 0}).idx
對於新的快速修復列表,會選取第一個項目,且索引為 1。可以使用 setqflist() 函數將任何快速修復/位置列表中的任何項目設定為目前選取的項目。範例
call setqflist([], 'a', {'idx' : 12})
call setqflist([], 'a', {'id' : qfid, 'idx' : 7})
call setloclist(1, [], 'a', {'idx' : 7})
quickfix-size
您可以使用 getqflist()getloclist() 函數分別取得快速修復和位置列表中的項目數(大小)。範例
echo getqflist({'size' : 1})
echo getloclist(5, {'size' : 1})
quickfix-context
任何 Vim 類型都可以作為上下文與快速修正或位置列表相關聯。 setqflist()setloclist() 函數可用於將上下文分別與快速修正和位置列表相關聯。 getqflist()getloclist() 函數可用於分別檢索快速修正和位置列表的上下文。這對於處理多個快速修正/位置列表的 Vim 外掛非常有用。範例
let somectx = {'name' : 'Vim', 'type' : 'Editor'}
call setqflist([], 'a', {'context' : somectx})
echo getqflist({'context' : 1})
let newctx = ['red', 'green', 'blue']
call setloclist(2, [], 'a', {'id' : qfid, 'context' : newctx})
echo getloclist(2, {'id' : qfid, 'context' : 1})
快速修正解析
您可以使用 'errorformat' 解析行列表,而無需使用 getqflist() 函數建立或修改快速修正列表。範例
echo getqflist({'lines' : ["F1:10:Line10", "F2:20:Line20"]})
echo getqflist({'lines' : systemlist('grep -Hn quickfix *')})
這會返回一個字典,其中 "items" 鍵包含從行解析的快速修正條目列表。以下展示如何使用自訂的 'errorformat' 來解析行,而無需修改 'errorformat' 選項
echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})
在快速修正或位置列表中的所有緩衝區中執行命令: :cdo
:cdo[!] {cmd} 在快速修正列表中的每個有效條目中執行 {cmd}。它的工作方式如下
:cfirst
:{cmd}
:cnext
:{cmd}
etc.
當目前檔案無法 放棄 且未出現 [!] 時,命令會失敗。當前往下一個條目失敗時,執行會停止。最後一個緩衝區(或發生錯誤的地方)會變成目前的緩衝區。{cmd} 可以包含 '|' 來串聯多個命令。
僅使用快速修正列表中的有效條目。可以使用範圍來選取條目,例如
:10,$cdo cmd
跳過條目 1 到 9。
注意: 當此命令執行時,Syntax 自動命令事件會透過將其新增至 'eventignore' 來停用。這會大幅加速編輯每個緩衝區的速度。另請參閱 :bufdo:tabdo:argdo:windo:ldo:cfdo:lfdo
:cfdo
:cfdo[!] {cmd} 在快速修正列表中的每個檔案中執行 {cmd}。它的工作方式如下
:cfirst
:{cmd}
:cnfile
:{cmd}
etc.
否則其工作方式與 :cdo 相同。
:ldo
:ld[o][!] {cmd} 在目前視窗的位置列表中的每個有效條目中執行 {cmd}。它的工作方式如下
:lfirst
:{cmd}
:lnext
:{cmd}
etc.
僅使用位置列表中的有效條目。否則其工作方式與 :cdo 相同。
:lfdo
:lfdo[!] {cmd} 在目前視窗的位置列表中的每個檔案中執行 {cmd}。它的工作方式如下
:lfirst
:{cmd}
:lnfile
:{cmd}
etc.
否則其工作方式與 :ldo 相同。
篩選快速修正或位置列表: cfilter-plugin :Cfilter :Lfilter 如果您的快速修正列表中有太多條目,您可以使用 cfilter 外掛程式來減少條目數量。使用以下方式載入外掛程式
packadd cfilter
然後您可以使用以下命令來篩選快速修正/位置列表
:Cfilter[!] /{pat}/
:Lfilter[!] /{pat}/
:Cfilter 命令會從目前快速修正列表中與 {pat} 相符的條目建立新的快速修正列表。{pat} 是 Vim 正規表示式 模式。檔案名稱和條目的文字都會與 {pat} 比對。如果提供了可選的 !,則會使用與 {pat} 不符的條目。模式可以選擇性地使用以下其中一個字元括起來:'、"、/。如果模式為空,則會使用上次使用的搜尋模式。
:Lfilter 命令的功能與 :Cfilter 相同,但會在目前的位置列表上操作。
這些命令不會修改目前的快速修正/位置列表,因此您可以使用 :colder/|:lolder| 命令返回未篩選的列表。

2. 錯誤視窗 quickfix-window

:cope :copen w:quickfix_title :cope[n] [height] 開啟一個視窗以顯示目前的錯誤列表。
當提供 [height] 時,視窗會變為該高度(如果有空間)。當省略 [height] 時,視窗會設為十行高。
如果已經有快速修正視窗,則會使其成為目前的視窗。無法開啟第二個快速修正視窗。如果提供 [height],則現有視窗會調整為該大小。
快速修正緩衝區
視窗會包含一個特殊的緩衝區,其中 'buftype' 等於 "quickfix"。請勿變更此設定!視窗會設定 w:quickfix_title 變數,該變數會指出產生快速修正列表的命令。如果 'statusline' 的值經過適當調整,則可以使用此變數來組合自訂狀態列。每當此緩衝區被快速修正命令或函數修改時,b:changedtick 變數就會遞增。您可以使用 getqflist() 和 getloclist() 函數,透過傳遞 "qfbufnr" 項目來取得此緩衝區的編號。對於位置列表,當移除位置列表時,此緩衝區會被清除。
:lop :lopen :lop[en] [height] 開啟一個視窗以顯示目前視窗的位置列表。僅當目前視窗存在位置列表時才有效。您可以一次開啟多個位置視窗。否則,其行為與 ":copen" 相同。
:ccl :cclose :ccl[ose] 關閉快速修正視窗。
:lcl :lclose :lcl[ose] 關閉顯示目前視窗位置列表的視窗。
:cw :cwindow :cw[indow] [height] 當有已辨識的錯誤時,開啟快速修正視窗。如果視窗已開啟且沒有已辨識的錯誤,則關閉視窗。
:lw :lwindow :lw[indow] [height] 與 ":cwindow" 相同,但使用顯示目前視窗位置列表的視窗。
:cbo :cbottom :cbo[ttom] 將游標放在快速修正視窗的最後一行,並捲動使其可見。當由非同步回呼新增錯誤時,這很有用。如果有很多更新要避免大量重繪,請僅偶爾呼叫它。
:lbo :lbottom :lbo[ttom] 與 ":cbottom" 相同,但使用顯示目前視窗位置列表的視窗。
通常,快速修正視窗位於螢幕底部。如果有垂直分割,則位於最右側的視窗欄底部。若要使其始終佔據完整寬度
:botright cwindow
您可以使用 視窗移動 命令來移動視窗。例如,若要將其移至頂部:CTRL-W K。會設定 'winfixheight' 選項,這表示視窗大多會保持其高度,而忽略 'winheight''equalalways'。您可以手動變更高度(例如,透過使用滑鼠拖曳其上方的狀態列)。
在快速修正視窗中,每一行都是一個錯誤。行號等於錯誤編號。目前的條目會以 QuickFixLine 反白顯示。您可以變更其外觀,例如
:hi QuickFixLine ctermbg=Yellow guibg=Yellow
您可以使用 ":.cc" 跳至游標下的錯誤。按下 <Enter> 鍵或在行上按兩下滑鼠會產生相同的效果。包含錯誤的檔案會在快速修正視窗上方的視窗中開啟。如果該檔案已經有一個視窗,則會改用該視窗。如果所使用視窗中的緩衝區已變更,且錯誤位於另一個檔案中,則跳至錯誤會失敗。您必須先確定視窗包含可以放棄的緩衝區。
當您從快速修正視窗中選取檔案時,會使用以下步驟來尋找用於編輯檔案的視窗
1. 如果目前的索引標籤頁面中存在顯示所選檔案的視窗(從快速修正視窗之前的視窗開始),則會使用該視窗。2. 如果上述步驟失敗,且如果 'switchbuf' 包含 "usetab",且任何一個索引標籤頁面中存在顯示所選檔案的視窗(從第一個索引標籤頁面開始),則會使用該視窗。3. 如果上述步驟失敗,則會使用目前索引標籤頁面中顯示 'buftype' 未設定的緩衝區的視窗(從快速修正視窗之前的視窗開始)。4. 如果上述步驟失敗,且如果 'switchbuf' 包含 "uselast",則會使用先前存取的視窗。5. 如果上述步驟失敗,則會使用快速修正視窗之前的視窗。如果沒有先前的視窗,則會使用快速修正視窗之後的視窗。6. 如果上述步驟失敗,則會使用快速修正視窗上方新的水平分割視窗。
CTRL-W_<Enter> CTRL-W_<CR> 您可以使用 CTRL-W <Enter> 開啟新視窗並跳至其中的錯誤。
填寫快速修正視窗後,會觸發兩個自動命令事件。首先,'filetype' 選項會設定為 "qf",這會觸發 FileType 事件(另請參閱 qf.vim)。然後會觸發 BufReadPost 事件,使用 "quickfix" 作為緩衝區名稱。這可以用於對列出的錯誤執行一些動作。範例
au BufReadPost quickfix  setlocal modifiable
        \ | silent exe 'g/^/s//\=line(".") .. " "/'
        \ | setlocal nomodifiable
這會在每行前面加上行號。請注意 ":s" 命令的取代字串中使用 "\=",這用於評估運算式。也會觸發 BufWinEnter 事件,同樣使用 "quickfix" 作為緩衝區名稱。
注意: 當新增至現有的快速修正列表時,不會觸發自動命令。
注意:在快速修復視窗中進行變更不會影響錯誤列表。'modifiable' 選項已關閉以避免進行變更。如果您還是刪除或插入行,文字與錯誤編號之間的關係將會錯亂。如果您真的想這樣做,您可以將快速修復視窗的內容寫入檔案,並使用 ":cfile" 來解析並將其用作新的錯誤列表。
位置列表視窗
位置列表視窗會顯示位置列表中的條目。當您開啟位置列表視窗時,它會在目前視窗下方建立,並顯示目前視窗的位置列表。位置列表視窗與快速修復視窗類似,但您可以同時開啟多個位置列表視窗。當您在此視窗中使用位置列表命令時,將會使用顯示的位置列表。
當您從位置列表視窗中選取檔案時,會使用以下步驟來尋找編輯該檔案的視窗
1. 如果目前索引標籤頁中存在與位置列表相關聯的非快速修復視窗,則會使用該視窗。2. 如果上述步驟失敗,且該檔案已在目前索引標籤頁中的另一個視窗中開啟,則會使用該視窗。3. 如果上述步驟失敗,且 'switchbuf' 包含 "usetab",且該檔案在任何一個索引標籤頁的視窗中開啟,則會使用該視窗。4. 如果上述步驟失敗,則會使用目前索引標籤頁中顯示 'buftype' 未設定的緩衝區的視窗。5. 如果上述步驟失敗,則會在新的視窗中編輯該檔案。
在上述所有情況下,如果尚未設定選取視窗的位置列表,則會將其設定為位置列表視窗中顯示的位置列表。
快速修復視窗 ID
您可以使用 getqflist()getloclist() 函式分別取得快速修復視窗和位置列表視窗的視窗 ID(如果存在)。範例
echo getqflist({'winid' : 1}).winid
echo getloclist(2, {'winid' : 1}).winid
getqflist 範例
getqflist()getloclist() 函式可用於取得快速修復和位置列表的各種屬性。以下是一些使用這些函式的範例
" get the title of the current quickfix list
:echo getqflist({'title' : 0}).title
" get the identifier of the current quickfix list
:let qfid = getqflist({'id' : 0}).id
" get the identifier of the fourth quickfix list in the stack
:let qfid = getqflist({'nr' : 4, 'id' : 0}).id
" check whether a quickfix list with a specific identifier exists
:if getqflist({'id' : qfid}).id == qfid
" get the index of the current quickfix list in the stack
:let qfnum = getqflist({'nr' : 0}).nr
" get the items of a quickfix list specified by an identifier
:echo getqflist({'id' : qfid, 'items' : 0}).items
" get the number of entries in a quickfix list specified by an id
:echo getqflist({'id' : qfid, 'size' : 0}).size
" get the context of the third quickfix list in the stack
:echo getqflist({'nr' : 3, 'context' : 0}).context
" get the number of quickfix lists in the stack
:echo getqflist({'nr' : '$'}).nr
" get the number of times the current quickfix list is changed
:echo getqflist({'changedtick' : 0}).changedtick
" get the current entry in a quickfix list specified by an identifier
:echo getqflist({'id' : qfid, 'idx' : 0}).idx
" get all the quickfix list attributes using an identifier
:echo getqflist({'id' : qfid, 'all' : 0})
" parse text from a List of lines and return a quickfix list
:let myList = ["a.java:10:L10", "b.java:20:L20"]
:echo getqflist({'lines' : myList}).items
" parse text using a custom 'efm' and return a quickfix list
:echo getqflist({'lines' : ['a.c#10#Line 10'], 'efm':'%f#%l#%m'}).items
" get the quickfix list window id
:echo getqflist({'winid' : 0}).winid
" get the quickfix list window buffer number
:echo getqflist({'qfbufnr' : 0}).qfbufnr
" get the context of the current location list
:echo getloclist(0, {'context' : 0}).context
" get the location list window id of the third window
:echo getloclist(3, {'winid' : 0}).winid
" get the location list window buffer number of the third window
:echo getloclist(3, {'qfbufnr' : 0}).qfbufnr
" get the file window id of a location list window (winnr: 4)
:echo getloclist(4, {'filewinid' : 0}).filewinid
setqflist 範例
setqflist()setloclist() 函式可用於設定快速修復和位置列表的各種屬性。以下是一些使用這些函式的範例
" create an empty quickfix list with a title and a context
:let t = 'Search results'
:let c = {'cmd' : 'grep'}
:call setqflist([], ' ', {'title' : t, 'context' : c})
" set the title of the current quickfix list
:call setqflist([], 'a', {'title' : 'Mytitle'})
" change the current entry in the list specified by an identifier
:call setqflist([], 'a', {'id' : qfid, 'idx' : 10})
" set the context of a quickfix list specified by an identifier
:call setqflist([], 'a', {'id' : qfid, 'context' : {'val' : 100}})
" create a new quickfix list from a command output
:call setqflist([], ' ', {'lines' : systemlist('grep -Hn main *.c')})
" parse text using a custom efm and add to a particular quickfix list
:call setqflist([], 'a', {'id' : qfid,
            \ 'lines' : ["a.c#10#L10", "b.c#20#L20"], 'efm':'%f#%l#%m'})
" add items to the quickfix list specified by an identifier
:let newItems = [{'filename' : 'a.txt', 'lnum' : 10, 'text' : "Apple"},
                \ {'filename' : 'b.txt', 'lnum' : 20, 'text' : "Orange"}]
:call setqflist([], 'a', {'id' : qfid, 'items' : newItems})
" empty a quickfix list specified by an identifier
:call setqflist([], 'r', {'id' : qfid, 'items' : []})
" free all the quickfix lists in the stack
:call setqflist([], 'f')
" set the title of the fourth quickfix list
:call setqflist([], 'a', {'nr' : 4, 'title' : 'SomeTitle'})
" create a new quickfix list at the end of the stack
:call setqflist([], ' ', {'nr' : '$',
                    \ 'lines' : systemlist('grep -Hn class *.java')})
" create a new location list from a command output
:call setloclist(0, [], ' ', {'lines' : systemlist('grep -Hn main *.c')})
" replace the location list entries for the third window
:call setloclist(3, [], 'r', {'items' : newItems})

3. 使用多個錯誤列表 quickfix-error-lists

到目前為止,都假設只有一個錯誤列表。實際上,會記住最後使用的十個列表。當開始新的列表時,會自動保留先前的列表。可以使用兩個命令來存取較舊的錯誤列表。它們會將現有的錯誤列表之一設定為目前的列表。
:colder :col E380 :col[der] [count] 前往較舊的錯誤列表。當給定 [count] 時,執行此操作 [count] 次。當已經在最舊的錯誤列表時,會顯示錯誤訊息。
:lolder :lol :lol[der] [count] 與 :colder 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:cnewer :cnew E381 :cnew[er] [count] 前往較新的錯誤列表。當給定 [count] 時,執行此操作 [count] 次。當已經在最新的錯誤列表時,會顯示錯誤訊息。
:lnewer :lnew :lnew[er] [count] 與 :cnewer 相同,但使用目前視窗的位置列表,而不是快速修復列表。
:chistory :chi :[count]chi[story] 顯示錯誤列表的列表。目前的列表會以 ">" 標記。輸出看起來像這樣
  error list 1 of 3; 43 errors   :make
> error list 2 of 3; 0 errors    :helpgrep tag
  error list 3 of 3; 15 errors   :grep ex_help *.c
當給定 [count] 時,則將 count'th 快速修復列表設為目前的列表。範例
" Make the 4th quickfix list current
:4chistory
:lhistory :lhi :[count]lhi[story] 顯示位置列表的列表,否則與 :chistory 類似。
當新增新的錯誤列表時,它會變成目前的列表。
當使用 ":colder" 且使用 ":make" 或 ":grep" 新增新的錯誤列表時,會覆寫一個較新的列表。如果您使用 ":grep" grep 瀏覽,這會特別有用。如果您想要保留較新的錯誤列表,請先使用 ":cnewer 99"。
若要取得快速修復和位置列表堆疊中的列表數,您可以使用 getqflist()getloclist() 函式,並將列表編號設定為特殊值 '$'。範例
echo getqflist({'nr' : '$'}).nr
echo getloclist(3, {'nr' : '$'}).nr
若要取得堆疊中目前列表的編號
echo getqflist({'nr' : 0}).nr

4. 使用 :make :make_makeprg

:mak :make :mak[e][!] [arguments] 1. 執行所有相關的 QuickFixCmdPre 自動命令。2. 如果 'autowrite' 選項開啟,則寫入任何已變更的緩衝區。3. 從 'makeef' 產生錯誤檔案名稱。如果 'makeef' 未包含 "##",且已存在具有此名稱的檔案,則會刪除該檔案。4. 使用 'makeprg' 選項給定的程式啟動(預設為 "make"),並使用選用的 [arguments],且輸出會儲存到錯誤檔案中(對於 Unix,也會在螢幕上回顯)。5. 使用 'errorformat' 讀取錯誤檔案。6. 執行所有相關的 QuickFixCmdPost 自動命令。請參閱以下範例。7. 如果未給定 [!],則會跳到第一個錯誤。8. 刪除錯誤檔案。9. 您現在可以使用 :cnext:cprevious 等命令來瀏覽錯誤,請參閱上方。此命令不接受註解,任何 " 字元都被視為引數的一部分。如果程式輸出的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:lmak :lmake :lmak[e][!] [arguments] 與 ":make" 相同,但會使用目前視窗的位置列表,而不是快速修復列表。
":make" 命令會執行 'makeprg' 選項給定的命令。這是藉由將命令傳遞給 'shell' 選項給定的 Shell 來完成的。這幾乎與輸入以下內容相同
":!{makeprg} [arguments] {shellpipe} {errorfile}"。
{makeprg}'makeprg' 選項給定的字串。可以使用任何命令,而不僅限於 "make"。字元 '%' 和 '#' 會像在命令列上一樣展開。您可以使用 "%<" 來插入不含副檔名的目前檔案名稱,或使用 "#<" 來插入不含副檔名的替代檔案名稱,例如
:set makeprg=make\ #<.o
[arguments] 是在 ":make" 後輸入的任何內容。{shellpipe}'shellpipe' 選項。{errorfile}'makeef' 選項,並將 ## 取代為使其唯一。
如果命令需要在其引數後加上一些額外字元,則可以使用佔位符 "$*" 來表示 {makeprg} 中的引數列表。然後,所有引數都會取代 $*。範例
:set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
或更簡單
:let &mp = 'latex \\nonstopmode \\input\{$*}'
"$*" 可以多次給定,例如
:set makeprg=gcc\ -o\ $*\ $*
'shellpipe' 選項在 Win32 上預設為 "2>&1| tee"。這表示編譯器的輸出會儲存到檔案中,而不會直接顯示在螢幕上。對於 Unix,會使用 "| tee"。編譯器輸出會同時顯示在螢幕上並儲存到檔案中。根據使用的 Shell,預設會使用 "|& tee" 或 "2>&1| tee",因此會包含 stderr 輸出。
如果 'shellpipe' 為空,則會省略 {errorfile} 部分。這對於自行寫入錯誤檔案的編譯器很有用。
使用 QuickFixCmdPost 修正編碼
'encoding' 可能會設定為與您的建置程式產生的訊息不同的編碼。此範例示範如何在 Vim 讀取錯誤訊息後修正此問題
function QfMakeConv()
   let qflist = getqflist()
   for i in qflist
      let i.text = iconv(i.text, "cp936", "utf-8")
   endfor
   call setqflist(qflist)
endfunction
au QuickfixCmdPost make call QfMakeConv()
(Faque Cheng 的範例)另一個選項是使用 'makeencoding'

5. 使用 :vimgrep 和 :grep grep lid

Vim 有兩種尋找模式比對的方法:內部和外部。內部 grep 的優點是它可以在所有系統上運作,並使用強大的 Vim 搜尋模式。當 Vim grep 無法執行您想要的操作時,可以使用外部 grep 程式。
內部方法會比較慢,因為檔案會讀取到記憶體中。優點是
行分隔符號和編碼會自動辨識,就像正在編輯檔案一樣。
使用 Vim 搜尋模式。可以使用多行模式。
當啟用外掛程式時:可以搜尋壓縮和遠端檔案。gzip netrw
為了能夠執行此操作,Vim 會載入每個檔案,就像正在編輯它一樣。當檔案中沒有比對時,相關的緩衝區會再次清除。'hidden' 選項會在此處忽略,以避免在搜尋許多檔案時耗盡記憶體或檔案描述子。但是,當使用 :hide 命令修飾詞時,會保留載入的緩衝區。這使得在相同檔案中進行後續搜尋的速度快很多。
請注意,可以使用 :copen(或 :lopen 表示 :lgrep)來開啟包含連結形式搜尋結果的緩衝區。可以使用 :silent 命令來抑制預設的全螢幕 grep 輸出。 :grep 命令的 ":grep!" 形式不會自動跳到第一個比對。可以結合這些命令來建立 NewGrep 命令
command! -nargs=+ NewGrep execute 'silent grep! <args>' | copen 42
5.1 使用 Vim 的內部 grep
:vim :vimgrep E682 E683 :vim[grep][!] /{pattern}/[g][j][f] {file} ... 在檔案 {file} ... 中搜尋 {pattern},並將符合的項目設定到錯誤列表中。符合 'wildignore' 的檔案會被忽略;而 'suffixes' 中的檔案會最後搜尋。
{pattern} 是一個 Vim 搜尋模式。 除了使用 / 將其包起來,也可以使用任何非 ID 字元(請參閱 'isident'),只要該字元沒有出現在 {pattern} 中即可。'ignorecase' 會生效。若要覆蓋它,可以在模式中加入 /\c 來忽略大小寫,或是加入 /\C 來匹配大小寫。'smartcase' 不會被使用。如果 {pattern} 是空的(例如指定 //),則會使用最後一次使用的搜尋模式。last-pattern
標記:'g' 若沒有 'g' 標記,則每一行只會加入一次。若有 'g' 標記,則每個匹配都會被加入。
'j' 若沒有 'j' 標記,Vim 會跳到第一個匹配項。若有 'j' 標記,則只會更新快速修正列表。若使用 [!],則當前緩衝區中的任何變更都會被捨棄。
'f' 當指定 'f' 標記時,會使用模糊字串匹配來尋找匹配的行。在這種情況下,{pattern} 會被視為字面字串,而非正規表示式。請參閱 fuzzy-matching 以了解更多關於模糊匹配字串的資訊。
QuickFixCmdPreQuickFixCmdPost 會被觸發。為匹配而開啟的檔案可以使用緩衝區編號,但如果可能的話會重複使用,以避免消耗緩衝區編號。
:{count}vim[grep] ... 當在命令前加上數字時,該數字會被用作尋找匹配項的最大數量。使用 ":1vimgrep pattern file" 只會尋找第一個。如果您只想檢查是否有匹配項,並在找到時快速退出,這會很有用。
每隔一秒左右,就會顯示被搜尋的檔案名稱,讓您了解進度。範例
:vimgrep /an error/ *.c
:vimgrep /\<FileName\>/ *.h include/*
:vimgrep /myfunc/ **/*.c
關於 "**" 的使用,請參閱 starstar-wildcard
:vim[grep][!] {pattern} {file} ... 和上面一樣,但不是用非 ID 字元將模式包起來,而是使用以空白分隔的模式。模式必須以 ID 字元開頭。範例
:vimgrep Error *.c
:lv :lvimgrep :lv[imgrep][!] /{pattern}/[g][j][f] {file} ... :lv[imgrep][!] {pattern} {file} ... 與 ":vimgrep" 相同,只是使用當前視窗的位置列表,而不是快速修正列表。
:vimgrepa :vimgrepadd :vimgrepa[dd][!] /{pattern}/[g][j][f] {file} ... :vimgrepa[dd][!] {pattern} {file} ... 和 ":vimgrep" 相同,但不是建立新的錯誤列表,而是將匹配項附加到目前的列表。
:lvimgrepa :lvimgrepadd :lvimgrepa[dd][!] /{pattern}/[g][j][f] {file} ... :lvimgrepa[dd][!] {pattern} {file} ... 和 ":vimgrepadd" 相同,只是使用當前視窗的位置列表,而不是快速修正列表。
5.2 外部 grep
Vim 可以使用類似於編譯器整合的方式與 "grep" 和類似 grep 的程式(例如 GNU id-utils)進行交互(請參閱上面的 :make)。
[Unix 小知識:Unix "grep" 命令的名稱來自 ":g/re/p",其中 "re" 代表正規表示式。]
:gr :grep :gr[ep][!] [引數] 與 ":make" 相同,但使用 'grepprg' 而不是 'makeprg',並使用 'grepformat' 而不是 'errorformat'。當 'grepprg' 為 "internal" 時,其運作方式類似 :vimgrep。 請注意,此時模式需要以分隔符號括起來。如果程式輸出的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:lgr :lgrep :lgr[ep][!] [引數] 與 ":grep" 相同,只是使用當前視窗的位置列表,而不是快速修正列表。
:grepa :grepadd :grepa[dd][!] [引數] 與 ":grep" 相同,但不是建立新的錯誤列表,而是將匹配項附加到目前的列表。範例
:call setqflist([])
:bufdo grepadd! something %
第一個命令會建立一個新的空的錯誤列表。第二個命令會為每個列出的緩衝區執行 "grepadd"。請注意使用 ! 以避免 ":grepadd" 跳到第一個錯誤,這在使用 :bufdo 時是不允許的。以下範例使用引數列表,並避免在沒有匹配項的檔案中發生錯誤
:silent argdo try
  \ | grepadd! something %
  \ | catch /E480:/
  \ | endtry"
如果程式輸出的編碼與 'encoding' 選項不同,您可以使用 'makeencoding' 選項來指定編碼。
:lgrepa :lgrepadd :lgrepa[dd][!] [引數] 與 ":grepadd" 相同,只是使用當前視窗的位置列表,而不是快速修正列表。
5.3 設定外部 grep
如果您安裝了標準的 "grep" 程式,則 :grep 命令可能可以使用預設值正常運作。其語法與標準命令非常相似
:grep foo *.c
將會在所有副檔名為 .c 的檔案中搜尋子字串 "foo"。傳遞給 :grep 的引數會直接傳遞給 "grep" 程式,因此您可以使用 "grep" 支援的任何選項。
預設情況下,:grep 會使用 -n 選項(顯示檔案和行號)來調用 grep。您可以使用 'grepprg' 選項來變更此設定。如果出現以下情況,您將需要設定 'grepprg'
a) 您使用的是不是叫做 "grep" 的程式 b) 您必須使用完整路徑來調用 grep c) 您想要自動傳遞其他選項(例如,不區分大小寫的搜尋)。
一旦 "grep" 執行完成,Vim 會使用 'grepformat' 選項來解析結果。此選項的運作方式與 'errorformat' 選項相同 - 請參閱該選項以了解詳細資訊。如果您的 grep 輸出非標準格式,或者您使用具有特殊格式的其他程式,則可能需要將 'grepformat' 從預設值變更。
解析結果後,Vim 會載入第一個包含匹配項的檔案,並跳到適當的行,這與它在 快速修正 模式中跳到編譯器錯誤的方式相同。然後,您可以使用 :cnext:clist 等命令來查看其他匹配項。
5.4 將 :grep 與 id-utils 搭配使用
您可以設定 :grep 來與 GNU id-utils 搭配使用,如下所示
:set grepprg=lid\ -Rgrep\ -s
:set grepformat=%f:%l:%m
接著
:grep (regexp)
會如您預期般運作。(前提是您記得先 mkid :))
5.5 使用 :vimgrep 或 :grep 瀏覽原始碼
使用 Vim 保留的錯誤列表堆疊,您可以瀏覽檔案以尋找函數及其呼叫的函數。例如,假設您必須向 read_file() 函數新增一個引數。您可以輸入以下命令
:vimgrep /\<read_file\>/ *.c
您可以使用 ":cn" 來瀏覽匹配列表並新增引數。在某個地方,您必須從更上層的函數 msg() 取得新的引數,因此也需要變更該函數。因此,您可以使用
:vimgrep /\<msg\>/ *.c
在變更 msg() 函數時,您會發現另一個函數需要從更上層取得引數。您可以再次使用 ":vimgrep" 來尋找這些函數。一旦完成一個函數,您可以使用
:colder
返回上一個函數。
這就像瀏覽樹狀結構:":vimgrep" 會深入一層,建立分支列表。":colder" 會返回上一層。您可以混用 ":vimgrep" 和 "colder" 來以樹狀方式瀏覽所有位置。如果您持續這樣做,您將可以找到所有位置,而無需寫下「待辦事項」清單。

6. 選擇編譯器 compiler-select

:comp :compiler E666 :comp[iler][!] {name} 設定選項以與編譯器 {name} 搭配使用。不加 "!" 時,選項會針對目前的緩衝區設定。加上 "!" 時,會設定全域選項。如果您在 "file.foo" 中使用 ":compiler foo",然後在另一個緩衝區中使用 ":compiler! bar",Vim 仍會在 "file.foo" 中繼續使用 "foo"。
"compiler" 目錄中的 Vim 外掛程式會設定選項以使用選定的編譯器。對於 :compiler,會設定本機選項,而對於 :compiler!,會設定全域選項。current_compiler
為了支援舊版的 Vim,外掛程式一律使用 "current_compiler",而不是 "b:current_compiler"。此命令實際執行以下操作
刪除 "current_compiler" 和 "b:current_compiler" 變數。
定義 "CompilerSet" 使用者命令。加上 "!" 時,會執行 ":set",不加 "!" 時,會執行 ":setlocal"。
執行 ":runtime! compiler/{name}.{vim,lua}"。外掛程式預期會使用 "CompilerSet" 來設定選項,並將 "current_compiler" 變數設定為編譯器的名稱。
刪除 "CompilerSet" 使用者命令。
將 "b:current_compiler" 設定為 "current_compiler" 的值。
不加 "!" 時,會還原 "current_compiler" 的舊值。
如需撰寫編譯器外掛程式,請參閱 write-compiler-plugin
使用 compiler-make 外掛程式來取消編譯器外掛程式的效果。
使用 g/b:`c_cppcheck_params` 來設定 cppcheck 參數。全域設定預設包括
--verbose:啟用詳細輸出。
--force:強制檢查所有設定。
--inline-suppr:允許行內抑制。
--enable=...:啟用特定的檢查,例如警告、樣式、效能、可移植性、資訊和遺失的 include。
-j:如果可用,則利用多個處理器,由 getconf 命令決定是否可用(需要省略 unusedFunction 檢查)。
對於 C++ 檔案 (filetype == 'cpp'),會加入 --language=c++ 選項,以確保 Cppcheck 將該檔案視為 C++ 處理。
如果目前目錄中存在 compile_commands.json,則會將其作為 --project 參數新增至命令列。否則,預設會將 &path 中的目錄作為 include 目錄傳遞。這些可以透過 g/b:`c_cppcheck_includes` 設定為 -I 旗標列表。Tim Pope 的 vim-apathy 外掛程式 [0] 可以展開 &path。若要同時附加 git repo 中的資料夾,請使用
let &l:path = join(systemlist('git ls-tree -d --name-only -r HEAD'), ',')
[0] https://github.com/tpope/vim-apathy
.NET CLI 編譯器預設會輸出錯誤和警告。透過將 g:dotnet_errors_only 變數設定為 v:true,可以限制輸出只包含錯誤。
每個錯誤和警告中都包含相關的專案名稱。若要隱藏專案名稱,請將 g:dotnet_show_project_file 變數設定為 v:false
範例:限制輸出只顯示錯誤,並隱藏專案名稱
let dotnet_errors_only = v:true
let dotnet_show_project_file = v:false
compiler dotnet
您可以為 GCC 編譯器設定一個變數
g:compiler_gcc_ignore_unmatched_lines 忽略與為 GCC 定義的任何模式不符的行。如果從 make 執行的命令輸出產生誤判,則這很有用。
常用的編譯器選項可以透過設定 g:javac_makeprg_params 變數新增至 'makeprg'。例如
let g:javac_makeprg_params = "-Xlint:all -encoding utf-8"

GNU MAKE compiler-make

由於預設的 make 程式是 "make",因此 make 的編譯器外掛程式 :compiler make 會將 'makeprg''errorformat' 選項重設為預設值,並取消設定先前編譯器外掛程式可能已設定的任何變數。
GROFF 編譯器外掛程式使用 mom 巨集集(記錄在 groff_mom 手冊頁中)作為輸入,並期望輸出檔案類型副檔名傳遞給 make,例如 :make html 或 :make pdf。
可以透過在 b:groff_compiler_argsg:groff_compiler_args 中設定額外的引數來傳遞給 groff。傳遞給 groff 的 language 引數是使用 'spelllang' 設定的;可以使用設定 b:groff_compiler_lang 來覆寫它。預設編碼為 UTF-8,可以透過設定 b:groff_compiler_encodingg:groff_compiler_encoding 來變更。
Pandoc 編譯器外掛程式預期輸出檔案類型副檔名傳遞給 make,例如 :make html 或 :make pdf。
可以將額外的引數傳遞給 pandoc
可以透過將它們附加到 make 來傳遞,例如 :make html --self-contained
或在 b:pandoc_compiler_argsg:pandoc_compiler_args 中設定它們。
--from 引數是使用緩衝區檔案類型進行的合理猜測;可以透過設定 b:pandoc_compiler_from 來覆寫它。--metadata lang 引數是使用 'spelllang' 設定的;如果假設 --from=markdown 並且未在標題標頭或 YAML 區塊中設定標題,則會將檔案名稱(不含副檔名)用作標題。
Perl 編譯器外掛程式實際上不會編譯,而是會叫用 Perl 的內部語法檢查功能並剖析輸出中可能存在的錯誤,以便您可以在快速修復模式中修正它們。
無論檔案內是否為 "no warnings" 或 "$^W = 0",都會強制顯示警告。若要停用此設定,請將 g:perl_compiler_force_warnings 設定為零值。例如
let g:perl_compiler_force_warnings = 0

PYUNIT COMPILER compiler-pyunit

這實際上不是編譯器,而是 Python 語言的單元測試框架。它包含在 2.0 版本開始的標準 Python 發行版本中。對於較舊的版本,您可以從 https://pyunit.sourceforge.net 取得。
當您使用框架執行測試時,Vim 會剖析可能發生的錯誤,並在快速修復模式中呈現給您。
不幸的是,沒有標準的執行測試方式。alltests.py 腳本似乎很常用,僅此而已。因此,對於 'makeprg' 選項有用的值為:setlocal makeprg=./alltests.py 「執行測試套件」setlocal makeprg=python\ %:S 「執行單一測試案例」

TEX COMPILER compiler-tex

發行版本中包含的 TeX 編譯器 ($VIMRUNTIME/compiler/tex.vim) 會盡可能使用 make 命令。如果編譯器在目前目錄中找到名為 "Makefile" 或 "makefile" 的檔案,則會假設您想要使用 make 處理您的 *TeX 檔案,而 makefile 會執行正確的工作。在這種情況下,編譯器會為 *TeX 輸出設定 'errorformat',並保持 'makeprg' 不變。如果找不到 "Makefile" 或 "makefile",編譯器將不會使用 make。您可以透過定義 b:tex_ignore_makefile 或 g:tex_ignore_makefile 變數(僅檢查它們是否存在)來強制編譯器忽略 makefile。
如果編譯器選擇不使用 make,則需要選擇正確的程式來處理您的輸入。如果存在 b:tex_flavor 或 g:tex_flavor 變數(以此優先順序),則它會為 :make 定義 TeX 風格(實際上,這是執行命令的名稱),如果兩個變數都不存在,則預設為 "latex"。例如,在編輯從 AMS-TeX 撰寫的 mypaper.tex 包含的 chapter2.tex 時
:let b:tex_flavor = 'amstex'
:compiler tex
[編輯中...]
:make mypaper
請注意,您必須指定要處理的檔案名稱作為引數(在編輯從 \input 或 \include 包含的檔案時處理正確的檔案;歡迎使用可攜式解決方案,以將 % 替換為無引數)。這不在 make 的語意中,您在其中指定目標,而非來源,但您可以指定不含副檔名 ".tex" 的檔案名稱,並將其視為「根據編譯器,make filename.dvi 或 filename.pdf 或 filename.some_result_extension」。
注意: tex 命令列語法設定為適用於 MikTeX(Srinath Avadhanula 的建議)和 teTeX(Artem Chuprina 檢查過)。來自 errorformat-LaTeX 的建議太複雜,無法在不同的 shell 和作業系統上保持運作,而且也不允許使用其他可用的 TeX 選項(如果有的話)。如果您的 TeX 不支援 "-interaction=nonstopmode",請回報它,並使用不同的方式從命令列表達 \nonstopmode。

TYPST COMPILER compiler-typst

Vim 包含 Typst 檔案的編譯器外掛程式。此編譯器會由 Typst 檔案類型外掛程式 ft-typst-plugin 在 Typst 緩衝區中自動啟用。執行 :make 來編譯目前的 Typst 檔案。
g:typst_cmd
預設情況下,Vim 會使用 "typst" 作為執行 Typst 編譯器的命令。可以透過設定 g:typst_cmd 變數來變更它。
let g:typst_cmd = "/path/to/other/command"

7. 錯誤格式 error-file-format

errorformat E372 E373 E374 E375 E376 E377 E378 'errorformat' 選項會指定可辨識的格式清單。會使用第一個與錯誤訊息相符的格式。您可以為編譯器產生的不同訊息新增數個格式,甚至是多個編譯器的項目。請參閱 efm-entries
'errorformat' 中的每個項目都是類似 scanf 的字串,描述該格式。首先,您需要知道 scanf 的運作方式。請參閱 C 編譯器的文件。以下是 Vim 了解的 % 項目。其他項目無效。
'errorformat' 中的特殊字元為逗號和反斜線。請參閱 efm-entries,了解如何處理它們。請注意,常值 "%" 是由 "%%" 比對,因此不會使用反斜線跳脫。請記住,在 :make:grep 輸出中,所有 NUL 字元都會替換為 SOH (0x01)。
注意:預設情況下,會忽略大小寫之間的差異。如果您想要比對大小寫,請將 "\C" 新增至模式 /\C
Vim 將讀取任何長度的行,但只會使用前 4095 個位元組,其餘的會被忽略。項目只能是 1023 個位元組長。
基本項目
%f 檔案名稱(尋找字串)%b 緩衝區編號(尋找數字)%o 模組名稱(尋找字串)%l 行號(尋找數字)%e 結束行號(尋找數字)%c 欄號(尋找代表錯誤字元欄的數字、位元組索引,<tab> 是 1 個字元欄)%v 虛擬欄號(尋找代表錯誤螢幕欄的數字 (1 <tab> == 8 個螢幕欄))%k 結束欄號(尋找代表錯誤字元欄的數字、位元組索引,或如果與 %v 一起使用時,則尋找代表錯誤螢幕結束欄的數字)%t 錯誤類型(尋找單一字元):e - 錯誤訊息 w - 警告訊息 i - 資訊訊息 n - 附註訊息 %n 錯誤編號(尋找數字)%m 錯誤訊息(尋找字串)%r 比對單行檔案訊息的「其餘」部分 %O/P/Q %p 指標行(尋找 '-'、'.'、' ' 或 Tab 的序列,並使用長度作為欄號)%*{conv} 任何 scanf 無法指派的轉換 %% 單一 '%' 字元 %s 搜尋文字(尋找字串)
"%f" 轉換可能取決於目前的 'isfname' 設定。"~/" 會展開為主目錄,而環境變數會展開。
"%f" 和 "%m" 轉換必須偵測字串的結尾。這通常是透過比對後續字元和項目來完成的。如果沒有任何內容跟隨,則會比對行的其餘部分。如果 "%f" 後面跟著 '%' 或反斜線,它會尋找 'isfname' 字元序列。
在 Windows 上,即使使用 "%f:","%f" 中也會包含開頭的 "C:"。這表示無法偵測單一字母的檔案名稱。
"%b" 轉換用於剖析緩衝區編號。這對於參照暫存緩衝區或沒有名稱的緩衝區中的行很有用。如果不存在具有相符編號的緩衝區,則該行會用作非錯誤行。
"%p" 轉換通常後面會跟著 "^"。它用於輸出像這樣的行的編譯器
^
---------^
以指出錯誤的欄。這將在多行錯誤訊息中使用。請參閱 errorformat-javac,以取得有用的範例。
"%s" 轉換會指定要搜尋以尋找錯誤行的文字。該文字會用作常值字串。錨點 "^" 和 "$" 會新增至文字,以尋找完全比對搜尋文字的錯誤行,並且該文字會加上 "\V" 原子,使其成為「非常不具魔力」。"%s" 轉換可用於尋找錯誤輸出中沒有行號的行。就像 "grep" shell 命令的輸出一樣。當模式存在時,不會使用行號。
「%o」轉換指定快速修正條目中的模組名稱。如果存在,它將在快速修正錯誤視窗中使用,而不是使用檔名。模組名稱僅用於顯示目的,跳轉到檔案時將使用檔名。
變更目錄
以下的大寫轉換字元指定特殊格式字串的類型。在單一逗號分隔的格式模式開頭,最多可以給定一個作為前綴。某些編譯器產生的訊息包含必須附加到 %f 讀取的每個檔名的目錄名稱(例如:GNU make)。可以使用以下代碼掃描這些目錄名稱;它們將儲存在內部目錄堆疊中。E379
%D「進入目錄」格式字串;預期後接一個 %f,以尋找目錄名稱 %X「離開目錄」格式字串;預期後接一個 %f
當定義「進入目錄」或「離開目錄」格式時,「%D」或「%X」必須在該子字串的開頭給定。Vim 會追蹤目錄變更,並將目前目錄附加到每個找到的相對路徑錯誤檔案。有關詳細資訊、提示和限制,請參閱quickfix-directory-stack
可以讀取產生多行訊息的程式輸出,即消耗多行以上的錯誤字串。可能的前綴是:%E 多行錯誤訊息的開始 %W 多行警告訊息的開始 %I 多行資訊訊息的開始 %N 多行註解訊息的開始 %A 多行訊息的開始(未指定類型) %> 下一行再次以目前模式開始 efm-%> %C 多行訊息的延續 %Z 多行訊息的結尾 這些可以與「+」和「-」一起使用,請參閱下面的 efm-ignore
在模式中使用「\n」無法比對多行訊息。
範例:您的編譯器碰巧以以下格式寫出錯誤(開頭的行號不屬於實際輸出)
1 Error 275
2 line 42
3 column 3
4 ' ' expected after '--'
適當的錯誤格式字串必須如下所示
:set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
為此錯誤產生的 :clist 錯誤訊息是
1:42 col 3 error 275: ' ' expected after '--'
另一個範例:假設有一個 Python 直譯器產生以下錯誤訊息(行號不屬於實際輸出)
1 ============================================================== 2 FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest) 3 -------------------------------------------------------------- 4 Traceback (most recent call last): 5 File "unittests/dbfacadeTest.py", line 89, in testFoo 6 self.assertEquals(34, dtid) 7 File "/usr/lib/python3.8/unittest.py", line 286, in 8 failUnlessEqual 9 raise self.failureException, \ 10 AssertionError: 34 != 33 11 12 -------------------------------------------------------------- 13 Ran 27 tests in 0.063s
假設您希望 :clist 只寫入此訊息的相關資訊,即:5 unittests/dbfacadeTest.py:89: AssertionError: 34 != 33
那麼錯誤格式字串可以定義如下
:set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
請注意,這裡的 %C 字串是在 %A 之前給出的:由於運算式 ' %.%#' (代表正規運算式 ' .*') 比對以空格開頭的每一行,後接任意字元到行尾,因此它也會隱藏第 7 行,否則將觸發單獨的錯誤訊息。錯誤格式字串總是逐模式解析,直到出現第一個比對。efm-%>
可以使用 %> 項目來避免嘗試在 'errorformat' 中較早出現的模式。這對於比對幾乎所有內容的模式非常有用。例如,如果錯誤看起來像這樣
Error in line 123 of foo.c
unknown variable "i"
這可以使用以下程式碼找到
:set efm=xxx,%E%>Error in line %l of %f:,%Z%m
其中 "xxx" 具有一個也會比對第二行的模式。
重要提示:沒有記憶體記錄 errorformat 的哪個部分之前比對;錯誤檔案中的每一行都會完整重新執行 error format 行。例如,如果有一個
setlocal efm=aa,bb,cc,dd,ee
其中 aa、bb 等是錯誤格式字串。錯誤檔案的每一行都會比對模式 aa,然後是 bb,然後是 cc 等。僅僅因為 cc 比對了先前的錯誤行,並不表示 dd 會在目前行上首先嘗試,即使 cc 和 dd 是多行 errorformat 字串。
如果檔名只給定一次,並且後面有多個引用此檔名的訊息,則這些前綴很有用。%O 單行檔案訊息:略過比對的部分 %P 單行檔案訊息:將檔案 %f 推入堆疊 %Q 單行檔案訊息:從堆疊中彈出最後一個檔案
範例:假設有一個編譯器產生以下錯誤記錄檔(沒有開頭的行號)
1 [a1.tt] 2 (1,17) error: ';' missing 3 (21,2) warning: variable 'z' not defined 4 (67,3) error: end of file found before string ended 5 6 [a2.tt] 7 8 [a3.tt] 9 NEW compiler v1.1 10 (2,2) warning: variable 'x' not defined 11 (67,3) warning: 's' already defined
此記錄檔列出每個以 [...] 包圍的檔案的多個訊息,這些訊息會被如下的錯誤格式正確解析
:set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q
:clist 的呼叫會根據它們的正確檔名寫入這些訊息
2 a1.tt:1 col 17 error: ';' missing 3 a1.tt:21 col 2 warning: variable 'z' not defined 4 a1.tt:67 col 3 error: end of file found before string ended 8 a3.tt:2 col 2 warning: variable 'x' not defined 9 a3.tt:67 col 3 warning: 's' already defined
與所有比對整行的其他前綴不同,%P、%Q 和 %O 可以用來比對同一行中的多個模式。因此,甚至可以解析如下一行中的巢狀檔案
{"file1" {"file2" error1} error2 {"file3" error3 {"file4" error4 error5}}}
然後 %O 會解析略過不包含任何推入/彈出檔名資訊的字串。有關擴展範例,請參閱 errorformat-LaTeX
忽略和使用整個訊息 efm-ignore
代碼「+」或「-」可以與上面的大寫代碼組合;在這種情況下,它們必須放在字母前面,例如「%+A」或「%-G」:%− 不要在任何輸出中包含比對的多行 %+ 在 %m 錯誤字串中包含整個比對行
有一個前綴僅在與「+」或「-」組合時才有用,即 %G。它會解析略過包含一般資訊的行,例如可以跳過的編譯器版本字串或其他標頭。%-G 忽略此訊息 %+G 一般訊息
模式比對
為了與先前版本的 Vim 向後相容,支援類似 scanf() 的 "%*[]" 標記法。但是,也可以在格式字串中指定(幾乎)任何 Vim 支援的正規運算式。由於正規運算式語言的元字元可以是普通比對字串或檔名的一部分(因此內部必須逸出),元符號必須使用前導「%」來寫入:「%\\」單個「\」字元。請注意,這必須在 ":set errorformat=" 定義中逸出(「%\\」)。「%.」單個「.」字元。「%#」單個「*」(!) 字元。「%^」單個「^」字元。請注意,這沒有用處,該模式已比對行首。「%$」單個「$」字元。請注意,這沒有用處,該模式已比對行尾。「%[」用於「[]」字元範圍的單個「[」字元。「%~」單個「~」字元。當在運算式中使用字元類別時(有關概述,請參閱 /\i),包含「\+」量詞的項目可以使用 scanf() 的 "%*" 標記法撰寫。範例:「%\\d%\\+」(「\d\+」,「任意數字」)等同於「%*\\d」。重要提示:子比對的 \(\.\.\.\) 分組不能在格式規格中使用,因為它保留用於內部轉換。
'errorformat' 中的多個條目 efm-entries
為了能夠偵測多個編譯器的輸出,可以在 'errorformat' 中放入多個格式模式,並以逗號分隔(請注意:逗號後的空格會被忽略)。使用第一個完全比對的模式。如果找不到比對,則將使用最後一個的比對部分,雖然檔名已移除,且錯誤訊息會設定為整個訊息。如果有一個模式可能會比對來自多個編譯器的輸出(但方式不正確),請將它放在限制性更強的模式之後。
若要在模式中包含逗號,請在逗號前面加上反斜線(您必須在 ":set" 命令中輸入兩個)。若要包含反斜線本身,請給出兩個反斜線(您必須在 ":set" 命令中輸入四個)。您還需要在 ":set" 的空格前面加上反斜線。
有效的比對 quickfix-valid
如果一行與 'errorformat' 中的其中一個條目不完全比對,則整行會放入錯誤訊息中,且該條目會標記為「無效」。這些行會使用「:cn」和「:cp」命令跳過(除非根本沒有有效的行)。您可以使用「:cl!」來顯示所有錯誤訊息。
如果錯誤格式不包含檔名,則 Vim 無法切換到正確的檔案。您必須手動執行此操作。
例如,Amiga Aztec 編譯器的輸出格式如下
檔名>行號:欄號:錯誤類型:錯誤編號:錯誤訊息
檔名:偵測到錯誤的檔案名稱 行號:偵測到錯誤的行號 欄號:偵測到錯誤的欄號 錯誤類型:錯誤類型,通常是單個「E」或「W」 錯誤編號:錯誤的編號(用於在手冊中查找) 錯誤訊息:錯誤的描述
可以使用此 'errorformat' 條目比對:%f>%l:%c:%t:%n:%m
以下是一些產生單行錯誤輸出的 C 編譯器範例:%f:%l:\ %t%*[^0123456789]%n:\ %m 用於 Manx/Aztec C 錯誤訊息 (scanf() 無法理解 [0-9]) %f\ %l\ %t%*[^0-9]%n:\ %m 用於 SAS C \"%f\"\\,%*[^0-9]%l:\ %m 用於通用 C 編譯器 %f:%l:\ %m 用於 GCC %f:%l:\ %m,%Dgmake[%*\\d]:\ Entering\ directory\%f', %Dgmake[%*\\d]:\ Leaving\ directory\%f' 用於使用 gmake 的 GCC (串連行!) %f(%l)\ :\ %*[^:]:\ %m 舊的 SCO C 編譯器 (pre-OS5) %f(%l)\ :\ %t%*[^0-9]%n:\ %m 同上,帶有錯誤類型和編號 %f:%l:\ %m,In\ file\ included\ from\ %f:%l:,\^I\^Ifrom\ %f:%l%m 用於 GCC,帶有一些額外資訊
以下提供處理多行訊息的擴展範例,請參閱 errorformat-Jikeserrorformat-LaTeX
請注意空格和雙引號前面的反斜線。這是 `:set` 命令所必需的。逗號前面有兩個反斜線,一個用於 `:set` 命令,另一個用於避免將逗號識別為錯誤格式的分隔符。
篩選訊息
如果您的編譯器產生的錯誤訊息不符合格式字串,您可以編寫一個程式將錯誤訊息轉換為此格式。您可以透過變更 'makeprg' 選項,將此程式與 ":make" 命令一起使用。例如
:set mp=make\ \\\|&\ error_filter
管道符號之前的反斜線是必需的,以避免它被識別為命令分隔符。每個空格前面的反斜線是 `set` 命令所必需的。

8. 目錄堆疊 quickfix-directory-stack

Quickfix 維護一個堆疊,用於儲存從 make 輸出中剖析的所有已使用目錄。對於 GNU-make 來說,這相當簡單,因為它總是會列印出它進入和離開的所有目錄的絕對路徑。無論這是否是透過 makefile 中的 'cd' 命令完成,還是使用參數 "-C dir" (在讀取 makefile 之前變更到目錄) 完成。使用開關 "-w" 強制 GNU-make 在處理之前和之後列印出工作目錄可能會很有用。
如果您不使用 GNU-make,則維護正確的目錄會更複雜。例如,AIX-make 不會列印任何關於其工作目錄的資訊。那麼您需要增強 makefile。在 LessTif 的 makefile 中,有一個命令會輸出 "Making {target} in {dir}"。這裡的特殊問題是它不會列印離開目錄的資訊,並且不會列印絕對路徑。
為了解決相對路徑和遺失「離開目錄」訊息的問題,Vim 使用以下演算法
1) 檢查給定的目錄是否為目前目錄的子目錄。如果為真,則將其儲存為目前目錄。2) 如果它不是目前目錄的子目錄,則嘗試它是否為上層目錄之一的子目錄。3) 如果仍然找不到該目錄,則假設它是 Vim 目前目錄的子目錄。
此外,對於每個檔案,都會檢查它是否確實存在於已識別的目錄中。如果沒有,則會在目錄堆疊的所有其他目錄中搜尋 (而不是目錄子樹!)。如果仍然找不到,則假設它位於 Vim 的目前目錄中。
此演算法存在限制。這些範例假設 make 只會以 "Making all in dir" 的形式列印有關進入目錄的資訊。
1) 假設您有以下目錄和檔案:./dir1 ./dir1/file1.c ./file1.c
如果 make 在處理目前目錄之前處理目錄 "./dir1",並且檔案 "./file1.c" 中有錯誤,您最終會讓 Vim 載入檔案 "./dir1/file.c"。
這只能透過「離開目錄」訊息來解決。
2) 假設您有以下目錄和檔案:./dir1 ./dir1/dir2 ./dir2
您會得到以下結果
Make 輸出 Vim 解釋的目錄 ------------------------ ---------------------------- Making all in dir1 ./dir1 Making all in dir2 ./dir1/dir2 Making all in dir2 ./dir1/dir2
這可以透過在「進入目錄」訊息中列印絕對目錄,或列印「離開目錄」訊息來解決。
為了避免這個問題,請確保列印絕對目錄名稱和「離開目錄」訊息。
Makefile 範例
Unix: libs: for dn in $(LIBDIRS); do \ (cd $$dn; echo "Entering dir '$$(pwd)'"; make); \ echo "Leaving dir"; \ done
在您的 'errorformat' 中新增 %DEntering\ dir\ '%f',%XLeaving\ dir 來處理上述輸出。
請注意,Vim 不會檢查「離開目錄」訊息中的目錄名稱是否為目前目錄。這就是為什麼您可以只使用訊息 "Leaving dir" 的原因。

9. 特定錯誤檔案格式 errorformats

errorformat-Jikes
Jikes(TM) 是由 IBM Research 發布的源碼到位元組碼 Java 編譯器,它會產生簡單的多行錯誤訊息。
下面顯示了一個與產生的訊息相符的 'errorformat' 字串。以下行可以放置在使用者的 init.vim 中,以覆寫 Vim 識別的預設格式,或者參閱 :set+= 以了解如何將此格式額外安裝到預設格式中。
:set efm=%A%f:%l:%c:%*\\d:%*\\d:,
      \%C%*\\s%trror:%m,
      \%+C%*[^:]%trror:%m,
      \%C%*\\s%tarning:%m,
      \%C%m
當使用選項 "+E" 叫用 Jikes(TM) 時,它會產生單行錯誤訊息,並且可以使用以下內容比對
:setl efm=%f:%l:%v:%*\\d:%*\\d:%*\\s%m
errorformat-javac
據回報,這個 'errorformat' 適用於 javac,它會輸出一個帶有 "^" 的行來指示錯誤的列。
:setl efm=%A%f:%l:\ %m,%-Z%p^,%-C%.%#
:setl efm=%A%f:%l:\ %m,%+Z%p^,%+C%.%#,%-G%.%#
這是來自 Michael F. Lamb 的另一個適用於 Unix 的替代方案,它會先篩選錯誤
:setl errorformat=%Z%f:%l:\ %m,%A%p^,%-G%*[^sl]%.%#
:setl makeprg=javac\ %:S\ 2>&1\ \\\|\ vim-javac-filter
您需要將以下內容放入您路徑中的某個位置 (例如,在 ~/bin 中) 的 "vim-javac-filter" 中,並使其可執行
#!/bin/sed -f
/\^$/s/\t/\ /g;/:[0-9]\+:/{h;d};/^[ \t]*\^/G;
用英語來說,該 sed 指令碼
將單個 Tab 字元變更為單個空格,並且
將帶有檔案名稱、行號、錯誤訊息的行移動到指標行之後。這樣,之間未使用的錯誤文字不會破壞 Vim 的「多行訊息」概念,也不會強迫我們將其包含為「多行訊息的延續」。
errorformat-ant
對於 ant (https://jakarta.apache.org/),必須修改上述 errorformat,以符合每個 javac 輸出列前面的前導 [javac]
:set efm=%A\ %#[javac]\ %f:%l:\ %m,%-Z\ %#[javac]\ %p^,%-C%.%#
也可以配置 'errorformat' 以處理 ant 以及 javac 或 jikes。如果您使用 jikes,您應該告訴 ant 使用 jikes 的 +E 命令列開關,這會強制 jikes 產生單行錯誤訊息。這就是下面的第二行 (build.xml 檔案) 所執行的操作
<property name = "build.compiler"       value = "jikes"/>
<property name = "build.compiler.emacs" value = "true"/>
處理 ant 以及 javac 和 jikes 的 'errorformat'
:set efm=\ %#[javac]\ %#%f:%l:%c:%*\\d:%*\\d:\ %t%[%^:]%#:%m,
         \%A\ %#[javac]\ %f:%l:\ %m,%-Z\ %#[javac]\ %p^,%-C%.%#
errorformat-jade
剖析 jade (請參閱 http://www.jclark.com/) 錯誤很簡單
:set efm=jade:%f:%l:%c:%t:%m
errorformat-LaTeX
以下範例說明如何為 (La)TeX 排版系統指定 'errorformat' 字串,該系統會在多行上顯示錯誤訊息。":clist" 和 ":cc" 等命令的輸出會在單行中顯示多行,並移除前導空白。應該很容易將上述 LaTeX errorformat 調整為任何由多行錯誤組成的編譯器輸出。
這些命令可以放在 vimrc 檔案或一些其他 Vim 指令碼檔案中,例如,一個僅在編輯 LaTeX 來源時載入的包含 LaTeX 相關內容的指令碼。請務必複製範例的所有行 (依給定順序),然後移除註解行。對於某些行開頭的 '\' 標記法,請參閱 line-continuation
首先準備 'makeprg',以便 LaTeX 會回報多個錯誤;在發生第一個錯誤時不要停止
:set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
多行錯誤訊息的開始
:set efm=%E!\ LaTeX\ %trror:\ %m,
       \%E!\ %m,
多行警告訊息的開始;前兩個還包括行號。一些正規表示式的含義
"%.%#" (".*") 比對 (可能是空的) 字串
"%*\\d" ("\d\+") 比對數字
\%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#,
\%+W%.%#\ at\ lines\ %l--%*\\d,
\%WLaTeX\ %.%#Warning:\ %m,
錯誤/警告訊息的可能延續;第一個還包括行號
\%Cl.%l\ %m,
\%+C\ \ %m.,
\%+C%.%#-%.%#,
\%+C%.%#[]%.%#,
\%+C[]%.%#,
\%+C%.%#%[{}\\]%.%#,
\%+C<%.%#>%.%#,
\%C\ \ %m,
符合以下模式的行不包含任何重要資訊;請勿將其包含在訊息中
\%-GSee\ the\ LaTeX%m,
\%-GType\ \ H\ <return>%m,
\%-G\ ...%.%#,
\%-G%.%#\ (C)\ %.%#,
\%-G(see\ the\ transcript%.%#),
通常排除任何要顯示的空白或僅包含空白的行
\%-G\\s%#,
LaTeX 輸出記錄不會逐行指定錯誤來源檔案的名稱;而是以括號括起來整體給出。以下模式嘗試比對這些名稱並將其儲存在內部堆疊中。這些模式可能會掃描相同的輸入行 (一個接一個),尾隨 "%r" 轉換表示該行其餘部分將在下一次掃描中剖析,直到到達行尾。
忽略以 '('...')' 括起來的檔案名稱;不要將其推送至堆疊,因為該檔案顯然不包含任何錯誤
\%+O(%f)%r,
將檔案名稱推送到堆疊上。該名稱是在 '(' 之後給出的
\%+P(%f%r,
\%+P\ %\\=(%f%r,
\%+P%*[^()](%f%r,
\%+P[%\\d%[^()]%#(%f%r,
掃描到 ')' 時,彈出最後儲存的檔案名稱
\%+Q)%r,
\%+Q%*[^()])%r,
\%+Q[%\\d%*[^()])%r
請注意,在某些情況下,無法正確剖析 LaTeX 輸出記錄中的檔案名稱。剖析器可能因為不平衡的括號而混亂。上述範例僅嘗試捕捉最相關的情況。您可以自訂給定的設定以滿足您自己的目的,例如,可以排除所有惱人的「過滿...」警告而不將其識別為錯誤。或者,除了篩選 LaTeX 編譯器輸出外,也可以直接讀取 [La]TeX 編譯器產生的 *.log 檔案。這包含更多關於可能錯誤原因的有用資訊。但是,要正確剖析如此複雜的檔案,應該使用外部篩選器。請參閱上面更進一步的說明,了解如何讓 Vim 知道此篩選器。

10. 自訂 Quickfix 視窗 quickfix-window-function

Quickfix 視窗和位置清單視窗中顯示的行的預設格式是
<filename>|<lnum> col <col>|<text>
每一行中顯示的值對應於 getqflist() 函式傳回的「bufnr」、「lnum」、「col」和「text」欄位。
對於某些 Quickfix/位置清單,需要自訂顯示的文字。例如,如果 Quickfix 項目僅存在檔案名稱,則檔案名稱後的兩個 "|" 欄位分隔字元不是必需的。另一個用例是自訂檔案名稱顯示的路徑。根據預設,對於不在目前目錄樹下的檔案,會顯示完整路徑 (可能太長)。檔案路徑可能需要簡化為共同的父目錄。
顯示的文字可以透過將 'quickfixtextfunc' 選項設定為 Vim 函式來自訂。此函式將會以一個字典引數呼叫,並應傳回一個字串列表,以便顯示在 quickfix 或 location list 視窗中。該字典引數將包含以下欄位:
quickfix:當為 quickfix list 呼叫時設為 1,當為 location list 呼叫時設為 0。winid:對於 location list,設為包含 location list 的視窗 ID。對於 quickfix list,設為 0。可用於 getloclist() 以取得 location list 項目。id:quickfix 或 location list 的識別碼。start_idx:應該傳回文字的第一個條目的索引。end_idx:應該傳回文字的最後一個條目的索引。
此函式應為從 start_idx 到 end_idx 的每個條目傳回單行文字,以顯示在 quickfix 視窗中。此函式可以使用 getqflist() 函式並指定 quickfix list 識別碼 "id" 來取得有關條目的資訊。對於 location list,可以使用帶有 "winid" 引數的 getloclist() 函式。如果傳回一個空列表,則將使用預設格式來顯示所有條目。如果傳回列表中的某個項目為空字串,則將使用預設格式來顯示對應的條目。
如果需要針對 quickfix 或 location list 進行特定的自訂,則可以使用 setqflist()setloclist() 函式來設定列表的 'quickfixtextfunc' 屬性。這將覆寫全域的 'quickfixtextfunc' 選項。
下面的範例會在 quickfix 視窗中顯示舊檔案列表 (v:oldfiles)。由於每個條目沒有相關聯的行號、列號和錯誤文字資訊,因此 'quickfixtextfunc' 函式僅傳回檔案名稱。範例:
" create a quickfix list from v:oldfiles
call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f',
                                    \ 'quickfixtextfunc' : 'QfOldFiles'})
func QfOldFiles(info)
    " get information about a range of quickfix entries
    let items = getqflist({'id' : a:info.id, 'items' : 1}).items
    let l = []
    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
        " use the simplified file name
      call add(l, fnamemodify(bufname(items[idx].bufnr), ':p:.'))
    endfor
    return l
endfunc
主要
指令索引
快速參考