libformat / clang-format for table-like code

This Q&A asks about using clang-format to support table-like code:

http://stackoverflow.com/questions/38022831/how-to-make-clang-format-respect-table-like-code-formatting

Motivating examples for this sort of thing include GUI construction code (e.g., this Qt sample code: http://doc.qt.io/qt-5/qtwidgets-widgets-groupbox-example.html#window-class-implementation ).

The two cases mentioned in the Q&A could be slightly expanded to:

  1. Braced initializers (including C++11 initializer lists).

  2. Function calls

Each could include:

a. Rows and columns within a single statement (shown in Q&A)

b. Rows in different statements with columns following the same pattern for each row (shown in the Q&A with Create() functions – same function call, same number of params, etc.).

c. Nested tables,e.g.,

S s = {
{ { “Dubs”, abc, 123 },
{ “X”, n, m },
{ “YZ”, ij / q, kl } },

{ { “Dubs”, abc, 123 },
{ “X”, n, m },
{ “YZ”, ij / q, kl } },
};

vs. (perhaps depending on max line length or user option)

S s = {
{ { “Dubs”, abc, 123 }, { “X”, n, m }, { “YZ”, ij / q, kl } },
{ { “X”, n, m }, { “YZ”, ij / q, kl }, { “Dubs”, abc, 123 } },
};

Similar nesting could be done with function calls within function call params.

d. Rows and columns following a looser pattern (e.g., different function names, different number of params, optionally keeping return values):

w = CreateDubs( “Dubs”, abc, 123 );
x = CreateEx( “X”, n ); // Two params!
CreateWhyZed( “YZ”, ij / q, kl ); // Ignore return value

My question is, how hard would it be to modify LibFormat to support some or all of these cases?

I’m an experienced developer, but I’ve not done LLVM development before. I’m potentially interested in working on it and submitting a patch, but I thought I would ask here first in case you can tell me that it would be an exercise in futility or would be unlikely to be accepted as a feature. Would it have to support all of these cases to be accepted?

Cheers!

M

This Q&A asks about using clang-format to support table-like code:

http://stackoverflow.com/questions/38022831/how-to-make-clang-format-respect-table-like-code-formatting

Motivating examples for this sort of thing include GUI construction code
(e.g., this Qt sample code:
http://doc.qt.io/qt-5/qtwidgets-widgets-groupbox-example.html#window-class-implementation
).

The two cases mentioned in the Q&A could be slightly expanded to:

1. Braced initializers (including C++11 initializer lists).
2. Function calls

Each could include:

a. Rows and columns within a single statement (shown in Q&A)

I presume that you mean the first statement with the nested braced list.

I have always wanted to do this, but so far haven't been able to set aside
the time. I would guess that this isn't too hard based on the work that has
been done to layout non-nested braced lists in columns.

b. Rows in different statements with columns following the same pattern for

each row (shown in the Q&A with Create() functions -- same function call,
same number of params, etc.).

This should also be reasonably hard to do if you can live with certain
limitations. It could probably be implemented very similar to the style
options (http://clang.llvm.org/docs/ClangFormatStyleOptions.html)
AlignConsecutiveAssignments and AlignConsecutiveDeclarations.

c. Nested tables,e.g.,

  S s = {
    { { "Dubs", abc, 123 },
      { "X", n, m },
      { "YZ", ij / q, kl } },

    { { "Dubs", abc, 123 },
      { "X", n, m },
      { "YZ", ij / q, kl } },
  };

vs. (perhaps depending on max line length or user option)

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

I don't see the fundamental difference to (a) here. I think the two could
be implemented together.

Similar nesting could be done with function calls within function call

params.

This might get very tricky, I think. The danger I see is that it can become
unexpected that clang-format starts aligning specific things. Users
generally dislike if the result suddenly becomes unexpected. The question
is also how to control it. Say for a certain statement you'd really not
want this alignment. What do you do?

d. Rows and columns following a looser pattern (e.g., different function

names, different number of params, optionally keeping return values):

  w = CreateDubs( "Dubs", abc, 123 );
  x = CreateEx( "X", n ); // Two params!
  CreateWhyZed( "YZ", ij / q, kl ); // Ignore return value

Here also, the precise cases in which it should be done are much less clear
to me.

My question is, how hard would it be to modify LibFormat to support some or

all of these cases?

I'm an experienced developer, but I've not done LLVM development before.
I'm potentially interested in working on it and submitting a patch, but I
thought I would ask here first in case you can tell me that it would be an
exercise in futility or would be unlikely to be accepted as a feature.
Would it have to support all of these cases to be accepted?

(a), (b) and the first half of (c) certainly. I am less convinced that we
are going to find good, generally useful rules/heuristics for the rest.

Cheers,
Daniel