语法foldmethod很棒,但是有时候我只想将注释折叠到源文件中。

注释的语法折叠也仅适用于C样式注释,例如:

/*
 ...
 */


,但不适用于类似以下内容的注释样板:

//
//
// ...
//


甚至对于非C类语言的注释块,例如:

#
#
# ...
#


如何用vim配置它?

评论

您是否要使用语法折叠和注释折叠?还是仅注释折叠?

@Carpetsmoker,如果可以说“打开所有折叠(注释除外)”,语法折叠+注释折叠就可以了。否则,不带语法折叠的注释折叠也可以。

#1 楼

使用foldmethod=expr仅折叠注释非常容易:

set foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*'.&commentstring[0]


这将仅检查行是否以任意数量的空格开头,后跟注释字符。请注意,这是非常幼稚的,可能不适用于所有语言,因为commentstring可能比单个字符更复杂。因此,您可能想使用autocmd进行更具体的设置:

autocmd FileType c      setlocal foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*//'
autocmd FileType python setlocal foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*#'


有关fold-expr的更多信息,请参见:


:help fold-expr
:help folding-functions
如何编写foldexpr?
通过正则表达式搜索模式进行折叠


使用语法折叠和注释折叠更加复杂;这将需要修改/usr/share/vim/vim74/syntax/*.vim中的语法文件,并且将特定于您使用的语言。

请注意,某些文件类型已经做到了!例如来自ruby.vim

if !exists("ruby_no_comment_fold")
  syn region rubyMultilineComment start="\%(\%(^\s*#.*\n\)\@<!\%(^\s*#.*\n\)\)\%(\(^\s*#.*\n\)\{1,}\)\@=" end="\%(^\s*#.*\n\)\@<=\%(^\s*#.*\n\)\%(^\s*#\)\@!" contains=rubyC
  syn region rubyDocumentation    start="^=begin\ze\%(\s.*\)\=$" end="^=end\%(\s.*\)\=$" contains=rubySpaceError,rubyTodo,@Spell fold
else
  syn region rubyDocumentation    start="^=begin\s*$" end="^=end\s*$" contains=rubySpaceError,rubyTodo,@Spell
endif


评论


@JackFrost如果您需要告诉某人答案中的代码不起作用,则注释或您自己的答案是更好的选择。 (马丁,建议对其中一组进行转义,以使其逃脱。不确定是否需要,但我怀疑可能是。)

– D. Ben Knoble♦
20年5月8日,0:17

仅使用一个\模式就被忽略了,猜猜我只测试了#在行首的情况。感谢您的编辑!

–马丁·图尔诺伊(Martin Tournoij)
20年5月8日,0:48



@ D.BenKnoble是的,由于:help option-backslash,您需要两个。我倾向于选择定义一个函数并设置将表达式(和autocmds等)用于函数调用的选项,以避免过多的转义。

–filbranden♦
20年5月8日,1:55

#2 楼

我喜欢缩进折叠,但要在折叠中包含注释(我的意思是每个注释的折叠程度与上一行相同)。

不幸的是,foldignore关键字仅适用于一行注释。因此,我在vimrc中用expr折叠了:

set foldmethod=expr
set foldexpr=FoldMethod(v:lnum)

function! FoldMethod(lnum)
  "get string of current line
  let crLine=getline(a:lnum)

  " check if empty line 
  if empty(crLine) "Empty line or end comment 
    return -1 " so same indent level as line before 
  endif 

  " check if comment 
  let a:data=join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )
  if a:data =~ ".*omment.*"
    return '='
  endif

  "Otherwise return foldlevel equal to indent /shiftwidth (like if
  "foldmethod=indent)
  else  "return indent base fold
    return indent(a:lnum)/&shiftwidth
endfunction


最后一个块:

indent(a:lnum)/&shiftwidth


返回折叠级别的基数缩进。

另外一个:

join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )


检查该行的第一个字符是否被视为带有语法的注释。因此,这是将缩进和语法折叠与表达式(最高级的折叠)合并的好方法。

请注意,您还可以根据想要的结果外观来“设置折叠文本”。

#3 楼

您可以使用vac直观地选择带注释的块,然后创建一个手动折叠zf

注释文本对象可能是标准vim文本对象集的语言扩展。使用Go语法对其进行了测试。

评论


实际上,交流电不是内置的。但是在tpope的评论中,gc是一个文本对象。因此,最糟糕的解决方案是zfac,zfgc或zfip

– D. Ben Knoble♦
19年7月25日在3:57