Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang-format line breaks

I'm looking for a clang-format setting to prevent the tool from removing line breaks.

For example, I have my ColumnLimit set to 120, and here's what happens when I reformat some sample code.

Before:

#include <vector> #include <string>  std::vector<std::string> get_vec() {    return std::vector<std::string> {       "this is a test",       "some of the lines are longer",       "than other, but I would like",       "to keep them on separate lines"    }; }  int main() {    auto vec = get_vec(); } 

After:

#include <vector> #include <string>  std::vector<std::string> get_vec() {    return std::vector<std::string>{"this is a test", "some of the lines are longer", "than other, but I would like",          "to keep them on separate lines"}; }  int main() {    auto vec = get_vec(); } 

What I would like is that the tool breaks lines that are over 120 characters, but doesn't decide to combine lines just because they are less than 120 characters.

Is there such an option? Nothing in the docs stood out to me.

like image 502
zmb Avatar asked Nov 11 '15 17:11

zmb


People also ask

Can clang format break code?

Short answer: YES. The clang-format tool has a -sort-includes option. Changing the order of #include directives can definitely change the behavior of existing code, and may break existing code.

What is clang tidy?

Clang-tidy is a standalone linter tool for checking C and C++ source code files. It provides an additional set of compiler warnings—called checks—that go above and beyond what is typically included in a C or C++ compiler.

How do you format a clang file?

You can install clang-format and git-clang-format via npm install -g clang-format . To automatically format a file according to Electron C++ code style, run clang-format -i path/to/electron/file.cc . It should work on macOS/Linux/Windows.

Does clang format work for C?

clang-format is located in clang/tools/clang-format and can be used to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code.


1 Answers

So, having messed around in the clang format code and made some patches, here's my two cents:

  • Clang format is based on,

    • parsing the AST using libclang, which basically eliminates all whitespace
    • breaking up the token sequence into "unwrapped lines" which are like "logical" code lines
    • Applying rules / configuration info to sometimes split up "unwrapped lines" into smaller units
    • Spit it all back out again with new whitespace / indentation

    It's not easy to make it respect the original whitepsace, that sort of gets tossed when you first parse the code.

  • You can control where it places line breaks, most easily, by

    • setting the column limit
    • using the "bin pack parameters" options
    • setting penalties for various kinds of breaks -- break after return type of a function, break before first call parameter, break a string literal, break a comment...
    • placing comments at the end of a line (clang format cannot remove the comment and must therefore split the line)
    • use the clang-format off / on directives

Here's one thing you could try:

std::vector<std::string> get_vec() {    return std::vector<std::string> {   //       "this is a test",                //       "some of the lines are longer",  //       "than other, but I would like",  //       "to keep them on separate lines" //    }; } 

The advantage of this over // clang-format off is that, if you later change the tab width or some other option, those code lines will still get those formatting changes so you don't need to manually go into the // clang-format off regions to fix it. However it's still a bit of a hack, YMMV.

Ultimately, clang-format is very much about imposing a uniform format over an entire code base, making sure that all string literals are formatted in the same style everywhere in your program. If you want to have micro-level control over line-break decisions, that's not really in the spirit of the tool, and you'll have to do things like disable it.

This can sometimes be frustrating esp. when you want to do things with arrays and have columns aligned or something -- for instance, here's some natural code from lua C api:

static luaL_Reg const methods[] = {     {"matches",               &dispatch::intf_match_unit},     {"to_recall",             &dispatch::intf_put_recall_unit},     {"to_map",                &dispatch::intf_put_unit},     {"erase",                 &dispatch::intf_erase_unit},     {"clone",                 intf_copy_unit},     {"extract",               &dispatch::intf_extract_unit},     {"advance",               intf_advance_unit}, }; 

When clang-format runs over that, it's generally not going to align the right column, its going to place it a fixed number of spaces after the commas and there's not much you can do about it afaik.

Or, if you have 4 x 4 matrix for use with OpenGL:

      constexpr float shadow_skew_hardcoded[16] =         { 1.0f, 0.0f, 0.0f, 0.0f,           0.5f, 0.5f, 0.0f, 0.0f,           0.0f, 0.0f, 1.0f, 0.0f,           0.0f, 0.0f, 0.0f, 1.0f }; 

If you let clang-format run over things like this it's just going to mangle them, and afaik there's no easy way to make it format them nicely, so you just have to resort either to the "lots of trivial comments" hack, or use clang-format off when you have something like this. These are just intrinsic limitations of the tool. If you aren't happy ever to have to do things like that then it's probably not the tool for you.

like image 147
Chris Beck Avatar answered Oct 08 '22 10:10

Chris Beck