手动设置折叠时,如果可以以上下文敏感的方式设置commentstring
,将会很方便。考虑语言使用BCPL样式注释标记的情况(即,注释以//
开始并以换行符终止),视觉块的第一行包含注释,而最后一行不包含注释。目前,如果commentstring
设置为//%s
,则在使用zf
创建折叠时,冗余//
字符将附加到第一行。评论字符串中的上下文敏感度
是否可以设置commentstring
以便仅在//
字符尚未出现在行上才能添加//
字符?
手动设置折叠时,如果可以以上下文敏感的方式设置commentstring
,将会很方便。考虑语言使用BCPL样式注释标记的情况(即,注释以//
开始并以换行符终止),视觉块的第一行包含注释,而最后一行不包含注释。目前,如果commentstring
设置为//%s
,则在使用zf
创建折叠时,冗余//
字符将附加到第一行。评论字符串中的上下文敏感度
是否可以设置commentstring
以便仅在//
字符尚未出现在行上才能添加//
字符?
根据:help fold-create-marker
,自动折叠标记插入 不能正常工作时:
- 线已包含具有一个电平数字的标记。然后Vim不知道该怎么做。
- 附近的折叠在他们的标记中使用了一个级别号码。
- 该行在注释中,
commentstring
不为空且嵌套 注释不起作用。例如对于C:在 内部添加/* {{{ */
,评论将截断现有评论。
因此,就不可能通过修改 commentstring
设置来改变默认zf
行为。
但是,可以创建zf
命令的定制版本, 将考虑折叠的开始或结束(或两个)行可能有意见。例如,考虑以下映射,一个用于通过视觉选择标记折叠的 ,另一个用于与运动 命令一起使用。
nnoremap <silent> <leader>zf :set opfunc=CreateMarkerFold<cr>[email protected]
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
模式。对于两个匹配的 中的每一个,它都在第一个发现的 评论中的相应标记内插入文本的开头。否则,标记为 ,根据commentstring
模板进行装饰,并在 的末尾添加该行。
如果在后一种情况下,最好在自己的行上分隔标记, 可以更改for循环,如下所示。
for i in [1, 0]
let line = getline(range[i])
if line =~ pat
let line = substitute(line, pat, escape(mark[i], '\'), '')
call setline(range[i], line)
else
call append(range[i] - !i, printf(&commentstring, mark[i]))
endif
endfor
不像以前的版本的循环,处理这两个 行的顺序是很重要的:将结束标记线应先加入,如果 必要的,因为插入线为开头标记将移 以下行改变了他们的号码。
非常好。我改变的唯一的事情就是使用setline而不是在else子句中追加来将标记保持在同一行上。 – 2012-03-10 13:28:35
@WilliamPursell:我认为,你是对的:将自定义'zf'命令设为默认行为是个好主意,因为它符合内置'zf'的行为。答案会相应更新。 – 2012-03-10 14:47:51