2011-09-29 74 views
12

有沒有辦法讓我可以設置vim來自動摺疊ruby源文件,但只在方法級別摺疊,而不管它們被定義的級別如何?vim中的自動ruby摺疊

所以,當我把它必倍:

class MyClass 
    def method 
    ... 
    end 
end 

而且,當我有:

module FirstModule 
    module SecondModule 
    class MyClass 
     def method 
     ... 
     end 
    end 
    end 
end 

我已經使用foldmethod =語法和各種倍的水平,但嘗試它並不需要考慮方法定義的深度。

此外,我不想在方法內部沒有摺疊(如果塊,每個塊等)。

我認爲foldmethod = expr會是我最好的選擇,但我還沒弄清楚fold表達式是如何工作的,而vim的幫助並不是很有啓發性。

回答

11

您好,我相信使用expr的方法是正確的!

您可以使用該文件的語法結構來評估您自己的syntax樣式摺疊。在我.vimrc產生預期的行爲如下:

function! RubyMethodFold(line) 
    let line_is_method_or_end = synIDattr(synID(a:line,1,0), 'name') == 'rubyMethodBlock' 
    let line_is_def = getline(a:line) =~ '\s*def ' 
    return line_is_method_or_end || line_is_def 
endfunction 

set foldexpr=RubyMethodFold(v:lnum) 

一些注意事項:

我不知道,如果最後一個參數synID應該01。這是決定您是否在所提供的位置獲得最上面的透明非透明元素的語法信息的參數。當沒有透明元素時,參數不起作用。在我試過的簡單例子中,它沒有引起任何問題,但它可能。

值得一提的是,line_is_def正則表達式可能太寬大了。在這種情況下返回-1可能會更好,因此與正則表達式匹配的行僅在摺疊方法塊旁邊摺疊。更嚴格的正則表達式也可以工作。

如果您感到很沮喪,您可以擴展此功能,並返回rubyClassrubyModule元素的單獨foldlevel。

如果您決定沿着這條路線走下去,有一些useful custom functions in my .vimrc用於內省語法元素和hilighting。當他們被映射到一個快速使用的鍵排序時,他們是最方便的:

nnoremap g<C-h> :echo GetSynInfo()<CR> 

請讓我知道這是否適合您!弄清楚是很有趣的。此外,對於它的價值,:help 'foldexpr'對細節很重要,:help 'fold-expr'更有幫助,甚至在頂部有一些例子。

+2

這是一個很好的答案。這看起來是一個正確的解決方案,或者至少是一個很好的起點,可以讓我得到我想要的東西。我會測試一下今天晚些時候的工作方式,並接受你的答案。你的vimrc看起來也是一個很好的學習資源,特別是你定義的所有功能。謝謝。 – adivasile

+0

非常歡迎您!快樂vimming! –

+0

順便說一下,我很想知道這是怎麼解決的! –

1

通過使用zO命令,您也許能夠擺脫方法內部摺疊的解決方案。 zO遞歸地打開摺疊,所以如果你使用它而不是zo,就好像這個方法裏面沒有東西被摺疊一樣。如果你感到很沮喪,你也可以重映射zozO

+0

確實會有幫助,但主要問題仍然存在:使方法自動摺疊。 – adivasile

3

您可能有這個更好的運氣,特別是如果你已經有了語法高亮:

這會進入你的〜/ .vimrc

 
"" Enable folding based on syntax rules 
set foldmethod=syntax 

"" Adjust the highlighting 
highlight Folded guibg=grey guifg=blue 

"" Map folding to Spacebar 
nnoremap za 

這也是在摺疊很大VIMcast:http://vimcasts.org/episodes/how-to-fold/

4

對Max Cantor的解決方案做出了改變,我的作品完美無缺,它將摺疊def方法(包括end關鍵字)和documentations(= begin = end)塊,而不管它在哪裏(在一個類中或縮進)

function! RubyMethodFold(line) 
    let stack = synstack(a:line, (match(getline(a:line), '^\s*\zs'))+1) 

    for synid in stack 
    if GetSynString(GetSynDict(synid)) ==? "rubyMethodBlock" || GetSynString(GetSynDict(synid)) ==? "rubyDefine" || GetSynString(GetSynDict(synid)) ==? "rubyDocumentation" 
     return 1 
    endif 
    endfor 

    return 0 
endfunction 

set foldexpr=RubyMethodFold(v:lnum) 

set foldmethod=expr 

感謝Max Cantor爲他的幫助方法打印出語法信息。

讓我解釋一下線這條線:

最重要的線將是第二行那裏得到語法元素的verious水平的堆在一條線上。 所以如果你有一條像def methodname這樣的行,在它之前有空格或製表符,它總是會在第一個非空白字符處得到堆棧。 Max Cantor的解決方案存在的問題是,他的代碼只會打印出該行第一列中找到的最低語法元素,因此它總是會返回一些隨機的元素,比如我們不關心的「rubyContant」。

所以通過使用match(getline(a:line), '^\s*\zs')我們可以將光標移動到第一個非空白字符的列,這樣我們就可以獲得更準確的堆棧圖。 +1,因爲匹配是零索引的。

然後剩下的就和GetSynInfo方法類似,我們通過堆棧循環並匹配我們想要的元素,然後返回1,所以它們都在同一個摺疊級別上,其餘的都是0。

就是這樣,工作摺疊expr的功能只會折紅寶石定義方法:)

享受和有一個愉快的一天!

+1

您的答案看起來很有希望,但不幸的是,當我嘗試它時,什麼都沒有發生。看起來解決方案錯過了這些函數的定義:'GetSynString'和'GetSynDict'。你能不能照顧他們?謝謝 –

1

我製作了vim-ruby-fold插件,用於簡單的紅寶石摺疊方法。我希望它可以幫助人們。