2012-03-05 60 views
1

手動設置摺疊時,如果可以以上下文敏感的方式設置commentstring,將會很方便。考慮語言使用BCPL樣式註釋標記的情況(即,註釋以//開始並以換行符終止),視覺塊的第一行包含註釋,而最後一行不包含註釋。目前,如果commentstring設置爲//%s,則在使用zf創建摺疊時,冗餘//字符將附加到第一行。評論字符串中的上下文敏感度

是否可以設置commentstring以便僅在//字符尚未出現在行上才能添加//字符?

回答

1

根據: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 

不像以前的版本的循環,處理這兩個 行的順序是很重要的:將結束標記線應先加入,如果 必要的,因爲插入線爲開頭標記將移 以下行改變了他們的號碼。

+0

非常好。我改變的唯一的事情就是使用setline而不是在else子句中追加來將標記保持在同一行上。 – 2012-03-10 13:28:35

+0

@WilliamPursell:我認爲,你是對的:將自定義'zf'命令設爲默認行爲是個好主意,因爲它符合內置'zf'的行爲。答案會相應更新。 – 2012-03-10 14:47:51

相關問題