2011-05-11 135 views
8

倍方法我想設置兩種方法用於摺疊兩個在同一時間

  1. :set foldmethod=indent並保留其所有功能
  2. 隱藏註釋與

    :set foldmethod=marker

    :set foldmarker=/*,*/

我發現這是不可能的。是否有可能實現所需的摺疊並將其設置爲.vimrc或者爲此使用一些腳本或插件?

回答

8

在同一緩衝區中不可能有不同的foldmethod類型。 Vim如何知道在與其他文本相同的縮進級別上有一些註釋要被視爲不同的(較高編號的)級別?

我相信你可以通過將foldmethod設置爲'expr'來達到你想要的效果。這是在Vim中進行摺疊的最靈活的方式,但根據您的需要可能會變得複雜(和/或緩慢)。儘管如此,我認爲它對於你的用例很容易。

首先,在您的vimrc或vimscripts中的某個地方,您需要確保foldexpr正在爲所討論的文件類型定義。

set foldexpr=MyFoldLevel(v:lnum) 
set foldmethod=expr 
" and for last code example 
let b:previous_level = 0 

然後你必須充實你的foldexpr函數,這樣它就可以按照你想要的行爲來分配級別。類似下面的代碼可能會在每個註釋行都有前綴符號(即不在您的情況下)的情況下接近工作,但我希望它需要一些調整。 h: fold-expr將是一個很好的地方尋求幫助:

function! MyFoldLevel(linenum) 
    " assign levels based on spaces indented and tabstop of 4 
    let level = indent(a:linenum)/4 
    if getline(a:linenum) =~ [put line-based comment prefix pattern here] 
     let level = 20 
    endif 
endfunction 

將需要修改分配徵求意見起點和終點之間的直線更高級別的標記你想要的方式:

function! MyFoldLevel(linenum) 
    let linetext = getline(a:linenum) 
    if linetext =~ [put line-based comment prefix pattern here] 
     let level = 20 
    elseif linetext =~ '^\s*/\*' 
     let level = 20 
    elseif linetext =~ '^\s*\*/' 
     let level = 21 
    else 
     if b:previous_level == 20 
      let level = 20 
     else 
      "assuming code is space-indented with tabstop of 4 
      let level = indent(a:linenum)/4 
     endif 
    endif 

    let b:previous_level = level 
    return level 

endfunction 

我不不要期望我寫的foldmethod函數能夠完全按照寫法工作。但他們確實指出了一些可行的方法。

請注意,對於註釋使用'20'級別只是任意級別,允許它們被摺疊,而所有(可能較低級別的)縮進代碼都可以被看到。最後一行評論部分的'21'只是爲了區分它與之前的20級註釋行,要知道下一行應該被視爲常規代碼行。

此外,當'zc'和'zo'等關鍵操作符被設置爲遠高於周圍代碼時,它們在註釋上不會正常工作。想要使用像:set foldlevel=21這樣的直接命令來顯示所有註釋行。

不是很漂亮,我希望它可以簡化一點,但類似這樣的事情是我認爲是你需要的。

實際上,再仔細考慮一下,我想你會希望任何註釋塊的第一行處於同一級別,就像它是非註釋行一樣,只有同一塊中的後續註釋行才需要將它們「摺疊」到開始註釋行中的級別更高。在我給出的代碼中,如果它工作或接近工作,我認爲vim會摺疊全部後面的非註釋行後面的註釋行,這不是您想要的,但我很遺憾沒有有更多的時間去投入這個小小的謎題。 。 。我已經完成了這種定製摺疊的很多次,而且一般都會有一些試驗和錯誤來獲得我想要的東西。

+0

是否有可能映射「ZO」命令「ZO」命令按21倍?我注意到多次按動ZO沒有副作用。它會減慢vim的速度嗎? – xralf 2011-05-12 18:28:49

1

基於語法的摺疊可能是一種更好的方式來獲得你想要的東西比我基於expr的方法在你的問題的不同答案中提出的建議。檢查:h fold-syn欲知更多信息。我認爲可能會有一些很好的解決方案用於基於c的摺疊。不知道它有多好,但這裏是基於語法的摺疊支持C-語法文件: http://www.vim.org/scripts/script.php?script_id=234 和另:以上 http://www.vim.org/scripts/script.php?script_id=925

的解決方案是完全基於語法的,不涉及使用縮進來確定摺疊級別。但是,如果需要,可以修改基於語法的摺疊來按縮進區域進行主摺疊。如果您根據語法元素縮進,結果可能是相同的。

這裏有一個技巧,演示如何只摺疊C風格的註釋(而不是實際的代碼) http://vim.wikia.com/wiki/Fold_C-style_comments

0

我有同樣的要求是你的,這是我的不完美的解決方案

我的製造者對是#< ===和#===>(或#地區和#endregion如pycharm)

let b:inBlock=0 
let b:lastLineNum=0 
let b:lastLevel=0 
let b:lastGoodLine=0 
let b:lastGoodBlock=0 
let b:startFoldingMark='^\s*.\?#<==*\|^\s*.\?#region' 
let b:endFoldingMark='^\s*.\?#=*=>\|^\s*.\?#endregion' 
function! MyFold(linenum) 
    let linetext = getline(a:linenum) 
    let level  = indent(a:linenum) /&shiftwidth 
    "the first line have 0 fold level 
    if (a:linenum == 1) 
     if linetext =~ b:startFoldingMark 
      let b:inBlock = 1 
      let b:lastLineNum=a:linenum 
      let b:lastGoodLine=0 
      let b:lastGoodBlock=0 
      let b:lastLevel=level 
      return level 
     endif 
     let b:inBlock=0 
     let b:lastInBlock=0 
     let b:lastLineNum=a:linenum 
     let b:lastGoodLine=0 
     let b:lastGoodBlock=b:inBlock 
     let b:lastLevel=level + b:inBlock 
     return level + b:inBlock 
    endif 

    " not calculate from the mid of text 
    if ((b:lastLineNum+1) != a:linenum) 
     let level  = indent(a:linenum) /&shiftwidth 
     let lastGoodNum = a:linenum-1 
     while (lastGoodNum>1 && getline(lastGoodNum) =~? '\v^\s*$') 
      let lastGoodNum -= 1 
     endwhile 
     if (foldlevel(lastGoodNum)==-1) 
      let b:inBlock=b:lastGoodBlock 
     else 
      let lastlevel = indent(lastGoodNum) /&shiftwidth 
      let lastlinetext = getline(lastGoodNum) 
      let lastlinelevel = foldlevel(lastGoodNum) 
      if lastlinetext =~ b:startFoldingMark 
       let b:inBlock = lastlinelevel - lastlevel + 1 
      elseif lastlinetext =~ b:endFoldingMark 
       let b:inBlock = lastlinelevel - lastlevel - 1 
      else 
       let b:inBlock = lastlinelevel - lastlevel 
      endif 
     endif 
    endif 

    "blank lines have undefined fold level 
    if getline(a:linenum) =~? '\v^\s*$' 
     let b:lastLineNum=a:linenum 
     let b:lastLevel=-1 
     return -1 
    endif 

    "if next line is a start of new marker block, inBlock ++ 
    if linetext =~ b:startFoldingMark 
     let b:lastLineNum=a:linenum 
     if (b:lastLevel != -1) 
      let b:lastGoodLine=a:linenum 
      let b:lastGoodBlock=b:inBlock 
     endif 
     let b:lastLevel=level + b:inBlock - 1 
     return level + b:inBlock - 1 
    "if next line is an end of new marker block, inBlock - 
    elseif linetext =~ b:endFoldingMark 
     let b:inBlock = b:inBlock - 1 
     let b:lastLineNum=a:linenum 
     let b:lastGoodLine=a:linenum 
     let b:lastGoodBlock=b:inBlock 
     let b:lastLevel=level + b:inBlock + 1 
     return level + b:inBlock + 1 
    endif 

    let b:lastLineNum=a:linenum 
    if (b:lastLevel != -1) 
     let b:lastGoodLine=a:linenum 
     let b:lastGoodBlock=b:inBlock 
    endif 
    let b:lastLevel=level + b:inBlock 
    return level+b:inBlock 
endfunction 

現在,我可以使用縮進摺疊方法時保持所有功能, ,我可以FO每個#< =,#=>標記塊, 此外,行的縮進摺疊關係仍然保留在每個塊中。

在此函數中,我避免使用「a1」,「s1」和「=」級別,這會導致此函數的迭代,並且對於大文件可能會很慢。 然而,在更新線,倍水平的計算可能是不正確的(因爲VIM可能無法更新從開始所有級別的摺疊,因此具有不正確inBlock值)

可以使用ZX手動更新倍水平。

多見於https://github.com/Fmajor/configs

相關問題