Make vim indent C preprocessor directives the same as other statements
c, indentation, preprocessor-directive, vim
Solution
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 */
}
}
Problem
General info (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`. Bad Thing 1 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. Bad Thing 2 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.) Bad Thing 3 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 `>>`. Failed solutions One solution suggests putting `set cinkeys-=0#` in my `.vimrc`. This fixes Bad Things 1 - 3, but adds a new one: Bad Thing 4 (only with `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. Question 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.