Is there a way that I can setup vim to automatically fold ruby source files, but only fold at the method level regardless of the level that they are defined?
So it will fold when I have:
class MyClass
def method
...
end
end
but also when I have:
module FirstModule
module SecondModule
class MyClass
def method
...
end
end
end
end
I've experimented with foldmethod=syntax and various fold levels but it doesn't take into account the depth where the method is defined.
Also I don't want nothing inside the method to get folded (if blocks, each blocks, etc).
I think foldmethod=expr would be my best bet, but I haven't manage to figure out how fold expressions work, and the help in vim hasn't been very enlightening.
Your hunch about using the expr
method, I believe, was correct!
You can use the syntax structure of the file to jury-rig your own syntax
-style folding. The following in my .vimrc
produced expected behavior:
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)
Some caveats:
I'm not sure if the final argument to synID
should be 0
or 1
. It's the argument that determines whether you get the syntax information for the topmost transparent or non-transparent element at the provided location. When there's no transparent element, the argument has no effect. In the trivial example I tried, it didn't cause any issues, but it might.
It's also worth noting that the line_is_def
regex is probably too lenient. It might be better to return -1
in this situation, so a line matching the regex is only folded when it's right next to the folded method block. A more restrictive regex could also work.
If you're feeling squirrely, you could expand on this and return separate foldlevels for rubyClass
and rubyModule
elements as well.
If you decide to go down that route, there are some useful custom functions in my .vimrc for introspecting into syntax elements and hilighting. They're handiest when mapped to a keybinding for quick use like so:
nnoremap g<C-h> :echo GetSynInfo()<CR>
Please do let me know if this works out for you! It was fun to figure out. Also, for what it's worth, while :help 'foldexpr'
is light on details, :help 'fold-expr'
is much more helpful, and even has some examples at the top.