2011-05-11 136 views
8

倍方法我想设置两种方法用于折叠两个在同一时间

  1. :set foldmethod=indent并保留其所有功能
  2. 隐藏注释与

    :set foldmethod=marker

    :set foldmarker=/*,*/

我发现这是不可能的。是否有可能实现所需的折叠并将其设置为.vimrc或者为此使用一些脚本或插件?

回答

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 

我不不要期望我写的foldmethod函数能够完全按照写法工作。但他们确实指出了一些可行的方法。

请注意,对于注释使用'20'级别只是任意级别,允许它们被折叠,而所有(可能较低级别的)缩进代码都可以被看到。最后一行评论部分的'21'只是为了区分它与之前的20级注释行,要知道下一行应该被视为常规代码行。

此外,当'zc'和'zo'等关键操作符被设置为远高于周围代码时,它们在注释上不会正常工作。想要使用像:set foldlevel=21这样的直接命令来显示所有注释行。

不是很漂亮,我希望它可以简化一点,但类似这样的事情是我认为是你需要的。

实际上,再仔细考虑一下,我想你会希望任何注释块的第一行处于同一级别,就像它是非注释行一样,只有同一块中的后续注释行才需要将它们“折叠”到开始注释行中的级别更高。在我给出的代码中,如果它工作或接近工作,我认为vim会折叠全部后面的非注释行后面的注释行,这不是您想要的,但我很遗憾没有有更多的时间去投入这个小小的谜题。 。 。我已经完成了这种定制折叠的很多次,而且一般都会有一些试验和错误来获得我想要的东西。

+0

是否有可能映射“ZO”命令“ZO”命令按21倍?我注意到多次按动ZO没有副作用。它会减慢vim的速度吗? – xralf 2011-05-12 18:28:49

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

0

我有同样的要求是你的,这是我的不完美的解决方案

我的制造者对是#< ===和#===>(或#地区和#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 

现在,我可以使用缩进折叠方法时保持所有功能, ,我可以FO每个#< =,#=>标记块, 此外,行的缩进折叠关系仍然保留在每个块中。

在此函数中,我避免使用“a1”,“s1”和“=”级别,这会导致此函数的迭代,并且对于大文件可能会很慢。 然而,在更新线,倍水平的计算可能是不正确的(因为VIM可能无法更新从开始所有级别的折叠,因此具有不正确inBlock值)

可以使用ZX手动更新倍水平。

多见于https://github.com/Fmajor/configs

相关问题