Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vim 同时采用两种方法_Vim_Folding - Fatal编程技术网

Vim 同时采用两种方法

Vim 同时采用两种方法,vim,folding,Vim,Folding,我想设置两种折叠方法 :设置foldmethod=indent并保留其所有功能 使用隐藏评论 :设置foldmethod=marker :设置foldmarker=/*,*/ 我发现这是不可能的。是否可以实现所需的折叠并在.vimrc中进行设置,或者为此使用一些脚本或插件?在同一缓冲区中不可能有不同的折叠方法类型。Vim如何知道有一些注释与其他文本具有相同的缩进级别,您希望将它们视为不同(编号更高)级别的注释 我相信通过将foldmethod设置为“expr”,您可以实现您想要的。这是在Vim中

我想设置两种折叠方法

  • :设置foldmethod=indent
    并保留其所有功能
  • 使用隐藏评论

    :设置foldmethod=marker

    :设置foldmarker=/*,*/


  • 我发现这是不可能的。是否可以实现所需的折叠并在
    .vimrc
    中进行设置,或者为此使用一些脚本或插件?

    在同一缓冲区中不可能有不同的折叠方法类型。Vim如何知道有一些注释与其他文本具有相同的缩进级别,您希望将它们视为不同(编号更高)级别的注释

    我相信通过将foldmethod设置为“expr”,您可以实现您想要的。这是在Vim中进行折叠的最灵活的方法,但根据您的需要可能会变得复杂(和/或缓慢)。不过,我认为它对于您的用例来说相当容易

    首先,在vimrc或vimscripts中的某个地方,您需要确保为所讨论的文件类型定义了Folderxpr

    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”只是一个任意级别,允许它们折叠,而所有(可能级别较低的)缩进代码都可以看到“注释的最后一行”部分只是为了将其与之前级别为20的注释行区分开来,以便知道下一行应被视为常规代码行

    另外,当注释的级别设置为比周围代码高得多时,像“zc”和“zo”这样的关键操作将不能很好地处理注释。要使用直接命令,如
    :set foldlevel=21
    ,以显示所有注释行

    不漂亮,我希望它可以简化一点,但我认为这是你想要的东西所必需的


    实际上,再仔细考虑一下,我想你会希望任何注释块的第一行与非注释行处于相同的级别,只有同一块中的后续注释行需要具有更高的级别才能“折叠”到起始注释行中。在我给出的代码中,如果它工作或接近工作,我认为vim会将所有注释行折叠到前面的非注释行后面,这不是您想要的,但不幸的是,我没有更多的时间来解决这个小难题。我已经做过很多次这种自定义折叠,通常在得到我想要的东西时会有一些尝试和错误。

    基于语法的折叠可能比我在不同的问题答案中建议的基于expr的方法更好。查看
    :h fold syn
    了解更多信息。我认为基于c的折叠可能已经有了一些很好的解决方案。不知道它有多好,但这里有一个支持基于语法的折叠的c-syntax文件: 还有一个:

    上述解决方案完全基于语法,不涉及使用缩进来确定折叠级别。但是,如果需要,可以修改基于语法的折叠,以按缩进区域进行主折叠。如果基于语法元素缩进,结果可能是相同的

    这里有一个技巧,展示了如何折叠c风格的注释(而不是实际的代码)

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

    我的生成器对是#(或pycharm中的#region和#endregion)

    设b:inBlock=0
    设b:lastLineNum=0
    设b:lastLevel=0
    设b:lastGoodLine=0
    设b:lastGoodBlock=0
    设b:startFoldingMark='^\s*\?\\\\\\\\\\\s*\?\\\'endregion'
    功能!MyFold(linenum)
    让linetext=getline(a:linenum)
    let level=缩进(a:linenum)/&shiftwidth
    “第一行有0个折叠级别
    如果(a:linenum==1)
    如果linetext=~b:startFoldingMark
    设b:inBlock=1
    设b:lastLineNum=a:linenum
    设b:lastGoodLine=0
    设b:lastGoodBlock=0
    设b:lastLevel=level
    返回水平
    恩迪夫
    设b:inBlock=0
    设b:lastInBlock=0
    设b:lastLineNum=a:linenum
    设b:lastGoodLine=0
    设b:lastGoodBlock=b:inBlock
    设b:lastLevel=level+b:inBlock
    返回级别+b:内锁
    恩迪夫
    “不从文本中间计算
    如果((b:lastLineNum+1)!=a:linenum)
    let level=缩进(a:linenum)/&shiftwidth
    设lastGoodNum=a:linenum-1
    而(lastGoodNum>1&&getline(lastGoodNum)=~?'\v^\s*$)
    设lastGoodNum-=1
    循环结束
    if(foldlevel(lastGoodNum)=-1)
    设b:inBlock=b:lastGoodBlock
    其他的
    设lastlevel=indent(lastGoodNum)/&shiftwidth
    让lastlinetext=getline(lastGoodNum)
    设lastlinelevel=foldlevel(lastGoodNum)
    如果lastlinetext=~b:startFoldingMark
    设b:inBlock=lastlinelevel-lastlevel+1
    elseif lastlinetext=~b:endFoldingMark
    设b:inBlock=lastlinelevel-lastlevel-1
    其他的
    设b:inBlock=lastlinelevel-lastlevel
    恩迪夫
    恩迪夫
    恩迪夫
    “空行具有未定义的折叠级别
    如果getline(a:linenum)=~?'\v^\s*$'
    设b:lastLineNum=a:linenum
    设b:lastLevel=-1
    返回-1
    恩迪夫
    “如果下一行是n的开头
    
    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