Reputation: 366
Vim supports syntax based folding for C code which works well. However the function name is not part of the fold, only the part between { and }.
given this example code:
static inline bool uFuzzyCompare(double p1, double p2)
{
return (uAbs(p1 - p2) <= 0.000000000001 * uMin(uAbs(p1), uAbs(p2)));
}
static inline bool uFuzzyComparef(float p1, float p2)
{
return (uAbsf(p1 - p2) <= 0.00001f * uMinf(uAbsf(p1), uAbsf(p2)));
}
static inline bool uFuzzyIsNull(double d)
{
return uAbs(d) <= 0.000000000001;
}
static inline bool uFuzzyIsNullf(float f)
{
return uAbs(f) <= 0.00001f;
}
This looks folded like this:
static inline bool uFuzzyCompare(double p1, double p2)
+-- 3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------
static inline bool uFuzzyComparef(float p1, float p2)
+-- 3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------
static inline bool uFuzzyIsNull(double d)
+-- 3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------
static inline bool uFuzzyIsNullf(float f)
+-- 3 lines: {----------------------------------------------------------------------------------------------------------------------------------------------------------------
I would prefer this:
+-- uFuzzyCompare(...) (5 lines)
+-- uFuzzyComparef(...) (5 lines)
+-- uFuzzyIsNull(...) (5 lines)
+-- uFuzzyIsNullf(...) (5 lines)
This means including the function declaration into the fold as well as the blank line and showing the function name as fold text.
Is this possible somehow? Maybe using foldmethod expression, but I don't know a good way to create this expression without writing a complete C parser. So using the syntax parser would be the best, but I could not find any configuration options for that.
regards, Gerhard
Upvotes: 2
Views: 640
Reputation: 32926
Correctly handling folding is not that trivial.
For instance, supporting K&R indenting style requires some work.
if (a_or_b) {
if (foo) {
a1();
} else if (bar) {
a2();
} else {
a3();
}
} else {
b();
}
Folding intelligently/nicely things like do {...} while(cond);
complicates things even further (as we need to support nested contexts)
do
{
act();
do {
a2();
}
while (inner);
}
while(outer)
;
Anyway, I've developed a solution that tries its best in a reasonable time: VimFold4C -- but no I don't support do { ... } while(cond);
yet, nor I exploit comments appearing at the beginning of folded zones :(.
Upvotes: 0
Reputation: 31419
This will get you on your way. It currently only folds top level functions. Put this in ~/.vim/ftplugin/c.vim
function! CFold()
if getline(v:lnum - 1)[0] ==# '}'
return '<1'
elseif getline(v:lnum + 1)[0] ==# '{'
return '>1'
endif
return '='
endfunction
function! CFoldText()
let line = getline(v:foldstart)
let sub = substitute(line, '.*\<\(\w\+\)(.*).*', '\1(...)', 'g')
return '+-- ' . sub . ' (' . (v:foldend - v:foldstart + 1) . ' lines)'
endfunction
setlocal foldmethod=expr
setlocal foldexpr=CFold()
setlocal foldtext=CFoldText()
setlocal fillchars-=fold:-
Output for the example text
+-- uFuzzyCompare(...) (5 lines)
+-- uFuzzyComparef(...) (5 lines)
+-- uFuzzyIsNull(...) (5 lines)
+-- uFuzzyIsNullf(...) (5 lines)
How this works. When you set foldmethod to expr vim uses the expression in foldexpr to determine how it should fold. All I am doing is checking to see if the line after after the current contains a {
in the first column if it does we set the fold level to >1
which says start a fold of level 1. It end on the line the }
. <1
says end a fold of level 1.
To set the fold text we just extract the function and replace the arguments with ...
(This might break for lines where the arguments are multiple lines). Then we return a nicely formatted string. v:foldstart
and v:foldend
are variables set that say which line the fold starts and end on.
Removing fold:-
from fillchars removes the dashes after the fold text.
Relevant help pages :h 'foldmethod'
, :h foldexpr
, :h foldtext
, and :h 'fillchars'
Upvotes: 4