2

Why is the following C++ source file indented like this,

#include <vector>
int main() {
    std::vector<std::vector<int>> v{
        {1,2},
            {1,1},
            {1,2}
    };
}

and not like this?

#include <vector>
int main() {
    std::vector<std::vector<int>> v{
        {1,2},
        {1,1},
        {1,2}
    };
}

Another funny usecase is here

int g(int...) { return 1;}

int main() {
    g(
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                g(1)
             ),
            g(
                    g(1)
             ),
            g(
                    g(1)
             ),
            g(
                    g(1)
             ),
            g(
                    g(1)
             ),
            g(
                    g(1)
             )
            );

}

(Follow up question here.)

2

Indentation of C++ (and also C, Objective-C and even Java) is typically handled by enabling the 'cindent' option, which uses Vim's built-in C-indenting implementation, which recognizes elements of these languages (such as curly braces, semi-colons, etc.) and uses them as cues to decide whether to indent or unindent a specific line.

This indentation engine also supports options through the 'cinoptions' setting, which allows some more granular control over whether to implement indentation for specific patterns, or by how much to indent certain elements.

In your particular example, it turns out that setting :set cinoptions=+0 makes that specific block indent correctly. The + option controls indentation of continuation lines, so setting +0 effectively disables indentation continuation lines.

This will, of course, have other adverse side effects. For instance, if you have an assignment with a long expression, Vim will no longer indent the continuation lines under cinoptions=+0.

So I guess the main issue here is why Vim is recognizing this syntax as a continuation line at all.

I guess the better answer I can come up with is that the direct-list-initialization syntax you're using here was only introduced in C++11, and Vim support for C and C++ indentation predates that by a lot. When it was written, that syntax was not really valid C++, so the engine was not written to recognize it.

One thing that's pretty telling is that if you use copy-initialization with a = instead, Vim seems to be perfectly fine with that:

#include <vector>
int main() {
    std::vector<std::vector<int>> v = {
        {1,2},
        {1,1},
        {1,2}
    };
}

So I guess what you're after then is some support for C++11 (or C++14, C++17, etc.) indentation for Vim. I looked for plug-ins that would implement that, but while I found plug-ins that improve syntax highlighting for newer C++ specifications, I didn't really find one that improves indentation (but then I didn't look that hard... It's possible one exists.)

A plug-in that implements better indentation for a newer version of C++ (or a variant of a C language with a few differences from the original) can be accomplished by writing a Vimscript function and setting 'indentexpr' to use that function to make indentation decisions at every line. Since you mostly want to use the built-in rules of 'cindent' (and quite possibly some user-defined options from 'cinoptions'), you can also use the cindent() function to determine what the indentation would be under 'cindent', and then decide whether you can keep it, or adapt it. (In your case, you could detect the direct-list-initialization from C++11 and decide to adapt it at that point.)

Another alternative to fix it is to open a bug report (or feature request) to Vim itself. It's possible that 'cindent' was actually meant to cover newer features of the C++ language and better support for the newer standards is welcome and desirable. (And it's quite possible that it's not too hard to fix this, perhaps it's just a small tweak.) You could consider filing an issue on the GitHub tracker, or perhaps sending a message to one of the Vim development mailing lists.

  • Thank you very much for your detailed answer. Could you also give a look at my latest edit, where I gave another example of a strange indentatioin? – Enlico Dec 9 '20 at 14:16
  • 1
    The last example is due to the default of looking for unclosed parentheses at most 20 lines away, see :help cino-). You can tweak that with set cino+=)50 which fixes indentation of that specific code snippet. – filbranden Dec 9 '20 at 14:42
  • 1
    I guess you meant set cino+=)50. – Enlico Dec 9 '20 at 20:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.