(Note: Please read this all the way through, because I spent a bit of time organizing it, making sure I addressed each individual problem I'm having and why one proposed solution doesn't work for me.)
I'm using cindent in vim to automagically do indentation. It works great most of the time. However, cindent does three Bad Things (in my opinion) involving C preprocessor directives (statements starting with a hash ('#')).
In case it's relevant, I use tabs for indentation, and I my .vimrc contains filetype indent on
.
As soon as I type a preprocessor directive, vim puts it in column 1 (it completely un-indents it). For example, here's what vim does to my code as I type it:
int main(void)
{
while(1) {
/* normal things */
#ifdef DEBUG
printDebugInfo();
#endif
/* normal things */
}
}
However, I want it look like this:
int main(void)
{
while(1) {
/* normal things */
#ifdef DEBUG
printDebugInfo();
#endif
/* normal things */
}
}
In other words, I'd prefer that vim treat preprocessor directives like any other C/C++ statement.
When I use ==
on (or [movement]=
across) a line with a preprocessor directive, vim puts it back in column 1. (This is consistent with Bad Thing 1 but still a problem.)
If (because of Bad Thing 1 or 2 or the use of <<
) a preprocessor directive ends up in column 1, it becomes "stuck" there and isn't affected by >>
. The only way to increase the indentation is I<Tab>
or i<Ctrl-t>
. It then becomes "un-stuck" and I can move it with <<
or >>
.
One solution suggests putting set cinkeys-=0#
in my .vimrc
. This fixes Bad Things 1 - 3, but adds a new one:
cinkeys-=0#
)Preprocessor directives in column 1 aren't affected by ==
or [movement]=
, meaning I still can't automagically fix their indentation until I manually indent them with >>
or by inserting a tab character.
Is there a way to resolve Bad Things 1 - 3 without introducing Bad Thing 4? Can I force vim to treat lines starting with '#' like ordinary C statements?
(Or am I just using #ifdef
s in a harmful way, and this is vim's way of telling me to stop?)
I'd prefer not to patch vim and/or recompile, but I will if I have to.
C static code analysis: Preprocessor directives should not be indented.
Preprocessing is an initial phase to process text before compilation. Preprocessor directives are lines of the source file where the first non-whitespace character is # , which distinguishes them from other lines of text.
Macro: a word defined by the #define preprocessor directive that evaluates to some other expression. Preprocessor directive: a special #-keyword, recognized by the preprocessor. Show activity on this post. preprocessor modifies the source file before handing it over the compiler.
Preprocessor directives are lines included in a program that begin with the character #, which make them different from a typical source code text. They are invoked by the compiler to process some programs before compilation.
From the Vim documentation, under cinoptions:
Vim puts a line in column 1 if:
- It starts with '#' (preprocessor directives), if 'cinkeys' contains '#'.
- It starts with a label (a keyword followed by ':', other than "case" and "default") and 'cinoptions' does not contain an 'L' entry with a positive value.
- Any combination of indentations causes the line to have less than 0 indentation.
So, removing 0#
from cinkeys
should override that default behavior. (This idea turns up in enough places on the interwebs.)
set cinkeys=0{,0},0),:,!^F,o,O,e
With that change to cinkeys, here's what I got, exactly what you're looking for:
int main(void)
{
while(1) {
/* normal things */
#ifdef DEBUG
printDebugInfo();
#endif
/* normal things */
}
}
set cinoptions+=#1s
This will indent by 1 shiftwidth if you use ==
or [movement]=
. Combining it with the option cinkeys-=0#
worked for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With