views:

563

answers:

6

We would like to make our C++ brace style more consistent. Right now, our code contains a mix of:

if (cond)
{
    // ...    
}
else
{
    // ...
}

...and:

if (cond) {
    // ...
} else {
    // ...
}

We want to use the latter style exclusively.

However, we don't want to change the indentation of our code. I've tried using astyle, bcpp, GNU indent and Uncrustify (and I've looked at the command-line options for GreatCode). Unfortunately, each of these tools insists on reindenting our code, and most of them mangle C++ constructor initializer lists and preprocessor macros pretty badly.

Are there any C++ code beautifiers which can fix braces while leaving indentation alone? It doesn't have to be a pre-existing tool--if you know how to do this using some crazy Perl one-liner, that's also good. Thank you!

Update: Yes, we aware that this will make it hard to read diffs against older code. This is a long-postponed code cleanup, and we've decided that the day-to-day advantages of consistent formatting outweigh any version-control difficulties.

+2  A: 

You really should think twice, and probably thrice, before doing this. It will completely destroy your source code control system's revision history at the point of change. You are using a source code control system, aren't you?

anon
maybe I'm being thick, but I don't get this. The only issue I see is that diffing files before and after the change will result in lots of diffs. I don't see how "It will completely destroy your source code control system's revision history".
Glen
Precisely - lots of diffs - probably on every other line, if short methods are being used. This will make the diffs useless - you would not be able to pick out the real changes from the noise caused by the re-formatting.
anon
Well, you are right. It won't completely destroy your revision history. It will only destroy your ability to compare affected newer code to older code across the change boundary. This may or may not matter to your or your project.
kmarsh
We've lived with this inconsistent formatting for 7+ years, and we've decided that we can afford a once-a-decade flag day to make our code more enjoyable to hack on. :-) All outstanding branches have been merged, and we're not concerned out our increasingly ancient stable branches.
emk
If you've lived with it for 7+ years, I can't see why you would change. It's not as if the style you are changing from is a particularly bad or uncommon style.
anon
About 75% of the code uses the style we want to use, and the remaining 25% uses the other style. If the overall style were actually consistent, we'd leave it alone.
emk
+2  A: 

The UNIX command Indent (http://en.wikipedia.org/wiki/Indent_(Unix)) (Available for PCs from GNU) has a million options to customize the reformating exactly as you like.

James Curran
As far as I can tell, most indent commands always reindent source code, just like all the other tools. Do you know any way to turn this off? Also, indent generally does not support C++.
emk
If you can (1) point me at a version of indent with the necessary options, and (2) explain anything which isn't obvious from the manual, then I'll accept this answer. But I've already spent half an hour looking at GNU indent with no luck.
emk
A: 

Wouldn't a hand full of simple regexs do the trick? Like (\).?\n.?\{) -> (\) \{) to delete the space between a closing bracket and an opening curly bracket.

DaClown
+5  A: 

Here's a Perl one-liner that should do what you want.

perl -pi.bak -e 'BEGIN { undef $/; } s/\s*?(\s?\/\/.*)?\r?\n\s*{/ {\1/g; s/}(\s?\/\/.*)?\r?\n\s*else\b(.*)/} else\2\1/g;'

It turns this:

int main(int argc, char *argv[])
{
    int something = 0;
    if (something)    // 5-12-2007
    {
        printf("Hi!\n");
    }
    else   // 5-13-2007
    {
        printf("Bye\n");
    }
    return 0;
}

into this:

int main(int argc, char *argv[]) {
    int something = 0;
    if (something) { // 5-12-2007
        printf("Hi!\n");
    } else { // 5-13-2007
        printf("Bye\n");
    }
    return 0;
}
Josh Kelley
Great! I'll try this out in an hour or so.
emk
Many thanks! This is a good start, and it can be adapted to handle other constructs like 'catch'.
emk
+2  A: 
perl -ei '$/=undef;while(<>){s/}\s*?(\s*\/\/^[\r\n]*)?\r?\n\s*else/} else$1/gm;s/(\s*\/\/[^\r\n]*)?\r?\n\s*{/ {$1/gm;print;}' yoursourcefile.cpp

This first mangles } <eol> <whitespace> else to } else, then removes end-of-lines from <eol> <whitespace> {.

To apply this to a source tree, use find and xargs:

find . -name \*.cpp -print0 | xargs -0 perl -ei '$/=undef;while(<>){s/}\s*?(\s*\/\/^[\r\n]*)?\r?\n\s*else/} else$1/gm;s/(\s*\/\/[^\r\n]*)?\r?\n\s*{/ {$1/gm;print;}'
laalto
A: 

I've tackled problems like this in the past by first running some tool like astyle to do 95% of what we wanted, and then writing a Perl or Python script over the result to finish the remaining 5%. Try it, it's always good practice to know your regular expressions. :)

Brian Neal