我正在尝试为大型 Markdown 文件创建一种简单、快速的折叠方法。我在 vim 中使用 fold-expr
方法。例如,如果我想在 H1
和 H2
Markdown 条目上开始折叠,我的 vimscript 代码是:
function! MarkdownLevel()
if getline(v:lnum) =~ '^# '
" begin a fold of level one here
return ">1"
elseif getline(v:lnum) =~ '^## '
" begin a fold of level two
return ">2"
else
return "="
endif
endfunction
这工作得很好,我得到了嵌套折叠。然而,当我有一个大的 markdown 文件时,vim 的速度会大大减慢。这并不奇怪,事实上,vim 中的 Fold-expr 帮助中已经指出了这一点。这是因为 =
符号告诉 vim 在文件中向后扫描,直到找到具有显式定义的折叠级别的第一行;这可能有数千行。
我尝试将最后一行替换为
else
" set foldlevel to foldlevel of previous line
return foldlevel(v:lnum-1)
endif
但这并没有按预期工作。有谁知道如何解决这一问题?很明显我不明白foldlevel函数是如何工作的,或者vim中的折叠算法是如何实现的。
最佳答案
我想出了如何解决速度下降的问题,并了解了 fold-expr
在 vim 中的工作原理。我在3000行md文件上测试了性能问题。
我依赖于 fold-expr
应该具有的以下自动折叠功能:如果当前行的折叠级别小于下一行的折叠级别,它将开始折叠。如果当前行的折叠级别大于下一行的折叠级别,则结束折叠。据我所知,事实证明这并没有按预期工作。
有效的方法是使用 return ">1"
明确告诉 vim 折叠从这里开始,其中 1
被替换为适当的数量。
在从@PeterRinker学习如何分析vim脚本后,我发现当我编辑第3000行时,return "="
语句被评估了很多很多次。
这是我的修复:如果当前行的折叠级别不属于任何标题类型并且前一行的折叠级别已经定义,则当前行应该继承前一行的折叠级别。这是一个显而易见的解决方案,但如果我使用上面的 return "1"
而不是 return ">1"
,它就会不起作用。它需要在第一遍中使用 return "="
语句来确定折叠级别。
所以对于3000行的文件来说,我的启动时间有点长(大约1秒),但现在编辑非常流畅。以下是完成的简单代码。其他更复杂的 Markdown 项目没有这种有用的简化。
function! MarkdownLevel()
let theline = getline(v:lnum)
let nextline = getline(v:lnum+1)
if theline =~ '^# '
" begin a fold of level one here
return ">1"
elseif theline =~ '^## '
" begin a fold of level two here
return ">2"
elseif theline =~ '^### '
" begin a fold of level three here
return ">3"
elseif nextline =~ '^===*'
" elseif the next line starts with at least two ==
return ">1"
elseif nextline =~ '^---*'
" elseif the line ends with at least two --
return ">2"
elseif foldlevel(v:lnum-1) != "-1"
return foldlevel(v:lnum-1)
else
return "="
endif
end
关于使用fold-expr 时 vim 变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27385161/