metal
metal

Reputation: 6332

How to make clang-format respect "table-like" code formatting

I have code that has tables of data or parameters that is aligned in columns like the following (contrived simple example; real code has much bigger tables):

//        Name    Size    Starting val
//        ======= ======= ============
S s = {
        { "Dubs", abc,    123 },
        { "X",    n,      m   },
        { "YZ",   ij / q, kl  } 
    };

//           Name    Size    Starting val
//           ======= ======= ============
w  = Create( "Dubs", abc,    123 );
x  = Create( "X",    n,      m   );
yz = Create( "YZ",   ij / q, kl  );

clang-format kills the table formatting:

//        Name    Size    Starting val
//        ======= ======= ============
S s = {
    { "Dubs", abc, 123 },
    { "X", n, m },
    { "YZ", ij / q, kl }
};

//           Name    Size    Starting val
//           ======= ======= ============
w  = Create( "Dubs", abc, 123 );
x  = Create( "X", n, m );
yz = Create( "YZ", ij / q, kl );

Our team wants to adopt clang-format and run it automatically, but this issue is preventing us from doing so. We could manually go through and wrap all such cases in // clang-format off/on tags, but that's manual labor.

Is there a way to setup clang-format to keep tables like this, or even to table-ize new code automagically?

Upvotes: 11

Views: 2193

Answers (2)

Claudio Perez
Claudio Perez

Reputation: 106

As of clang-format 13 there is a new AlignArrayOfStructures option available that can help with exactly this.

Upvotes: 1

Ash
Ash

Reputation: 1966

You will not be able to get clang-format to respect all custom inhouse formatting, and their documentation on adding new style options is pretty tight. The adoption of clang-format into an existing codebase requires some compromising. This is one of those compromises.

I was in your situation, a large codebase with dozens of engineers fixed in their ways and unwilling to change their inhouse coding standard. I had done several large refactors which had weeks of fixing up spacing. Not a good use of time.

I was unable to navigate the politics of standardising the legacy formatting. Clang-Formats adoption was conditional on it respecting our legacy formatting.

My solution was to write a wrapping script which would read the file in, detect the inhouse oddities (in your case, look for a long comment of only '=' and ' ') and sandwich them in clang-format instructions:

// clang-format off
// AddedByYourTool
//           Name    Size    Starting val
//           ======= ======= ============
w  = Create( "Dubs", abc,    123 );
x  = Create( "X",    n,      m );
yz = Create( "YZ",   ij / q, kl );
// clang-format on

It would then pipe it through clang-format. Then find the AddedByYourTool in the output and remove the surrounding clang-format off. (You need that token so you don't remove existing clang-format offs).

It sucks. It is a horrible solution, but unless you have the power to order that formatting to die, or the political skills to negotiate it to die, or feel like manually reformatting for the rest of your career, it's the only real solution.

Upvotes: 3

Related Questions