我想设置两种折叠方法
:set foldmethod=indent
并保留其所有功能用
隐藏评论 :set foldmethod=marker
:set foldmarker=/*,*/
我发现这是不可能的。是否有可能实现所需的折叠并在.vimrc
中设置或为此使用一些脚本或插件?
答案 0 :(得分:8)
在同一个缓冲区中不可能有不同的foldmethod类型。 Vim如何知道在同一缩进级别有一些评论与您想要视为具有不同(更高编号)级别的其他文本?
我确信你可以通过将foldmethod设置为'expr'来达到你想要的效果。这是在Vim中进行折叠的最灵活方式,但可能会变得复杂(和/或缓慢),具体取决于您的需求。不过,我认为它对你的用例来说相当容易。
首先,在vimrc或vimscripts中的某个位置,您需要确保为相关文件类型定义了foldexpr。
set foldexpr=MyFoldLevel(v:lnum)
set foldmethod=expr
" and for last code example
let b:previous_level = 0
然后你必须充实你的foldexpr函数,以便它以一种导致你想要的行为的方式分配级别。类似下面的代码可能接近于每个注释行都有前缀符号(即,不是你的情况),但我希望它需要一些调整。 h: fold-expr
是寻求帮助的好地方:
function! MyFoldLevel(linenum)
" assign levels based on spaces indented and tabstop of 4
let level = indent(a:linenum) / 4
if getline(a:linenum) =~ [put line-based comment prefix pattern here]
let level = 20
endif
endfunction
需要进行修改,以便按照您希望的方式为评论开始和结束标记之间的行分配更高级别:
function! MyFoldLevel(linenum)
let linetext = getline(a:linenum)
if linetext =~ [put line-based comment prefix pattern here]
let level = 20
elseif linetext =~ '^\s*/\*'
let level = 20
elseif linetext =~ '^\s*\*/'
let level = 21
else
if b:previous_level == 20
let level = 20
else
"assuming code is space-indented with tabstop of 4
let level = indent(a:linenum) / 4
endif
endif
let b:previous_level = level
return level
endfunction
我不希望我写的折叠方法功能完全按照书面方式工作。但他们确实指出了可行的方法。
请注意,对评论使用“20”级别只是允许折叠的任意级别,而所有(可能是较低级别的)缩进代码都可见。最后一行评论部分的“21”只是为了区别于前面的20级评论,以便知道下一行应该被视为常规代码行。
此外,像'zc'和'zo'这样的关键操作在注释设置为远高于周围代码的水平时将无法正常工作。希望使用:set foldlevel=21
之类的直接命令来显示所有注释行。
不漂亮,我希望它可以简化一点,但我认为这就是你想要的东西。
实际上,考虑到这一点,我想你会希望任何评论块的第一行与非评论行处于相同的水平,只需要在同一块中的后续评论行更高级别让他们“折叠”到起始评论行。在我给出的代码中,如果它起作用或接近完成工作,我认为vim会将前面的非注释行后面的注释行折叠 all ,这不是你想要的,但是遗憾的是,我没有更多的时间专注于这个小谜题。 。 。我做过这种自定义折叠很多次,并且在获得我想要的东西时总是会有一些试验和错误。
答案 1 :(得分:1)
基于语法的折叠可能是比我在不同的问题答案中建议的基于expr的方法更好的方法。查看:h fold-syn
了解详情。我认为基于c的折叠可能已经有了一些很好的解决方案。不知道它有多好,但这里是一个支持基于语法的折叠的c语法文件:
http://www.vim.org/scripts/script.php?script_id=234
另一个:
http://www.vim.org/scripts/script.php?script_id=925
上述解决方案完全基于语法,不涉及使用缩进来确定折叠级别。但是如果需要,您可以修改基于语法的折叠以通过缩进区域进行主折叠。如果你基于语法元素缩进,结果可能是相同的。
这是一个提示,展示如何折叠c风格的评论(而不是实际的代码) http://vim.wikia.com/wiki/Fold_C-style_comments
答案 2 :(得分:1)
我和你的请求一样,这是我不完美的解决方案
我的制造商对是#< ===和#===> (或#region和#endregion在pycharm中)
let b:inBlock=0
let b:lastLineNum=0
let b:lastLevel=0
let b:lastGoodLine=0
let b:lastGoodBlock=0
let b:startFoldingMark='^\s*.\?#<==*\|^\s*.\?#region'
let b:endFoldingMark='^\s*.\?#=*=>\|^\s*.\?#endregion'
function! MyFold(linenum)
let linetext = getline(a:linenum)
let level = indent(a:linenum) / &shiftwidth
"the first line have 0 fold level
if (a:linenum == 1)
if linetext =~ b:startFoldingMark
let b:inBlock = 1
let b:lastLineNum=a:linenum
let b:lastGoodLine=0
let b:lastGoodBlock=0
let b:lastLevel=level
return level
endif
let b:inBlock=0
let b:lastInBlock=0
let b:lastLineNum=a:linenum
let b:lastGoodLine=0
let b:lastGoodBlock=b:inBlock
let b:lastLevel=level + b:inBlock
return level + b:inBlock
endif
" not calculate from the mid of text
if ((b:lastLineNum+1) != a:linenum)
let level = indent(a:linenum) / &shiftwidth
let lastGoodNum = a:linenum-1
while (lastGoodNum>1 && getline(lastGoodNum) =~? '\v^\s*$' )
let lastGoodNum -= 1
endwhile
if (foldlevel(lastGoodNum)==-1)
let b:inBlock=b:lastGoodBlock
else
let lastlevel = indent(lastGoodNum) / &shiftwidth
let lastlinetext = getline(lastGoodNum)
let lastlinelevel = foldlevel(lastGoodNum)
if lastlinetext =~ b:startFoldingMark
let b:inBlock = lastlinelevel - lastlevel + 1
elseif lastlinetext =~ b:endFoldingMark
let b:inBlock = lastlinelevel - lastlevel - 1
else
let b:inBlock = lastlinelevel - lastlevel
endif
endif
endif
"blank lines have undefined fold level
if getline(a:linenum) =~? '\v^\s*$'
let b:lastLineNum=a:linenum
let b:lastLevel=-1
return -1
endif
"if next line is a start of new marker block, inBlock ++
if linetext =~ b:startFoldingMark
let b:lastLineNum=a:linenum
if (b:lastLevel != -1)
let b:lastGoodLine=a:linenum
let b:lastGoodBlock=b:inBlock
endif
let b:lastLevel=level + b:inBlock - 1
return level + b:inBlock - 1
"if next line is an end of new marker block, inBlock -
elseif linetext =~ b:endFoldingMark
let b:inBlock = b:inBlock - 1
let b:lastLineNum=a:linenum
let b:lastGoodLine=a:linenum
let b:lastGoodBlock=b:inBlock
let b:lastLevel=level + b:inBlock + 1
return level + b:inBlock + 1
endif
let b:lastLineNum=a:linenum
if (b:lastLevel != -1)
let b:lastGoodLine=a:linenum
let b:lastGoodBlock=b:inBlock
endif
let b:lastLevel=level + b:inBlock
return level+b:inBlock
endfunction
现在,我可以在使用缩进折叠方法时保留所有功能, 我可以折叠每个#&lt; =,#=&gt;标记块, 而且,线条&#39;每个区块仍保留缩进折叠关系。
在此功能中,我避免使用&#34; a1&#34;,&#34; s1&#34;和&#34; =&#34; level,这将导致此函数的迭代,并且对于大文件可能会很慢。 但是,当您更新行时,折叠级别的计算可能不正确(因为vim可能不会从开头更新所有折叠级别,因此具有不正确的inBlock值)
您可以使用 zx 手动更新折叠级别。
了解详情