【问题标题】:Adding a marker for vim syntax folding为 vim 语法折叠添加标记
【发布时间】:2015-11-04 23:10:05
【问题描述】:

我通常用 C 编写代码,我的 .vimrc set foldmethod=syntax 中有它,它可以很好地折叠大括号和 cmets 等等。

但有时我需要折叠大块代码以免它们妨碍我(例如一组相关函数),我通常使用 set foldmethod=marker 和标记 >>> 和 @ 987654324@.

我一直在尝试添加一个新的同步区域,最近我得到的是:

syn region cFoldMarkers start='>>>' end='<<<' containedin=cComment transparent fold

但这会造成混乱,因为它以某种方式与 cmets 匹配。

有没有办法实现这两个目标?还是我应该放弃用语法来做这件事,而只为大括号、cmets 和我的自定义标记设置标记?

提前致谢

【问题讨论】:

    标签: vim syntax folding


    【解决方案1】:

    好的,经过……尝试使用语法折叠 5 个小时后,我放弃并改为表达式折叠。

    按照这个问题:LLVM-IR syntax folding for vim 我创建了一个折叠函数,或多或少可以满足我的需求:

    function! CFold()
        let this_line = getline(v:lnum)
    
        " Matching of braces
        if match(this_line, '}') >= 0
            return 's1'
        elseif match(this_line, '{$') >= 0
            return 'a1'
        " Matching of comments
        elseif match(this_line, '/\*') >= 0
            if match(this_line, '\*/$') == -1
                return 'a1'
            " Matching custom folding
            elseif match(this_line, '>>>') >= 0
                return 'a1'
            elseif match(this_line, '<<<') >= 0
                return 's1'
            endif
        elseif match(this_line, '\*/$') >= 0
            return 's1'
        endif
        return '='
    endfunction
    
    setlocal foldmethod=expr
    setlocal foldexpr=CFold()
    

    【讨论】:

      【解决方案2】:

      插件syntaxMarkerFold 增加了这个功能。它的实现相当简单:

      " syntaxMarkerFold
      " Maintainer:  Jorengarenar <https://joren.ga>
      " License:     MIT
      
      if exists('g:loaded_syntaxMarkerFold') | finish | endif
      let s:cpo_save = &cpo | set cpo&vim
      
      function! s:genLeveled(lvl) abort
        let l:higherLvls = ""
        for i in range(a:lvl-1, 0, -1)
          let l:higherLvls .= " end = '\\ze" . s:op[1:] . i . s:ed
          let l:higherLvls .= " end = '\\ze" . s:cl[1:] . i . s:ed
        endfor
      
        exec "syn region syntaxMarkerFold" . a:lvl . " matchgroup=Comment transparent fold containedin=ALL"
              \ "start = " . s:op . a:lvl . s:ed
              \ "end   = " . s:cl . a:lvl . s:ed
              \ "end   = '\\ze" . s:op[1:] . a:lvl . s:ed
              \ l:higherLvls
              \ "end   = '\\ze" . s:cl[1:] . s:ed[:1] . "$'"
      
      endfunction
      
      function! s:init(...) abort
        let [ m1, m2 ] = split(&l:foldmarker, ",")
      
        let maxlvl = get(b:, "syntaxMarkerFold_maxlevel", get(g:, "syntaxMarkerFold_maxlevel", 5))
      
        if a:0 == 0
          let comm = split(&l:comments, ',')
          call map(comm, 'substitute(v:val, ".\\{-}:", "", "")')
          let comm = '\%(' . join(comm, '\|') . '\)'
        else
          let comm = a:1
        endif
      
        let s:st = "'\\V\\s\\*" . comm . "\\.\\{-}"
        let s:op = s:st . m1
        let s:cl = s:st . m2
        let s:ed = "\\v(\\s.*)?'"
      
        exec "syn region syntaxMarkerFold matchgroup=Comment transparent fold containedin=ALL"
              \ "start = " . s:op . s:ed
              \ "end   = " . s:cl . s:ed
      
        for lvl in range(1, maxlvl)
          call s:genLeveled(lvl)
        endfor
      
      endfunction
      
      augroup syntaxMarkerFold
        autocmd Syntax * call s:init()
        autocmd OptionSet foldmarker
              \  exec "syn clear syntaxMarkerFold"
              \| for i in range(1, get(b:, "syntaxMarkerFold_maxlevel", get(g:, "syntaxMarkerFold_maxlevel", 5)))
              \|   exec "syn clear syntaxMarkerFold".i
              \| endfor | unlet i
              \| call s:init()
      augroup END
      
      let g:loaded_syntaxMarkerFold = 1
      let &cpo = s:cpo_save | unlet s:cpo_save
      

      【讨论】:

        猜你喜欢
        • 2012-06-13
        • 2011-04-23
        • 1970-01-01
        • 1970-01-01
        • 2014-01-12
        • 2013-02-11
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        相关资源
        最近更新 更多