来自:help 'foldexpr'
:
对每条线进行评估以获取其折叠级别
的foldexpr
评价,所以它需要VimL代码; 没有提及“特殊语法”等。评估的结果控制了Vim认为是折叠还是不折叠。
可能的值为
0 the line is not in a fold
1, 2, .. the line is in a fold with this level
"<1", "<2", .. a fold with this level ends at this line
">1", ">2", .. a fold with this level starts at this line
这不是完整列表;只是问题示例中使用的那些。请参阅:help foldexpr
完整列表。
第一
第一个相当简单,一旦我们添加了一些空格并删除了反斜杠,就需要在:set
命令中使它正常工作:
getline(v:lnum)[0] == "\t"
getline(v:lnum)
得到整条线。
[0]
得到那个的第一个字符
- 并
== "\t"
检查它是否为制表符。
- VimL没有“ true”或“ false”,它仅将“ 0”表示为false,将“ 1”表示为true。因此,如果此行以制表符开头,则以foldlevel 1折叠。如果不是,则不在fold(0)中。
如果您将其扩展为计算选项卡的数量,则将具有基于缩进的折叠(至少在expandtab
未启用时)。
第三
第三个确实没有第一个复杂。与第一个示例一样,我们首先要使其更具可读性:
getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
- 我们得到了整条线
getline(v:lnum)
- 我们匹配与一个正则表达式
=~
来'^\s*$'
; ^
锚定到开头,\s
表示任何空白字符,*
表示重复前一个零次或多次,然后$
锚定到末尾。因此,此正则表达式与空白行或仅包含空格的行匹配(返回true)。
getline(v:lnum + 1)
获取下一行。
- 我们将
\S
其匹配到,这匹配此行上任何地方的任何非空白字符。
- 如果这两个条件都成立,我们求值为
<1
,否则为1
。这是通过if
C和其他一些语言中已知的“三元”来完成的 condition ? return_if_true : return_if_false
。
<1
表示折线在此行结束,并且1
表示折线级别1。
因此,如果我们在一行是空白而下一行不是空白的情况下结束折叠。否则,我们将处于折叠级别1。或者说::h foldexpr
这将使用空白行分隔的段落折叠起来
第四
第四者的行为与第三者相同,但方式略有不同。扩展为:
getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1
如果前一行是空白行,而当前行是非空白行,则在该行(>1
)上开始折叠,如果不是,则将折叠级别设置为1。
后记
因此,所有3个示例的逻辑都非常简单。大多数困难来自缺少空格和一些反斜杠的使用。
我怀疑调用函数会产生一些开销,并且因为要评估每条要获得良好性能的行,因此会对其进行评估。我不知道现代机器上的区别有多大,除非您有性能问题,否则建议您使用一个函数(如第二个示例中所示)。记住The Knuth:“过早的优化是万恶之源”。
这个问题也在StackOverflow上,答案略有不同。但是我的当然更好;-)