Usr_30

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


VIM 使用者手冊 - 作者:Bram Moolenaar
編輯程式
Vim 提供了各種輔助編寫電腦程式的指令。編譯程式並直接跳至回報的錯誤。自動為多種語言設定縮排並格式化註解。
30.1 編譯 30.2 縮排 C 檔案 30.3 自動縮排 30.4 其他縮排 30.5 Tab 和空白 30.6 格式化註解
下一章:usr_31.txt 善用 GUI 前一章:usr_29.txt 在程式中移動 目錄:usr_toc.txt

編譯

Vim 有一組所謂的「快速修正」指令。它們讓您可以從 Vim 內部編譯程式,然後檢視產生的錯誤並修正它們(希望如此)。然後您可以重新編譯並修正找到的新錯誤,直到您的程式最終編譯時沒有任何錯誤。
以下指令會執行程式「make」(提供您給定的任何引數)並捕獲結果
:make {arguments}
如果產生錯誤,它們會被捕獲,並且編輯器會將您定位到第一個發生錯誤的地方。看看一個 ":make" 會話的範例。(典型的 :make 會話會產生更多的錯誤,以及更少的愚蠢錯誤。)在輸入 ":make" 後,畫面看起來像這樣
:!make | &tee /tmp/vim215953.err
gcc -g -Wall -o prog main.c sub.c
main.c: In functionmain
main.c:6: too many arguments to function 'do_sub'
main.c: At top level
main.c:10: parse error before '}'
make: *** [prog] Error 1
2 returned
"main.c" 11L, 111C
(3 of 6): too many arguments to function 'do_sub'
按 ENTER 或輸入指令繼續
從這裡您可以看到「main.c」檔案中有錯誤。當您按下 <Enter> 時,Vim 會顯示「main.c」檔案,游標位於第 6 行,也就是第一個有錯誤的行。您不需要指定檔案或行號,Vim 會透過查看錯誤訊息來知道要去哪裡。
          +---------------------------------------------------+
          |int main()                                            |
          |{                                                    |
          |        int i=3;                                    |
cursor -> |        do_sub("foo");                                    |
          |        ++i;                                            |
          |        return (0);                                    |
          |}                                                    |
          |}                                                    |
          | ~                                                    |
          |(3 of 12): too many arguments to function 'do_sub' |
          +---------------------------------------------------+
以下指令會跳到下一個發生錯誤的地方
:cnext
Vim 會跳到第 10 行,也就是檔案中的最後一行,那裡有一個多餘的「}」。當空間不足時,Vim 會縮短錯誤訊息。若要查看完整訊息,請使用
:cc
您可以使用 ":clist" 指令取得所有錯誤訊息的概述。輸出看起來像這樣
:clist
3 main.c: 6:too many arguments to function 'do_sub'
5 main.c: 10:parse error before '}'
這裡僅列出 Vim 識別出檔案名稱和行號的行。它假設這些行是感興趣的行,其餘的只是無聊的訊息。但是,有時無法識別的行確實包含您想看到的東西。例如,連結器輸出的關於未定義函式的訊息。若要查看所有訊息,請在指令中加上「!」
:clist!
1 gcc -g -Wall -o prog main.c sub.c
2 main.c: In functionmain
3 main.c:6: too many arguments to function 'do_sub'
4 main.c: At top level
5 main.c:10: parse error before '}'
6 make: *** [prog] Error 1
Vim 會反白顯示目前的錯誤。若要回到上一個錯誤,請使用
:cprevious
在錯誤清單中移動的其他指令
:cfirst 到第一個錯誤 :clast 到最後一個錯誤 :cc 3 到錯誤編號 3

使用其他編譯器

當執行 ":make" 指令時要執行的程式名稱由 'makeprg' 選項定義。通常它會設定為「make」,但 Visual C++ 使用者應該將其設定為「nmake」,方法是執行以下指令
:set makeprg=nmake
您也可以在此選項中加入引數。特殊字元需要使用反斜線跳脫。範例
:set makeprg=nmake\ -f\ project.mak
您可以在指令規格中包含特殊的 Vim 關鍵字。% 字元會展開為目前檔案的名稱。因此,如果您執行以下指令
:set makeprg=make\ %:S
當您正在編輯 main.c 時,":make" 會執行以下指令
make main.c
這不是很有用,因此您會稍微細化指令並使用 :r(根)修飾符
:set makeprg=make\ %:r:S.o
現在執行的指令如下
make main.o
關於這些修飾符的更多資訊:filename-modifiers

舊的錯誤清單

假設您使用 ":make" 編譯一個程式。一個檔案中有警告訊息,另一個檔案中有錯誤訊息。您修正錯誤並再次使用 ":make" 來檢查是否真的已修正。現在您想查看警告訊息。它不會顯示在最後一個錯誤清單中,因為具有警告的檔案沒有再次編譯。您可以使用以下指令返回上一個錯誤清單
:colder
然後使用 ":clist" 和 ":cc {nr}" 跳到具有警告的地方。若要向前跳到下一個錯誤清單
:cnewer
Vim 會記住十個錯誤清單。

切換編譯器

您必須告訴 Vim 您的編譯器產生的錯誤訊息格式是什麼。這是透過 'errorformat' 選項來完成的。此選項的語法相當複雜,並且可以使其適用於幾乎任何編譯器。您可以在這裡找到說明:errorformat
您可能會使用各種不同的編譯器。每次都設定 'makeprg' 選項,尤其是 'errorformat' 選項並不容易。Vim 為此提供了一種簡單的方法。例如,若要切換為使用 Microsoft Visual C++ 編譯器
:compiler msvc
這會尋找「msvc」編譯器的 Vim 指令碼,並設定適當的選項。您可以編寫自己的編譯器檔案。請參閱 write-compiler-plugin

輸出重導向

":make" 指令會將已執行程式的輸出重導向至錯誤檔案。這如何運作取決於各種因素,例如 'shell'。如果您的 ":make" 指令無法捕獲輸出,請檢查 'makeef''shellpipe' 選項。'shellquote''shellxquote' 選項也可能很重要。
如果您無法讓 ":make" 為您重導向檔案,另一個替代方法是在另一個視窗中編譯程式,並將輸出重導向到檔案。然後讓 Vim 使用以下指令讀取此檔案
:cfile {filename}
跳到錯誤的運作方式將與 ":make" 指令相同。

30.2 縮排 C 樣式文字

當行已正確縮排時,程式會更容易理解。Vim 提供了各種方法來減少這項工作。對於 C 或 C 樣式的程式(如 Java 或 C++),請設定 'cindent' 選項。Vim 對於 C 程式了解甚多,並會盡力自動為您設定縮排。將 'shiftwidth' 選項設定為您想要更深層級的空格數。四個空格即可。一個 ":set" 指令即可完成
:set cindent shiftwidth=4
啟用此選項後,當您輸入類似「if (x)」的內容時,下一行會自動縮排一個額外的層級。
if (flag) 自動縮排 ---> do_the_work(); 自動取消縮排 <-- if (other_flag) { 自動縮排 ---> do_file(); 保留縮排 do_some_more(); 自動取消縮排 <-- }
當您在花括號 ({}) 中輸入內容時,文字會在開始時縮排,並在結尾時取消縮排。取消縮排會在輸入 '}' 之後發生,因為 Vim 無法猜測您將要輸入的內容。
自動縮排的一個副作用是它可以幫助您儘早發現程式碼中的錯誤。當您輸入 } 來完成函式時,卻發現自動縮排給它的縮排比您預期的還要多,這可能表示缺少一個 }。使用「%」指令找出與您輸入的 } 相符的 {。缺少 ) 和 ; 也會導致額外縮排。因此,如果您獲得的空白比預期的還要多,請檢查前面的行。
當您的程式碼格式不佳,或您插入和刪除了行時,您需要重新縮排這些行。「=」運算子可以做到這一點。最簡單的形式是
==
這會縮排目前的行。與所有運算子一樣,有三種方法可以使用它。在視覺模式中,「=」會縮排選取的行。一個有用的文字物件是「a{」。這會選取目前 {} 區塊。因此,若要重新縮排游標所在的程式碼區塊
=a{
如果您的程式碼縮排非常糟糕,您可以使用以下指令重新縮排整個檔案
gg=G
但是,不要在已仔細手動縮排的檔案中執行此操作。自動縮排的效果很好,但在某些情況下,您可能想要覆寫它。

設定縮排樣式

不同的人有不同的縮排樣式。預設情況下,Vim 在縮排方面做得相當不錯,90% 的程式設計師都這樣做。但是,有不同的樣式;因此,如果您想要,可以使用 'cinoptions' 選項自訂縮排樣式。預設情況下,'cinoptions' 為空,而 Vim 使用預設樣式。您可以在想要不同樣式的地方新增各種項目。例如,若要讓花括號像這樣放置
if (flag)
{
i = 8;
j = 0;
}
請使用此指令
:set cinoptions+={2
其中有很多這樣的項目。請參閱 cinoptions-values

30.3 自動縮排

您不希望每次編輯 C 檔案時都手動開啟 'cindent' 選項。這是讓它自動運作的方法
:filetype indent on
實際上,這不僅僅是為 C 檔案開啟 'cindent'。首先,它會啟用偵測檔案類型。這與用於語法反白顯示的方式相同。當檔案類型已知時,Vim 會搜尋此類型檔案的縮排檔案。Vim 發行版包含許多用於各種程式設計語言的縮排檔案。然後,此縮排檔案會準備好針對此檔案的自動縮排。
如果您不喜歡自動縮排,可以再次將其關閉
:filetype indent off
如果您不喜歡針對某種特定檔案類型的縮排,可以這樣避免它。建立一個只有這一行的檔案
:let b:did_indent = 1
現在您需要將其寫入具有特定名稱的檔案
{directory}/indent/{filetype}.vim
{filetype} 是檔案類型的名稱,例如「cpp」或「java」。您可以使用以下指令查看 Vim 偵測到的確切名稱
:set filetype
在此檔案中,輸出為
filetype=help
因此,您會將「help」用於 {filetype}。對於 {directory} 部分,您需要使用您的執行時間目錄。請查看以下指令的輸出
set runtimepath
現在使用第一個項目,也就是第一個逗號之前的名稱。因此,如果輸出看起來像這樣
runtimepath=~/.config/nvim,/usr/local/share/vim/vim60/runtime,~/.config/nvim/after
您會將 "~/.config/nvim" 用於 {directory}。然後產生的檔案名稱為
~/.config/nvim/indent/help.vim
您也可以撰寫自己的縮排檔案,而不是關閉縮排功能。如何執行此操作在此處說明:indent-expression

30.4 其他縮排

最簡單的自動縮排形式是使用 'autoindent' 選項。它會使用前一行的縮排。稍微聰明一點的是 'smartindent' 選項。這對於沒有縮排檔案可用的語言很有用。'smartindent' 沒有 'cindent' 那麼聰明,但比 'autoindent' 聰明。設定 'smartindent' 後,每個 { 都會增加一個縮排層級,每個 } 都會移除一個縮排層級。對於 'cinwords' 選項中的任何單字,也會增加一個縮排層級。以 # 開頭的行會被特殊處理:所有縮排都會被移除。這樣做的目的是為了讓前置處理器指令都從第一欄開始。縮排會在下一行恢復。

修正縮排

當您使用 'autoindent''smartindent' 來取得前一行的縮排時,很多時候您需要新增或移除一個 'shiftwidth' 的縮排。一個快速的方法是在插入模式中使用 CTRL-D 和 CTRL-T 命令。例如,您正在輸入一個應該像這樣的 shell 腳本
if test -n a; then
echo a
echo "-------"
fi
首先設定這些選項
:set autoindent shiftwidth=3
您先輸入第一行,<Enter>,然後輸入第二行的開頭
if test -n a; then
echo
現在您發現您需要額外的縮排。輸入 CTRL-T。結果是
if test -n a; then
echo
在插入模式中,CTRL-T 命令會在行中的任何位置新增一個 'shiftwidth' 的縮排。您繼續輸入第二行,<Enter>,然後輸入第三行。這次縮排沒問題。然後 <Enter>,最後一行。現在您有這個
if test -n a; then
echo a
echo "-------"
fi
要移除最後一行多餘的縮排,請按 CTRL-D。這會刪除一個 'shiftwidth' 的縮排,無論您在行中的哪個位置。當您處於普通模式時,您可以使用 ">>" 和 "<<" 命令來移動行。「>」和「<」是運算子,因此您可以使用通常的三種方式來指定要縮排的行。一個有用的組合是
>i{
這會將縮排新增到目前的大括號 {} 內的程式碼區塊中。{ 和 } 行本身保持不變。「>a{」會包含它們。在此範例中,游標位於 "printf" 上
原始文字 「>i{」之後 「>a{」之後
if (flag) if (flag) if (flag)
{ { {
printf("yes"); printf("yes"); printf("yes");
flag = 0; flag = 0; flag = 0;
} } }

30.5 Tab 鍵和空格

'tabstop' 預設設定為 8。雖然您可以變更它,但您很快就會遇到麻煩。其他程式不會知道您使用的 tabstop 值。它們可能會使用預設值 8,您的文字突然看起來會非常不同。此外,大多數印表機都使用固定的 tabstop 值 8。因此,最好保持 'tabstop' 不變。(如果您編輯以不同 tabstop 設定撰寫的檔案,請參閱 25.3 以了解如何修正。)為了縮排程式中的行,使用 8 個空格的倍數會讓您很快地到達視窗的右邊界。使用單個空格無法提供足夠的視覺差異。許多人喜歡使用 4 個空格,這是一個很好的折衷方案。由於 <Tab> 是 8 個空格,而您想使用 4 個空格的縮排,因此您無法使用 <Tab> 字元來建立縮排。有兩種方法可以處理這個問題
1. 使用 <Tab> 和空格字元的組合。由於 <Tab> 取代 8 個空格的位置,因此您的檔案中的字元較少。插入 <Tab> 比插入 8 個空格更快。倒退也更快。
2. 僅使用空格。這可以避免程式使用不同 tabstop 值時產生的問題。
幸運的是,Vim 非常支援這兩種方法。

空格和 Tab 鍵

如果您使用的是 Tab 鍵和空格的組合,您只需正常編輯即可。Vim 預設值可以很好地處理這些問題。您可以透過設定 'softtabstop' 選項來讓生活更輕鬆一點。此選項會告訴 Vim 讓 <Tab> 鍵看起來和感覺像是將 Tab 鍵設定為 'softtabstop' 的值一樣,但實際上使用的是 Tab 鍵和空格的組合。執行以下命令後,每次按下 <Tab> 鍵時,游標都會移動到下一個 4 個欄位的邊界
:set softtabstop=4
當您從第一欄開始並按下 <Tab> 時,會在您的文字中插入 4 個空格。第二次時,Vim 會取出 4 個空格並放入一個 <Tab> (因此將您帶到第 8 欄)。因此,Vim 會盡可能使用多的 <Tab>,然後以空格填滿。倒退時,其運作方式相反。<BS> 將始終刪除 'softtabstop' 指定的數量。然後,盡可能多地使用 <Tab>,並以空格填補間隙。以下顯示按下 <Tab> 鍵幾次,然後使用 <BS> 時會發生什麼。「.」代表空格,而「------->」代表 <Tab>
輸入 結果
<Tab> .... <Tab><Tab> -------> <Tab><Tab><Tab> ------->.... <Tab><Tab><Tab><BS> -------> <Tab><Tab><Tab><BS><BS> ....
另一種選擇是使用 'smarttab' 選項。當它設定時,Vim 會使用 'shiftwidth' 來表示在行的縮排中輸入的 <Tab>,並在第一個非空白字元後輸入時使用真正的 <Tab>。但是,<BS> 的運作方式與 'softtabstop' 不同。

僅限空格

如果您希望檔案中絕對沒有 Tab 鍵,則可以設定 'expandtab' 選項
:set expandtab
當設定此選項時,<Tab> 鍵會插入一系列空格。因此,您會得到與插入 <Tab> 字元時相同的空白量,但您的檔案中沒有真正的 <Tab> 字元。倒退鍵將單獨刪除每個空格。因此,在輸入一個 <Tab> 之後,您必須按下 <BS> 鍵最多八次才能還原它。如果您處於縮排中,按下 CTRL-D 會更快。

將 Tab 鍵變更為空格 (以及反向變更)

設定 'expandtab' 不會影響任何現有的 Tab 鍵。換句話說,文件中任何的 Tab 鍵都仍是 Tab 鍵。如果您想將 Tab 鍵轉換為空格,請使用 ":retab" 命令。使用這些命令
:set expandtab
:%retab
現在,Vim 會將所有縮排變更為使用空格而非 Tab 鍵。但是,所有在非空白字元之後的 Tab 鍵都會被保留。如果您也希望轉換這些 Tab 鍵,請新增一個 !
:%retab!
這有點危險,因為它也可能會變更字串內的 Tab 鍵。若要檢查這些是否存在,您可以使用這個
/"[^"\t]*\t[^"]*"
建議不要在字串內使用硬 Tab 鍵。將它們取代為 "\t" 以避免麻煩。
另一種方式也同樣有效
:set noexpandtab
:%retab!

30.6 設定註解格式

Vim 的其中一個優點是它了解註解。您可以要求 Vim 設定註解的格式,它會執行正確的操作。例如,假設您有以下註解
/*
 * This is a test
 * of the text formatting.
 */
然後,您將游標放在註解的開頭,然後輸入
gq]/
"gq" 是設定文字格式的運算子。"]/" 是將您帶到註解結尾的移動。結果是
/*
 * This is a test of the text formatting.
 */
請注意,Vim 正確處理了每一行的開頭。另一種方法是在視覺模式中選取要設定格式的文字,然後輸入 "gq"。
若要將新行新增至註解,請將游標放在中間行上,然後按 "o"。結果如下所示
/*
 * This is a test of the text formatting.
 *
 */
Vim 會自動為您插入星號和空格。現在您可以輸入註解文字。當它長度超過 'textwidth' 時,Vim 會斷行。同樣,會自動插入星號
/*
 * This is a test of the text formatting.
 * Typing a lot of text here will make Vim
 * break
 */
為了讓它運作,'formatoptions' 中必須存在一些旗標
r 在插入模式中輸入 <Enter> 時插入星號 o 在普通模式中使用 "o" 或 "O" 時插入星號 c 根據 'textwidth' 斷開註解文字
請參閱 fo-table 以取得更多旗標。
定義註解
'comments' 選項定義註解的外觀。Vim 會區分單行註解和具有不同開頭、結尾和中間部分的註解。許多單行註解都以特定字元開頭。在 C++ 中使用 //,在 Makefiles 中使用 #,在 Vim 腳本中使用 "."。例如,若要讓 Vim 了解 C++ 註解
:set comments=://
冒號將專案的旗標與註解所識別的文字分開。'comments' 中專案的一般形式為
{flags}:{text}
{flags} 部分可以是空白的,如本例中所示。這些專案中的多個可以串聯起來,並以逗號分隔。這允許同時識別不同類型的註解。例如,讓我們編輯電子郵件訊息。回覆時,其他人撰寫的文字會以 ">" 和 "!" 字元開頭。此命令會有效
:set comments=n:>,n:!
有兩個專案,一個用於以 ">" 開頭的註解,另一個用於以 "!" 開頭的註解。兩者都使用 "n" 旗標。這表示這些註解會巢狀結構。因此,以 ">" 開頭的行可能會在 ">" 之後有另一個註解。這允許設定像這樣的訊息格式
> ! 你有看到那個網站嗎?
> ! 它看起來真的很棒。
> 我不喜歡它。這個
> 顏色很糟糕。
那個網站的網址是什麼
網站?
試著將 'textwidth' 設定為不同的值,例如 80,並透過視覺化選取文字並輸入 "gq" 來設定文字格式。結果是
> ! 你有看到那個網站嗎?它看起來真的很棒。
> 我不喜歡它。顏色很糟糕。
那個網站的網址是什麼?
您會注意到 Vim 沒有將文字從一種註解移動到另一種註解。第二行中的 "I" 本來可以放在第一行的結尾,但由於該行以 "> !" 開頭,而第二行以 ">" 開頭,因此 Vim 知道這是不同種類的註解。
三部分註解
C 註解以 "/*" 開頭,中間有 "*",結尾有 "*/"。'comments' 中此項的輸入看起來像這樣
:set comments=s1:/*,mb:*,ex:*/
起始定義為「s1:/*」。其中「s」表示三段式註解的起始。「:」號將標記與註解辨識文字「/*」分開。標記只有一個:「1」。這告訴 Vim 中間部分有一個空格的偏移量。中間部分「mb:*」以「m」開頭,表示它是中間部分。「b」標記表示文字後必須跟隨一個空格。否則,Vim 會認為像「*pointer」這樣的文字也是註解的中間部分。結束部分「ex:*/」的「e」用於識別。「x」標記具有特殊含義。這表示在 Vim 自動插入星號後,輸入 / 將刪除額外的空格。
更多詳細資訊請參閱format-comments
下一章:usr_31.txt 探索 GUI
版權:請參閱manual-copyright vim:tw=78:ts=8:noet:ft=help:norl
主要
指令索引
快速參考