How to collapse (fold) Doxygen comments by default in vim? - c++

We're looking at adding Doxygen documentation to C++ header files, but some people would prefer not to see the verbose Doxygen documentation by default.
Is there a way in .vimrc to fold (collapse) Doxygen comments by default?
Note: I have tried autocmd FileType c,cpp set foldmethod=syntax which will collapse all matching syntax, but I have been unable to figure out how to avoid collapsing functions, classes, et al., i.e. to only collapse Doxygen documentation format.
Another solution that looks like it might be a good one if the C-fold plugin for vim. Here's a detailed install sequence to get it working:
Add Doxygen syntax highlighting
(a) Install it from http://vim.sourceforge.net/scripts/script.php?script_id=5 which will create ~/.vim/syntax/doxygen.vim.
(b) Add ~/.vim\ftdetect\doxygen.vim with this single line:
au BufNewFile,BufRead *.doxygen setfiletype doxygen
(c) Add ~/.vim/syntax/doxygen_load.vim with these two lines:
au! Syntax {cpp,c,idl}
au Syntax {cpp,c,idl} runtime syntax/doxygen.vim
Add at the end of ~/.vimrc:
let mysyntaxfile='/home/dchinner/.vim/syntax/doxygen_load.vim'
autocmd FileType c,cpp set foldmethod=syntax
autocmd FileType c,cpp set foldlevel=10
Note that foldlevel determines how much will be folded initially. A high value will ensure most is open.
Add C-fold to (un)fold code or comments
(a) Install it from http://vim.sourceforge.net/scripts/script.php?script_id=1145 which will install ~/.vim/plugins/cfold.vim and ~/.vim/after/syntax/c.vim.
(b) Add at the end of ~/.vim/syntax/doxygen.vim:
syn region doxygenComment start= ... keepend fold
Done! You can now use these C-fold plugin key-combos:
z[ opens all doxygen-style comments
z] closes all doxygen-style comments
z{ opens all code blocks
z} closes all code blocks
vim a file with Doxygen comments, and hit z] to fold the Doxygen comments.

Both syntax/c.vim and syntax/doxygen.vim use syntax folding. Since there is no condition around the fold definitions in c.vim, you cannot turn off just one part.
You have to fork the default $VIMRUNTIME/syntax/c.vim into ~/.vim/syntax/c.vim, and remove all fold attributes from the syntax commands. That should leave just the doxygen parts folded (with :set foldmethod=syntax). The downside is that you have to maintain your special version of c.vim from now on.

Related

How to set up clang-format comment pragmas so multiline doxygen comments don't get touched?

I am trying to introduce clang-format to a couple of our projects at work (C and C++), but I am having trouble getting it to format multi-line Doxygen comments the way I want.
All comments have the same format:
/*! #brief Some text
*
* Some more text
*
* #verbatim
*
* A very long line of text that exceeds the clang-format column width but should not be touched
*
* #endverbatim
*/
I want clang-format to leave the verbatim blocks alone and not reflow them. I am using clang-format-6.0
Turning ReflowComments off is not an option as non-doxygen comments must be taken care of by clang-format
I have tried various regular expressions in the CommentPragmas config item but to no avail:
#verbatim(.*\n)*.*#endverbatim to treat the entire verbatim block as a comment pragma. This is the ideal situation, as any other part of the Doxygen comment I do not mind being broken into multiple lines.
#brief(.*\n)+ to match the entire comment block as the pragma. I've also tried this with an arbitrary token at the end of the comment to act as an explicit end-of-block marker. This isn't ideal as it doesn't force the non-verbatim part of the comment to conform, but is a compromise I'm willing to live with if I have to.
Various other regexes I've seen in other discussions, adapted to fit our Doxygen markup.
All I've managed to get it to do so far is to leave the first line of the multi-line comment alone, if it happens to exceed the column limit. However, any following long line is still broken up.
The only other tool I have left in my box is to use // clang-format off and // clang-format on around these comments but again I'd like to avoid it if I can because:
a) it'll be quite tedious to add them throughout the code base
b) I'll have to surround the entire comments with these, rather than just the verbatim blocks (I haven't figured out if you can disable it just for a portion of a multi-line comment - I've only managed to get it working for an entire one, and even if that was possible the clang-format directives would end up in the generated Doxygen docs which is unacceptable)
c) I don't really like the way it looks in code.
Any help is appreciated. Thanks.
Ran into this issue also, and the only work around found was to use clang-format on/off.
clang-format re flowing comments tends to:
break #page, #section, etc titles, and links generated from them (in rare cases).
break #startuml blocks, which have a specific syntax.
break #verbatim blocks.
See an example of usage in MySQL:
https://github.com/mysql/mysql-server/blob/8.0/storage/perfschema/pfs.cc
Update:
Filed a feature request on clang-format itself:
https://bugs.llvm.org/show_bug.cgi?id=44486

Vim automatic hard wrapping long comments in C++?

To reproduce my issue:
$ vim -u NONE test.cpp
:set nocompatible
:set tw=20
:set fo=croql
Now type in the following text:
/*
test test test test test test test test test
*/
Notice that there is no leading asterisk on the line containing the tests. Vim will insert this by default, remove it.
Vim should be auto-wrapping this, but it doesn't.
How can I make Vim wrap automatically in comments, and only in comments? :set fo+=t works, but then everything gets wrapped and I do not want automatic hard wrapping for code.
With my OnSyntaxChange plugin, you can change the 'fo' option value depending on whether the cursor inside a comment or not:
call OnSyntaxChange#Install('Comment', '^Comment$', 0, 'a')
autocmd User SyntaxCommentEnterA setlocal fo+=t
autocmd User SyntaxCommentLeaveA setlocal fo-=t
It's also available on GitHub.
Sorry, but Vim by itself cannot be configured to automatically wrap text in multi-line comments, without some character at the beginning of the line. The 'comments' option controls how Vim recognizes comments for automatic wrapping. Multi-line comments must have a "s", "e", and "m" part in the 'comments' option to be recognized; :help format-comments says: "Three-piece comments must have a middle string because otherwise Vim can't recognize the middle lines."
Nevertheless, you can still manually reformat such lines with the gq operator (shorthand gqq for a single line) and Vim should mostly do what you want. If it is slightly off, you can mess with the 'formatexpr' option.
You're probably better off just using the leading * in multi-line comments, or using //-style comments.
There are plugins available that use syntax-defined regions in clever ways which may allow you to work around these limitations. See Ingo's answer.
I'm using VIM 8.2 and it CAN wrap comments out of the box.
Short answer how
set tw=80
set fo=croaq
Check your comments option with :set comments?. I must contains /*, * and */ sequences.
Long answer
You can read details in :help formatoptions, :help fo-table and :help comments.
The tw=80 option is for limiting line width.
The formatoptions uses next flags here:
The c flag is to apply wrapping only for comments
The r and o flag is for auto-inserting the comment-leader on new lines (* symbol for /* styled comment in C-like languages).
The a will auto-format your paragraphs while you are typing.
The q option will handle the comment leader the correct way.
For some types of buffers you can apply formatoptions for all text like next:
"Limit line width for git commit messages to 72 characters
autocmd FileType gitcommit setlocal tw=72
"Auto format all text for git commit messages and markdown files
autocmd FileType gitcommit,markdown setlocal formatoptions+=t
Here
The t flag is to apply wrapping for text (additionally to c)
The comments option will help vim to detect comments correctly.

clang-format breaks lint annotations

We use lint in our codebase at work for C/C++, I'm trying to start integrating clang-format in my workflow as well.
Unfortunately, lint occasionally requires annotations to ignore a specific check, either of the format:
/*lint -[annotation] */
or
//lint -[annotation]
Specifically, if there's a space between the opening token for the comment and 'lint', it doesn't recognize it as an annotation directive. Unfortunately, the default settings I have for clang-format see that as an error and helpfully insert the space.
Is there any way to get clang-format to recognize comments matching that pattern and leave them alone? Right now I'm using 3.4, but could upgrade if needed.
Clang-format has a `CommentPragmas' option that is
A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed.
When I put the following line in my .clang-format file, my Lint comments remain untouched.
CommentPragmas: '^lint'
Other comments that still have "lint" in them, but are not Lint comments still get formatted.
You can disable clang-format for that section of your file by using:
int formatted_code;
// clang-format off
void unformatted_code ;
// clang-format on
void formatted_code_again;
See the Disabling formating on a piece of code section.

Easily comment (C++) code in vim

I have looked at the following question:
How to comment out a block of Python code in Vim
But that does not seem to work for me. How do I comment code easily without resorting to plugins/scripts?
Use ctrl-V to do a block selection and then hit I followed by //[ESC].
Alternatively, use shift-V to do a line-based select and then type :s:^://[Enter]. The latter part could easily go into a mapping. eg:
:vmap // :s:^://<CR>
Then you just shift-V, select the range, and type // (or whatever you bind it to).
You can add this to your .vimrc file
map <C-c> :s/^/\/\//<Enter>
Then when you need to comment a section just select all lines (Shift-V + movement) and then press CtrlC.
To un-comment you can define in a similar way
map <C-u> :s/^\/\///<Enter>
that removes a // at begin of line from the selected range when pressing CtrlU.
You can use the NERD commenter plugin for vim, which has support for a whole bunch of languages (I'm sure C++ is one of them). With this installed, to comment/uncomment any line, use <Leader>ci. To do the same for a block of text, select text by entering the visual mode and use the same command as above.
There are other features in this such as comment n lines by supplying a count before the command, yank before comment with <Leader>cy, comment to end of line with <Leader>c$, and many others, which you can read about in the link. I've found this plugin to be extremely useful and is one of my 'must have' plugins.
There's always #ifdef CHECK_THIS_LATER ... #endif which has the advantage of not causing problems with nested C-style comments (if you use them) and is easy to find and either uncomment or remove completely later.

To comment out matches in Vim - independent on comment leader?

I want to comment out lines in some code I have. I have different kinds of codes, and they use different comment leaders. E.g. in latex: '%', in Fortran 90: '!' and in python: '#'. I want to do a substitute command that looks something like this:
:g/<search-string>/s/^/<add-comment-leader-here>/
If this is possible, I could also make a command in Vim that automatically commented out the selected text. Something like this:
vmap <z> :'<,'>s/^/<add-comment-leader-here>/
Any ideas are welcome! :)
If you haven't seen it already, you may be interested in the NERD Commenter Vim plugin.
Check out Enhanced Commentify: I think this does what you want: it determines the comment leader based on the file type.
If you want to do it yourself, the easiest way would be to define a mapping that uses exec to build a command and include a variable that is set in your ~/.vim/after/ftplugin/c.vim and other ftplugin files. Alternatively, just add the same mapping (with a different leader) to each ftplugin file.