摺疊

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


摺疊 folding folds
您可以在使用者手冊的第 28 章找到有關摺疊的介紹。usr_28.txt

1. 摺疊方法 fold-methods

可以使用 'foldmethod' 選項設定摺疊方法。
當將 'foldmethod' 設定為 "manual" 以外的值時,所有摺疊都會被刪除並建立新的摺疊。切換到 "manual" 方法並不會刪除現有的摺疊。這可以用來先自動定義摺疊,然後手動變更它們。
有六種方法可以選取摺疊:manual 手動定義摺疊 indent 縮排越多表示摺疊層級越高 expr 指定一個表達式來定義摺疊 syntax 透過語法高亮定義摺疊 diff 未變更文字的摺疊 marker 透過文字中的標記定義摺疊
使用命令手動定義摺疊區域。這也可以被腳本使用,解析文字來尋找摺疊。
摺疊的層級僅由其巢狀結構定義。要增加一行範圍的摺疊層級,請在其中定義具有相同行的摺疊。
當您放棄檔案時,手動摺疊會遺失。要儲存摺疊,請使用 :mkview 命令。該視圖稍後可以使用 :loadview 還原。
摺疊會根據行的縮排自動定義。
摺疊層級是根據行的縮排除以 'shiftwidth'(向下取整)計算得出的。一系列具有相同或更高摺疊層級的行構成一個摺疊,具有更高層級的行形成一個巢狀摺疊。
摺疊的巢狀結構受 'foldnestmax' 限制。
某些行會被忽略,並取得上方或下方行的摺疊層級,取兩者中較低者。這些是空白行或空格行,以及以 'foldignore' 中的字元開頭的行。在檢查 'foldignore' 中的字元之前,會跳過空白字元。對於 C 語言,使用 "#" 來忽略預處理器行。
當您想要以其他方式忽略行時,請使用 "expr" 方法。indent() 函數可以在 'foldexpr' 中使用,以取得行的縮排。
摺疊會根據其摺疊層級自動定義,就像 "indent" 方法一樣。評估 'foldexpr' 選項的值以取得行的摺疊層級。範例:這將為所有以 tab 開頭的連續行建立一個摺疊
:set foldexpr=getline(v:lnum)[0]==\"\\t\"
這會將段落分隔為空白行
:set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1
這會做同樣的事情
:set foldexpr=getline(v:lnum-1)=~'^\\s*$'&&getline(v:lnum)=~'\\S'?'>1':1
請注意,必須使用反斜線來跳脫 ":set" 處理方式不同的字元(空格、反斜線、雙引號等,請參閱 option-backslash)。
最有效的方法是呼叫不帶參數的函數
:set foldexpr=MyFoldLevel()
該函數必須使用 v:lnum。請參閱 expr-option-function
以下是評估表達式的條件
目前緩衝區和視窗是為該行設定的。
變數 "v:lnum" 設定為行號。
結果用於摺疊層級的方式如下:值 意義 ~ 0 該行不在摺疊中 1, 2, .. 該行在具有此層級的摺疊中 -1 摺疊層級未定義,使用此行之前或之後的行的摺疊層級,取兩者中較低者。 "=" 使用上一行的摺疊層級 "a1", "a2", .. 將上一行的摺疊層級加一、加二,.. ,使用結果作為目前行的摺疊層級 "s1", "s2", .. 從上一行的摺疊層級減一、減二,.. ,使用結果作為下一行的摺疊層級 "<1", "<2", .. 具有此層級的摺疊在此行結束 ">1", ">2", .. 具有此層級的摺疊在此行開始
不需要使用 ">1" ("<1") 標記摺疊的開始(結束),當摺疊層級高於(低於)上一行的摺疊層級時,摺疊也會開始(結束)。
表達式不得有副作用。緩衝區中的文字、游標位置、搜尋模式、選項等不得變更。如果小心,您可以變更並還原它們。
如果表達式中存在一些錯誤,或者結果值無法辨識,則不會出現錯誤訊息,並且摺疊層級將為零。為了進行偵錯,可以將 'debug' 選項設定為 "msg",屆時錯誤訊息將可見。
注意:由於必須為每一行評估表達式,因此此摺疊方法可能會非常慢!
盡量避免使用 "="、"a" 和 "s" 回傳值,因為 Vim 通常必須向後搜尋定義摺疊層級的行。這可能會很慢。
如果 'foldexpr' 表達式以 s: 或 <SID> 開頭,則它會被腳本 ID 取代(local-function)。範例
set foldexpr=s:MyFoldExpr()
set foldexpr=<SID>SomeFoldExpr()
使用 "a1" 和 "s1" 的範例:對於多行 C 註解,包含 "/*" 的行會回傳 "a1" 來開始摺疊,而包含 "*/" 的行會回傳 "s1" 以在該行之後結束摺疊
if match(thisline, '/\*') >= 0
  return 'a1'
elseif match(thisline, '\*/') >= 0
  return 's1'
else
  return '='
endif
但是,這不適用於單行註解、字串等。
foldlevel() 可以用於計算相對於先前摺疊層級的摺疊層級。但請注意,如果層級尚未知,foldlevel() 可能會回傳 -1。而且它會回傳行首的層級,而摺疊可能會在該行結束。
摺疊可能無法正確更新。您可以使用 zxzX 強制更新摺疊。
摺疊由具有 "fold" 引數的語法項目定義。:syn-fold
摺疊層級由巢狀摺疊定義。摺疊的巢狀結構受 'foldnestmax' 限制。
請小心指定正確的語法同步。如果沒有正確執行,摺疊可能會與顯示的高亮不同。當使用比對多行的模式時,這一點尤其相關。如果存有疑問,請嘗試使用暴力同步
:syn sync fromstart

DIFF fold-diff

摺疊是針對不屬於變更或接近變更的文字自動定義的。
只有在為目前的視窗設定 'diff' 選項並顯示變更時,此方法才能正常運作。否則,整個緩衝區將會是一個大型摺疊。
可以使用 'diffopt' 選項指定內容。也就是說,不包含在摺疊中的摺疊和變更之間的行數。例如,要使用 8 行的內容
:set diffopt=filler,context:8
預設內容為六行。
當同時設定 'scrollbind' 時,Vim 會嘗試在其他 diff 視窗中保持相同的摺疊開啟,以便可以看見相同的文字。
文字中的標記會告訴摺疊的開始和結束位置。這讓您可以精確地指定摺疊。這將允許刪除和放置摺疊,而不會有包含錯誤行的風險。'foldtext' 選項通常設定為在摺疊行中顯示標記之前的文字。這使得可以為摺疊命名。
標記可以包含層級,也可以使用比對的配對。包含層級更容易,您不必新增結束標記,並且避免不匹配的標記配對問題。範例
/* global variables {{{1 */
int varA, varB;
/* functions {{{1 */
/* funcA() {{{2 */
void funcA() {}
/* funcB() {{{2 */
void funcB() {}
{{{ }}} 摺疊從 "{{{" 標記開始。以下數字指定摺疊層級。會發生什麼情況取決於目前摺疊層級與標記給定的層級之間的差異:1. 如果遇到具有相同摺疊層級的標記,則先前的摺疊結束,並且開始另一個具有相同層級的摺疊。2. 如果找到具有更高摺疊層級的標記,則會開始巢狀摺疊。3. 如果找到具有較低摺疊層級的標記,則會結束到此層級(包含此層級)的所有摺疊,並且會開始具有指定層級的摺疊。
該數字表示摺疊層級。不能使用零(會忽略層級為零的標記)。您可以使用帶有數字的 "}}}" 來表示結束的摺疊的層級。下一行的摺疊層級將比指示的層級少一。請注意,Vim 不會回頭查看匹配標記的層級(那會花費太多時間)。範例
{{{1
fold level here is 1
{{{3
fold level here is 3
}}}3
fold level here is 2
您也可以使用 "{{{" 和 "}}}" 標記的匹配配對來定義摺疊。每個 "{{{" 會將摺疊層級增加一,每個 "}}}" 會將摺疊層級減少一。請小心保持標記匹配!範例
{{{
fold level here is 1
{{{
fold level here is 2
}}}
fold level here is 1
您可以混合使用帶有數字和不帶有數字的標記。一種有用的方法是為大型摺疊使用編號標記,並在本機函數中使用未編號的標記。例如,為您檔案的章節(例如「結構定義」、「區域變數」和「函數」)使用第一層摺疊。為每個定義和函數使用第二層標記,在函數內使用未編號的標記。當您變更函數以分割摺疊時,不必重新編號標記。
可以使用 'foldmarker' 選項設定標記。建議將其保持在預設值 "{{{,}}}",以便可以在 Vim 使用者之間交換檔案。僅當檔案需要時才變更它(例如,它包含來自其他摺疊編輯器的標記,或預設標記為檔案的語言造成問題)。
fold-create-marker
"zf" 可以用來建立由標記定義的摺疊。Vim 會為您插入標記。Vim 會附加開始和結束標記,如 'foldmarker' 中所指定。標記會附加到行尾。'commentstring' 會在不為空時使用。當以下情況時,這無法正常運作
該行已經包含具有層級編號的標記。然後 Vim 不知道該怎麼做。
附近的摺疊在其標記中使用會造成干擾的層級編號。
該行位於註解內,'commentstring' 不為空,且巢狀註解無法運作。例如,對於 C:在註解中新增 /* {{{ */ 會截斷現有的註解。請將標記放在註解之前或之後,或手動新增標記。一般而言,當您已經有帶有層級編號的標記時,讓 Vim 建立標記並不是一個好主意。
fold-delete-marker
"zd" 可以用來刪除由標記定義的摺疊。Vim 會為您刪除標記。Vim 會在摺疊的開始和結束處搜尋開始和結束標記,如 'foldmarker' 中所指定。當標記周圍的文字與 'commentstring' 比對時,也會刪除該文字。當以下情況時,這無法正常運作
一行包含多個標記,其中一個標記指定層級。僅會移除第一個標記,而不會檢查這是否會達到刪除摺疊的預期效果。
標記包含一個層級編號,用於同時開始或結束多個摺疊。

2. 摺疊指令 fold-commands E490

所有摺疊指令都以 "z" 開頭。提示:從側面看,"z" 看起來像一張摺疊的紙。
建立和刪除摺疊
zf E350 zf{motion} 或 {Visual}zf 操作符用於建立摺疊。僅當 'foldmethod' 為 "manual" 或 "marker" 時才有效。新的摺疊對於 "manual" 方法將會是關閉的。'foldenable' 將會被設定。另請參閱 fold-create-marker
zF
zF 為 [count] 行建立摺疊。作用類似於 "zf"。
:{range}fo[ld] :fold :fo{range} 中的行建立摺疊。作用類似於 "zf"。
zd E351 zd 刪除游標處的一個摺疊。當游標位於摺疊的行上時,該摺疊將被刪除。巢狀摺疊會向上移動一層。在視覺模式下,選定區域中(部分)的所有摺疊的一層會被刪除。注意:這很容易刪除比您預期的更多摺疊,並且手動摺疊沒有復原功能。僅當 'foldmethod' 為 "manual" 或 "marker" 時才有效。另請參閱 fold-delete-marker
zD
zD 遞迴刪除游標處的摺疊。在視覺模式下,選定區域中(部分)的所有摺疊以及其中的所有巢狀摺疊都會被刪除。僅當 'foldmethod' 為 "manual" 或 "marker" 時才有效。另請參閱 fold-delete-marker
zE E352 zE 消除視窗中的所有摺疊。僅當 'foldmethod' 為 "manual" 或 "marker" 時才有效。另請參閱 fold-delete-marker
開啟和關閉摺疊
小於 'foldminlines' 的摺疊將始終顯示為已開啟。因此,下面的命令在小型摺疊上的運作方式可能有所不同。
zo
zo 開啟游標下的一個摺疊。當給定計數時,將會開啟該深度層級的摺疊。在視覺模式下,選定區域中所有行的摺疊都會開啟一層。
zO
zO 遞迴開啟游標下的所有摺疊。不包含游標行的摺疊將保持不變。在視覺模式下,它會開啟選定區域中的所有摺疊,也包括那些僅部分選定的摺疊。
zc
zc 關閉游標下的一個摺疊。當給定計數時,將會關閉該深度層級的摺疊。在視覺模式下,選定區域中所有行的摺疊都會關閉一層。'foldenable' 將會被設定。
zC
zC 遞迴關閉游標下的所有摺疊。不包含游標行的摺疊將保持不變。在視覺模式下,它會關閉選定區域中的所有摺疊,也包括那些僅部分選定的摺疊。'foldenable' 將會被設定。
za
za 摘要:切換游標下的摺疊。當在關閉的摺疊上時:開啟它。當摺疊是巢狀時,您可能需要多次使用 "za"。當給定計數時,將會開啟該數量的關閉摺疊。當在開啟的摺疊上時:關閉它並設定 'foldenable'。這只會關閉一層,因為再次使用 "za" 會開啟摺疊。當給定計數時,將會關閉該數量的摺疊(這與重複多次 "za" 不同)。
zA
zA 當在關閉的摺疊上時:遞迴開啟它。當在開啟的摺疊上時:遞迴關閉它並設定 'foldenable'
zv
zv 檢視游標行:開啟足夠的摺疊以使游標所在的行不被摺疊。
zx
zx 更新摺疊:復原手動開啟和關閉的摺疊:重新套用 'foldlevel',然後執行 "zv":檢視游標行。還會強制重新計算摺疊。當使用 'foldexpr' 並且緩衝區以導致摺疊無法正確更新的方式變更時,這很有用。
zX
zX 復原手動開啟和關閉的摺疊:重新套用 'foldlevel'。還會強制重新計算摺疊,如同 zx
zm
zm 摺疊更多:從 'foldlevel' 中減去 v:count1。如果 'foldlevel' 已為零,則不會發生任何事。'foldenable' 將會被設定。
zM
zM 關閉所有摺疊:將 'foldlevel' 設定為 0。'foldenable' 將會被設定。
zr
zr 減少摺疊:將 v:count1 加到 'foldlevel'
zR
zR 開啟所有摺疊。這會將 'foldlevel' 設定為最高摺疊層級。
:foldo :foldopen :{range}foldo[pen][!] 開啟 {range} 中的摺疊。當加上 [!] 時,所有摺疊都會開啟。用於查看 {range} 中的所有文字很有用。沒有 [!] 時,會開啟一層摺疊。
:foldc :foldclose :{range}foldc[lose][!] 關閉 {range} 中的摺疊。當加上 [!] 時,所有摺疊都會關閉。用於隱藏 {range} 中的所有文字很有用。沒有 [!] 時,會關閉一層摺疊。
zn
zn 不摺疊:重設 'foldenable'。所有摺疊都會開啟。
zN
zN 正常摺疊:設定 'foldenable'。所有摺疊都會恢復到之前的狀態。
zi
zi 反轉 'foldenable'
在摺疊之間移動
[z
[z 移動到目前開啟的摺疊的開始處。如果已經在開始處,則移動到包含它的摺疊的開始處。如果沒有包含摺疊,則命令失敗。當使用計數時,會重複執行該命令 [count] 次。
]z
]z 移動到目前開啟的摺疊的結尾處。如果已經在結尾處,則移動到包含它的摺疊的結尾處。如果沒有包含摺疊,則命令失敗。當使用計數時,會重複執行該命令 [count] 次。
zj
zj 向下移動到下一個摺疊的開始處。關閉的摺疊算作一個摺疊。當使用計數時,會重複執行該命令 [count] 次。此命令可以在 operator 之後使用。
zk
zk 向上移動到上一個摺疊的結尾處。關閉的摺疊算作一個摺疊。當使用計數時,會重複執行該命令 [count] 次。此命令可以在 operator 之後使用。
對摺疊執行命令
:[range]foldd[oopen] {cmd} :foldd :folddo :folddoopen 對所有不在關閉摺疊中的行執行 {cmd}。當給定 [range] 時,僅使用這些行。每次執行 {cmd} 時,游標都會定位在執行該命令的行上。這與 ":global" 命令的作用類似:首先標記所有不在關閉摺疊中的行。然後對所有標記的行執行 {cmd}。因此,當 {cmd} 變更摺疊時,這不會影響其執行位置(當然,除非刪除了行)。範例
:folddoopen s/end/loop_end/ge
請注意使用 "e" 旗標以避免在 "end" 不匹配時出現錯誤訊息。
:[range]folddoc[losed] {cmd} :folddoc :folddoclosed 對所有在關閉摺疊中的行執行 {cmd}。其他方面與 ":folddoopen" 相同。

3. 摺疊選項 fold-options

關閉摺疊的顏色由 Folded 群組設定 hl-Folded。摺疊欄的顏色由 FoldColumn 群組設定 hl-FoldColumn。設定顏色的範例
:highlight Folded guibg=grey guifg=blue
:highlight FoldColumn guibg=darkgrey guifg=white

FOLDLEVEL fold-foldlevel

'foldlevel' 是一個數字選項:值越高,開啟的摺疊區域就越多。當 'foldlevel' 為 0 時,所有摺疊都會關閉。當 'foldlevel' 為正數時,某些摺疊會關閉。當 'foldlevel' 非常高時,所有摺疊都會開啟。'foldlevel' 會在變更時套用。之後,可以手動開啟和關閉摺疊。當增加時,高於新層級的摺疊會開啟。不會關閉任何手動開啟的摺疊。當減少時,高於新層級的摺疊會關閉。不會開啟任何手動關閉的摺疊。

FOLDTEXT fold-foldtext

'foldtext' 是一個字串選項,用於指定一個表達式。此表達式會被評估以取得關閉摺疊所顯示的文字。範例
:set foldtext=v:folddashes.substitute(getline(v:foldstart),'/\\*\\\|\\*/\\\|{{{\\d\\=','','g')
這會顯示摺疊的第一行,並移除 "/*"、"*/" 和 "{{{"。請注意使用反斜線來避免某些字元被 ":set" 命令解譯。定義一個函數並調用它會簡單得多
:set foldtext=MyFoldText()
:function MyFoldText()
:  let line = getline(v:foldstart)
:  let sub = substitute(line, '/\*\|\*/\|{{{\d\=', '', 'g')
:  return v:folddashes .. sub
:endfunction
評估 'foldtext' 是在 sandbox 中完成的。目前的視窗會設定為顯示該行的視窗。
錯誤會被忽略。對於除錯,請將 'debug' 選項設定為 "throw"。
預設值為 foldtext()。這會為大多數類型的摺疊返回合理的文字。如果您不喜歡它,您可以指定自己的 'foldtext' 表達式。它可以使用這些特殊的 Vim 變數:v:foldstart 摺疊中第一行的行號 v:foldend 摺疊中最後一行的行號 v:folddashes 包含虛線以表示摺疊層級的字串。v:foldlevel 摺疊的摺疊層級
如果結果是 List,則會像「覆蓋」虛擬文字一樣進行剖析和繪製(請參閱 nvim_buf_set_extmark()),否則結果會轉換為字串,其中 TAB 會被空格取代,並且不可列印的字元會變成可列印的字元。
產生的行會被截斷以適合視窗,它永遠不會換行。當文字之後有空間時,它會使用 'fillchars' 所指定的字元填滿。
如果 'foldtext' 表達式以 s: 或 <SID> 開頭,則會將其替換為腳本 ID(local-function)。範例
set foldtext=s:MyFoldText()
set foldtext=<SID>SomeFoldText()
請注意,反斜線需要用於 ":set" 命令處理方式不同的字元:空格、反斜線和雙引號。option-backslash

FOLDCOLUMN fold-foldcolumn

'foldcolumn' 是一個數字,設定視窗側邊欄的寬度,以指示摺疊。當它為零時,則沒有摺疊欄。一個正常的值是 auto:9。最大值為 9。
一個開啟的摺疊會以頂部有一個 '-',下方有 '|' 字元的欄位指示。此欄位會在開啟的摺疊停止處停止。當摺疊巢狀時,巢狀摺疊會在其包含的摺疊右邊一個字元的位置。
一個關閉的摺疊會以 '+' 指示。
這些字元可以使用 'fillchars' 選項進行更改。
當摺疊欄太窄而無法顯示所有巢狀摺疊時,會顯示數字以指示巢狀層級。
滑鼠也可以通過點擊摺疊欄來開啟和關閉摺疊。
點擊 '+' 以開啟此列中關閉的摺疊。
點擊任何其他非空白字元以關閉此列中開啟的摺疊。

其他選項

'foldenable' 'fen': 未設定時開啟所有摺疊。'foldexpr' 'fde': 用於 "expr" 摺疊的表達式。'foldignore' 'fdi': 用於 "indent" 摺疊的字元。'foldmarker' 'fmr': 用於 "marker" 摺疊的定義標記。'foldmethod' 'fdm': 目前摺疊方法的名稱。'foldminlines' 'fml': 摺疊以關閉顯示的最小螢幕行數。'foldnestmax' 'fdn': "indent" 和 "syntax" 摺疊的最大巢狀層級。'foldopen' 'fdo': 哪些指令會開啟關閉的摺疊。'foldclose' 'fcl': 當游標下的摺疊未關閉時。

4. 摺疊的行為 fold-behavior

當向上或向下移動游標以及滾動時,游標將移動到一連串摺疊行的第一行。當游標已經在摺疊的行上時,它會移動到下一個未摺疊的行或下一個關閉的摺疊。
當游標在摺疊的行上時,游標始終顯示在第一列。尺規會顯示實際游標位置,但由於該行已摺疊,因此無法在那裡顯示。
許多移動命令會將一連串摺疊的行視為空行。例如,「w」命令會在第一列停止一次。
當在關閉的摺疊中開始搜尋時,它不會在目前的摺疊中找到匹配項。這就像向前搜尋始終從關閉的摺疊末尾開始,而向後搜尋則從關閉的摺疊開始處開始。
當處於插入模式時,游標行永遠不會被摺疊。這讓您可以看到您輸入的內容!
當使用運算子時,關閉的摺疊會作為整體包含在內。因此,「dl」會刪除游標下整個關閉的摺疊。
對於在緩衝區行上工作的 Ex 命令,範圍會調整為始終從關閉的摺疊的第一行開始,並在關閉的摺疊的最後一行結束。因此,此命令
:s/foo/bar/g
當游標位於關閉的摺疊上使用時,會將摺疊的所有行中的「foo」替換為「bar」。這不會發生在 :folddoopen:folddoclosed
當編輯先前編輯過的緩衝區時,會再次使用上次使用的摺疊設定。對於手動摺疊,會還原定義的摺疊。對於所有摺疊方法,會還原手動開啟和關閉的摺疊。如果此緩衝區已在此視窗中編輯過,則會使用當時的值。否則,會使用上次編輯該緩衝區的視窗中的值。
主要
指令索引
快速參考