fold

fold.txt 适用于 Vim 9.0 版本。 最近更新: 2023年2月 VIM 参考手册 by Bram Moolenaar 译者: Zimin<cranecai@users.sf.net>、tocer 折叠 Folding folding folds 你可以在用户手册的第 28 章找到有关折叠的序论。 usr_28.txt 1. 折叠方法 fold-methods 2. 折叠命令 fold-commands 3. 折叠选项 fold-options 4. 折叠行为 fold-behavior {仅当编译时加入 +folding 特性才有效}

1. 折叠方法 fold-methods

可用选项 'foldmethod' 来设定折叠方法。 设置选项 'foldmethod' 为非 "manual" 的其它值时,所有的折叠都会被删除并且创建新 的。如果设置成 "manual",将不去除已有的折叠。可以利用这一点来先自动定义折叠, 然后手工调整。 有 6 种方法来选定折叠: manual 手工定义折叠 indent 更多的缩进表示更高级别的折叠 expr 用表达式来定义折叠 syntax 用语法高亮来定义折叠 diff 对没有更改的文本进行折叠 marker 对文中的标志折叠 手 工 fold-manual 使用命令来手工定义要折叠的范围。分析文本并发现折叠的脚本也可用这种方法。 折叠的级别仅由嵌套次数来定义。要对一定行数的折叠增加级别,可以对相同的行反复定 义折叠。 当你退出文件编辑时,手工折叠会被遗弃。要保存折叠,使用 :mkview 命令。之后要 恢复可以使用 :loadview 。 缩 进 fold-indent 由缩进行自动定义折叠。 折叠级别由行的缩进除以 'shiftwidth' (向下取整) 计算而得。连续的,有同样或更高 的折叠级别的行,形成一个折叠。在其中,有更高折叠级别的行形成嵌套的折叠。 嵌套的级别数受 'foldnestmax' 选项限制。 某些行会被忽略并得到上一行或下一行的折叠级别 (取较小值)。符合条件的这样的行要 么是空行,要么以 'foldignore' 选项里包含的字符开始。在查找 'foldignore' 里包含 的字符时,空白字符会被忽略。对于 C,该选项使用 "#" 来略过要预处理的那些行。 当你想用另一种方式来略过行时,使用 "expr" 方法。在 'foldexpr'indent() 函 数被用来取得一行的缩进。 表 达 式 fold-expr 就像用 "indent" 方式一样,表达式方式的折叠也是由折叠级别自动定义的。对每行,通 过计算选项 'foldexpr' 的值来并得到它的折叠级别。如: 对所有以制表符开始的连续的几行,创建折叠: :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,2 等 -1 折叠级别没有定义,使用这行之前或之后一行的级别值,取其 中较小的一个。 "=" 使用上一行的折叠级别。 "a1", "a2", .. 上一行的折叠级别加 1,2,..,结果适用于当前行 "s1", "s2", .. 上一行的折叠级别减 1,2,..,结果适用于当前行 "<1", "<2", .. 此折叠级别在本行结束 ">1", ">2", .. 此折叠级别在本行开始 不需要用 ">1" ("<1") 标志折叠的开始 (结束)。当这行折叠级别高于 (低于) 上一行的 级别时,折叠将开始 (结束)。 表达式必须没有副作用。在缓冲区里的文字,光标位置,查找模式,选项等等,不能被改 动。如果你非常小心,改动并恢复这些设置还是可以的。 表达式中有错误或者计算结果不能识别时,Vim 不会产生错误消息,而是将折叠级别设为 0。所以当需要调试时,可将 '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() 计算相对于上一折叠级别的折叠级别。但要注意,如果该级别未知, foidlevel() 返回 -1。它返回的级别对应于该行开始的位置,尽管折叠本身可能在该行 结束。 折叠可能会没有及时更新。用 zx 或者 zX 可以强制折叠更新。 语 法 fold-syntax 由带有 "fold" 参数的语法项来定义折叠。 :syn-fold 折叠级别由嵌套的折叠层数来定义。嵌套数由 'foldnestmax' 限定。 要小心指定合适的语法同步方式。如果这里有问题,折叠和显示高亮可能会不一致。尤其 在使用可能跨越多行的模式时更要小心。如果有疑问,不妨尝试如下的强制同步: :syn sync fromstart 比 较 fold-diff 对没有改动的文本或靠近改动的文本自动定义折叠。 这个方法仅适用于当前窗口设定 'diff' 选项来显示不同之处时才有效。不然,整个缓冲 区就是一个大的折叠。 选项 'diffopt' 可以指定上下文。即折叠和不被折叠包括的改变之间相距的行数。比 如,设定上下文为 8: :set diffopt=filler,context:8 默认值是 6。 当设定了 'scrollbind' 选项时,Vim 会试图在其它比较窗口中打开相同的折叠,这样这 些窗口就会显示同一处文本。 标 志 fold-marker 在文本中可以加入标志来指明折叠开始和结束的地方。这可以让你精确的定义折叠。这也 让你可以放心地删除和复制折叠而不用担心错误包括了某些行。选项 'foldtext' 通常设 置为使折叠行显示折叠标志之前的文本。这样做可以为折叠命名。 标志可以包含级别数,也可以使用匹配对。包含级别数较简单,你无须添加结束标志,并 可以避免标志不配对的问题。如: /* global variables {{{1 */ int varA, varB; /* functions {{{1 */ /* funcA() {{{2 */ void funcA() {} /* funcB() {{{2 */ void funcB() {} {{{ }}} 折叠开始于 "{{{" 标志。接下去的数字决定了折叠级别。产生的效果依当前折叠级别和 该折叠标志给定的级别的大小关系而定: 1. 如果遇到级别相同的标志,上一个折叠结束,另一个有同样级别的折叠开始。 2. 如果遇到级别更高的标志,开始一个嵌套的折叠。 3. 如果遇到级别更低的标志,所有大于或等于当前级别的折叠结束,且指定级别的折叠 开始。 数字指定了折叠级别。不能使用 0 (忽略级别为 0 的标志)。你可以使用 "}}}" 带上一 个数字来表示这个级别的折叠结束。此行以下的折叠级别将比当前级别小一。备注: Vim 不会回溯匹配的标志 (这将耗费太多的时间)。如: {{{1 fold level here is 1 {{{3 fold level here is 3 }}}3 fold level here is 2 你也可以用一对匹配标志 "{{{" 和 "}}}" 来定义折叠。每个 "{{{" 使折叠级别加 1, "}}}" 使折叠级别减 1。注意一定要使标志匹配!如: {{{ fold level here is 1 {{{ fold level here is 2 }}} fold level here is 1 带数字的标志和没有带数字的标志可以混合使用。对于一个大折叠我们可以使用带数字的 标志,在函数的内部我们可以使用不带数字的。如对文件中的 "结构定义","局部变量" 和 "函数原型" 各个部分,使用级别 1 的折叠。对定义和函数体使用级别 2 的标志。而 在函数内部可以使用不带数字的标志。当你在一函数中作更改以分割折叠时,你无须记着 标志在哪里。 选项 'foldmarker' 可设定所用的标志。建议保留默认值 "{{{,}}}"。这样在 Vim 用户 间交换文件时就不会出问题。有时为了要编辑的文件必须改变该选项 (如,文件包含了来 自另一个编辑器的折叠标志,或对于当前文件的语法而言,折叠标志会产生歧义等)。 fold-create-marker "zf" 可通过标志来创建一个折叠。 Vim 将为你插入开始和结束标志。这些标志由 'foldmarker' 指定。标志会被添加在行末。如果 'commentstring' 不为空,使用之。 以下情况下可能无法正常工作: - 此行已有一个带级别的标志了。Vim 无法判断该如何做。 - 在附近的折叠里使用了带级别的标志,使添加无法进行。 - 这行包含在一注释中,且 'commentstring' 不为空,且嵌套的注释是非法的。如,在 C 的注释中加入 /* {{{ */ ,这将使现有的注释中断。你可以在注释之前或之后添加 标志,或手工添加。 总的来说,当你已有带级别的标志时,再让 Vim 为你创建标志不是个好主意。 fold-delete-marker "zd" 可用来删除一个用标志定义的折叠。 Vim 将为你删除标志。Vim 将在折叠的开始和 结束处根据 'foldmarker' 查找开始和结束标志。如果标志周围文字和 'commentstring' 匹配,这些文字也会被删除。 但在以下情况下无法正确执行: - 当一行包含有多于一个的标志且其中一个指定了级别。Vim 不考虑结果是不是真能删除 折叠,而仅删除第一个标志。 - 当这个标志带有级别且同时被用来开始或结束几个折叠时。

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 删除 (delete) 在光标下的折叠。当光标在被折叠的行上,该折叠被删 除。嵌套的折叠上移一级。在可视模式下所选区域 (部分) 涵盖的一层 折叠被删除。 小心: 这很容易比你想象地要删得多,手动折叠不能撤销。 仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。 参考 fold-delete-marker zD zD 循环删除 (Delete) 光标下的折叠。在可视模式下所选区域 (部分) 涵 盖的折叠和嵌套的折叠都被删除。 仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。 参考 fold-delete-marker zE E352 zE 除去 (Eliminate) 窗口里所有的折叠。 仅当 'foldmethod' 设为 "manual" 或 "marker" 时有效。 参考 fold-delete-marker打 开 和 关 闭 折 叠 一个小于 'foldminlines' 的折叠的显示就像它被打开时一样。所以,以下的命令对于小 折叠所起的作用与描述不同。 zo zo 打开 (open) 在光标下的折叠。当给定计数时,相应深度的折叠被打 开。在可视模式下,所选区域的所有行的折叠被打开一级。 zO zO 循环打开 (Open) 光标下的折叠。不在光标下的折叠不改变。 在可视模式下,打开所有的在选中区域里的折叠,包括被部分选中的。 zc zc 关闭 (close) 在光标下的折叠。当给定计数时,相应深度的折叠被关 闭。在可视模式下,所选区域里的所有行的折叠被关闭一级。 'foldenable' 被设定。 zC zC 循环关闭 (Close) 在光标下的所有折叠。不在光标下的折叠不改变。 在可视模式下,关闭所有的在选中区域里的折叠,包括被部分选中的。 'foldenable' 被设定。 za za 当光标位于一关闭的折叠上时,打开之。当折叠嵌套时,你可能需要用 "za" 数次。当给定计数时,打开相应数量的被关闭的折叠。 当光标位于一打开的折叠上时,关闭之且设定 'foldenable' 。这仅关 闭一级折叠,因为再次使用 "za" 将再次打开折叠。当给定计数时,关 闭相应数量的折叠 (这不同于重复 "za" 许多次)。 zA zA 当处在一关闭的折叠上时,循环地打开折叠。 当处在一打开的折叠上时,循环地关闭折叠且设定 'foldenable' zv zv 查看 (view) 光标所在的行: 仅打开足够的折叠使光标所在的行不被折 叠。 zx zx 更新折叠: 撤销被手工打开和关闭的折叠: 再次应用 'foldlevel'。 然后使用 "zv" : 查看光标所在行。 同时强制重新计算折叠。使用 "foldexpr" 并且缓冲区发生改变但折叠 不能正确地更新时,这会有用。 zX zX 手工恢复被打开和关闭的折叠: 再次应用 'foldlevel'。 也同时强制重新计算折叠,同 zx zm zm 折起更多 (more): 'foldlevel' 减 v:count1。如果 'foldlevel' 已 经为 0,则不会被减小。 'foldenable' 被设定。 zM zM 关闭所有折叠: 'foldlevel' 设为 0。 'foldenable' 被设定。 zr zr 减少 (reduce) 折叠: 'foldlevel' 加 v:count1。 zR zR 打开所有的折叠。'foldlevel' 设为最高级别。 :foldo :foldopen :{range}foldo[pen][!] 在 {range} 内打开折叠。当加上 [!] 时,所有的折叠都被打开。对查 看在 {range} 内的所有文本很有用。没有 [!] 时,打开一级折叠。 :foldc :foldclose :{range}foldc[lose][!] 在 {range} 内关闭折叠。当加上 [!] 时,所有的折叠都被关闭。对隐 藏在 {range} 内的所有文本很有用。没有 [!] 时,关闭一级折叠。 zn zn 不折叠 (none): 复位 'foldenable'。所有的折叠被打开。 zN zN 正常折叠 (normal): 设定 '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] 时,仅对范围内那些行起作用。 每次命令被执行时,光标会被定位在要被操作的行上。 就如 ":global" 命令: 首先标记出所有不在关闭的折叠中的行。然后 对所有标记过的行,执行 {cmd}。所以当 {cmd} 改变了文本的折叠 时,对命令执行的位置没有影响 (当然,删除行例外)。 如: :folddoopen s/end/loop_end/ge 使用标志位 "e" 避免了当 "end" 不匹配时得到错误消息。 :[range]folddoc[losed] {cmd} :folddoc :folddoclosed 对所有在关闭的折叠里的行,执行 {cmd}。 其它同 ":folddoopen" 命令。

3. 折叠选项 fold-options

颜 色 fold-colors 对关闭的折叠的颜色的设定由 Folded 高亮组 hl-Folded 决定。对折叠栏的颜色的设 定由 FolderColumn 高亮组 hl-FoldColumn 决定。 下面是设定颜色的例子: :highlight Folded guibg=grey guifg=blue :highlight FoldColumn guibg=darkgrey guifg=white 折 叠 级 别 fold-foldlevel 'foldlevel' 是个数值选项: 数字越大则打开的折叠更多。 当 'foldlevel' 为 0 时,所有的折叠关闭。 当 'foldlevel' 为正数时,一些折叠关闭。 当 'foldlevel' 很大时,所有的折叠打开。 'foldlevel' 的改变后立即生效。之后,折叠可以被手动地打开和关闭。 当其值增大,在新级别 (译者注: 旧级别?) 之上的折叠被打开。手工打开的折叠不会被 关闭。 当其值减小,在新级别之上的折叠被关闭。手工关闭的折叠不会被打开。 折 叠 文 本 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 使用不带参数的函数调用的优点是更加速,见 expr-option-function'foldtext' 的计算是在沙盘 sandbox 里完成的。其中的当前窗口设为要显示该行的窗 口。上下文设为上次设置此选项所在的脚本。 错误被忽略。要方便调试可设 'debug' 选项为 "throw"。 默认值是 foldtext() 。对于大多数类型的折叠它可以返回适合的文字。如果你不喜欢 它,你可以自己指定 'foldtext' 表达式。可以使用以下这些 Vim 变量: v:foldstart 折叠首行的行号 v:foldend 折叠末行的行号 v:folddashes 一个含有连字符的字符串,用来表示折叠级别 v:foldlevel 折叠级别 在结果中,制表符被替换为空格,而不可显示的字符被替换为可显示的字符。 结果行被截短以适合窗口的宽度,永远不会回绕。 当在文字后有空余时,用 'fillchars' 来填充。 'foldtext' 表达式以 s: 或 <SID> 开始时,它们被脚本 ID 替换 ( local-function )。例如: set foldtext=s:MyFoldText() set foldtext=<SID>SomeFoldText() 备注: 对那些 ":set" 命令作特殊处理的字符在其前面须加上反斜杠。如: 空格,反斜杠 和双引号。 option-backslash 折 叠 栏 fold-foldcolumn 'foldcolumn' 是个数字,它设定了在窗口的边上表示折叠的栏的宽度。当为 0 时,没有 折叠栏。一个普通值是 4 或 5。最小可用的值是 2,不过 1 仍然可以提供一些信息。最 大是 12。 一个打开的折叠由一栏来表示,顶端是 '-',其下方是 '|'。这栏在折叠结束的地方结 束。当折叠嵌套时,嵌套的折叠出现在被包含的折叠右方一个字符位置。 一个关闭的折叠由 '+' 表示。 这些字符可用 '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 当光标在关闭的折叠上时,它将在整个折叠里用 "bar" 替换 "foo"。 不过 :folddoopen:folddoclosed 的操作并非如此。 编辑一个已经被编辑过的缓冲区时,上次被使用的折叠设置会被再次使用。对手工定义折 叠方式,已经被定义的折叠会被恢复。对所有的折叠方式,手工打开和关闭的折叠会被恢 复。如果这个缓冲区曾经在这个窗口里被编辑,过去用的值被恢复。否则,来自该缓冲区 最近一次编辑的窗口值被使用。

vim:tw=78:ts=8:noet:ft=help:norl: