手動設置摺疊時,如果可以以上下文敏感的方式設置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