Reactive vim fold plugin for C & C++ (and similar languages).
Unlike folding on syntax or on indent, this script tries to correctly detect the fold boundaries.
The foldtext displayed will also try to be as pertinent as possible:
- Correctly indented
- Strip spaces in parenthesis
- Strip
scopes::
(optional) - Multiple subsequent (consecutive ?)
#include
will be condensed into one line #if
& co are folded- When the fold text line to display is too long, simplifications are operated:
- Template parameters may be discarded
- Initialisation-lists are replaced with
....
- Parameter names are discarded (this requires lh-cpp).
- Last parameters are discarded
- fold any instruction, or declaration, spanning on several lines (
cout
,printf
,log(stuff << stuff)
In order to keep the plugin reactive, I had to introduce a few hacks that
diminish the precision of the incremental algorithm used to detect fold
boundaries.
As a consequence, sometimes lines are folded in a very strange way.
In order to fix it, use zx
or zX
to reset all fold boundaries.
Here is a little screencast to see how things are displayed with VimFold4C.
Note: the code comes from unrelated experiment of mine.
You can set local or global options to tune the behaviour of this fold-plugin.
" In the .vimrc
let g:fold_options = {
\ 'fallback_method' : { 'line_threshold' : 2000, 'method' : 'syntax' },
\ 'fold_blank': 0,
\ 'fold_includes': 0,
\ 'max_foldline_length': 'win',
\ 'merge_comments' : 1,
\ 'show_if_and_else': 1,
\ 'strip_namespaces': 1,
\ 'strip_template_arguments': 1
\ }
or from a local_vimrc plugin:
let b:fold_options = {
\ 'fallback_method' : { 'line_threshold' : 2000, 'method' : 'syntax' },
\ 'fold_blank': 1,
\ 'fold_includes': 1,
\ 'ignored_doxygen_fields': ['class', 'ingroup', 'function', 'def', 'defgroup', 'exception', 'headerfile', 'namespace', 'property', 'fn', 'var'],
\ 'max_foldline_length': 'win',
\ 'merge_comments' : 0,
\ 'show_if_and_else': 1,
\ 'strip_namespaces': 1,
\ 'strip_template_arguments': 1
\ }
The options are:
-
fallback_method
(default:{'line_threshold': 0}
) tells to use another fold method when the number of lines in the current file is greater to the given threshold.
In that case usefallback_method.method
on the current buffer as fold method -- (default:"syntax"
).
This option is ignored if the threshold equals 0. -
fold_blank
(default: true) tells to fold blanks lines with the lines preceding them. -
fold_includes
(default: true) tells to fold blocks of#include
directives. -
ignored_doxygen_fields
(default:['class', 'ingroup', 'function', 'def', 'defgroup', 'exception', 'headerfile', 'namespace', 'property', 'fn', 'var']
) list of doxygen keywords that shall be ignored when computing the folded text -- whenmerge_comments == 0
-
max_foldline_length
(default: "win") specifies the maximum line length of the fold text. The possibile values are:- "win": stops at current window width
- "tw": stops at current
'textwidth'
column - number: hardcoded maximum number of characters to keep.
-
merge_comments
(default: 1) specifies whether comments shall be folded together with the code or separativelly. -
strip_namespaces
(default: true) tells to strip scopes likestd::
orboost::filesystem::
from the fold text generated. -
strip_template_arguments
(default: true) strips template arguments from the fold text generated if the text would be too long for the current window width -
show_if_and_else
(which is currently hard-coded to true) requires to have two folds onif (foo) { foo_action(); } else { bar_action(); }
instead of the single fold we have when using
indent
foldmethod (or was it thesyntax
one ?).
Do not set the
'foldmethod'
option in a ftplugin, or in an autocommand. VimFold4C already takes care of
setting it to expr
.
-
Requirements: Vim 7.+, lh-vim-lib 4.2.0+
-
With vim-addon-manager, install VimFold4C.
ActivateAddons VimFold4C
-
or with vim-flavor which also supports dependencies:
flavor 'LucHermitte/VimFold4C'
-
When installing lh-cpp with vim-addon-manager, or other plugin managers based on vim-pi, or with vim-flavor this fold-plugin will get automatically installed.
ActivateAddons lh-cpp " Or just this one (and soon as I register it in vim-pi): ActivateAddons VimFold4C
This is the preferred method because of the various dependencies, and because VimFold4C will do a better job if lh-cpp is installed and detected.
-
or with Vundle/NeoBundle (expecting I haven't forgotten anything):
Bundle 'LucHermitte/lh-vim-lib' Bundle 'LucHermitte/VimFold4C'
So far, it is only triggered for C and C++. It should be easy to use it from C#, Java, and other languages with C like syntax: a
runtime ftplugin/c/c-fold.vim
from a C#/Java/... ftplugin should do the trick.
However, I'm unlikely to handle specials cases in those languages.
There is still a lot to be done:
- [optional] Fold visibilities
#include
- [optional] cut the foldtext line when it's too long to fit
- [optional] strip the dirname of each included file to build the foldtext line.
- Comments
- Correctly handle comments for fold boundaries detection
- [optional] when there is a leading comment, add a summary at the end of the fold text
- [optional] support a policy for comments handling (integrated to the following fold, independent fold, not folded)
- use @doxygen tags to build comments foldtext
- File headers shall have a special treatment -> detect copyrights/licence/... to build the foldtext
- Tests
- Test, Test, and re-test!
- Test with C++11 lambdas
- Control statements
switch
/case
- increment foldlevel for every
case
- [optional] merge
case
s that aren't separated by abreak;
- increment foldlevel for every
do { } while();
requires a specific handling
-
A long time ago (~2001), Johannes Zellner published a first folding plugin for C & C++.
-
Then, I did some changes (2002-2004), but the result was very slow at the time. (the last version is still archived in http://hermitte.free.fr/vim/ressources/lh-cpp.tar.gz)
-
Eventually I got tired of the slow execution times and moved back to
foldmethod=indent
. -
Here is a new (2014) version almost entirely rewritten, that I hope will be fast enough to be usable.