手动设置折叠时,如果可以以上下文敏感的方式设置commentstring
,则会很方便。考虑这种情况,语言使用BCPL样式的注释标记(即注释以//
开头并以换行符结束),可视块的第一行包含注释,最后一行不包含注释。目前,如果commentstring
设置为//%s
,则当//
用于创建折叠时,多余的zf
字符将附加到第一行。
是否可以设置commentstring
以便仅在//
字符尚未显示在该行上时添加{{1}}个字符?
答案 0 :(得分:1)
根据:help fold-create-marker
,自动折叠标记插入
在以下情况下无法正常工作:
- 该行已包含带有级别编号的标记。然后Vim没有 知道该怎么做。
- 在附近折叠使用他们的标记中的等级编号,这会妨碍他们。
- 该行位于注释中,
commentstring
不为空且嵌套 评论不起作用。例如,使用C:在里面添加/* {{{ */
评论将截断现有评论。
因此,无法通过修改默认zf
行为来更改
commentstring
设置。
但是,可以创建zf
命令的自定义版本
将考虑到开始或结束(或两者)的行
折叠可以有评论。例如,请考虑以下映射,一个
通过视觉选择标记折叠,另一个用于运动
命令。
nnoremap <silent> <leader>zf :set opfunc=CreateMarkerFold<cr>g@
vnoremap <silent> <leader>zf :<c-u>call CreateMarkerFold(visualmode(), 1)<cr>
function! CreateMarkerFold(vt, ...)
let range = map(['[<', ']>'], 'line("''".v:val[a:0])')
let mark = split(&foldmarker, ',')
let pat = escape(&commentstring, '\')
let pat = '\V' . substitute(pat, '\\\@<!%s', '\\zs\\ze\\.\\{-}', '')
for i in [1, 0]
let line = getline(range[i])
if line =~ pat
let line = substitute(line, pat, escape(mark[i], '\'), '')
else
let line .= printf(&commentstring, mark[i])
endif
call setline(range[i], line)
endfor
endfunction
两个映射都遵循相同的例程。在添加起始和之前
结束折叠标记,它分别检查第一个和最后一个
要折叠的块的行与commentstring
模式匹配。对于每一个
两个匹配,它在第一个找到的内部插入相应的标记
评论,在其文本的最开始。否则,标记是
根据{{1}}模板进行装饰,并在最后添加
这条线。
如果在后一种情况下,最好将标记分开, 可以改变for循环,如下所示。
commentstring
与循环的先前版本不同,处理两者的顺序 线很重要:首先应添加结束标记线,如果 必要的,因为为开始标记插入一行会改变 以下几行改变了他们的数字。