【问题标题】:Clang-format line breaksClang 格式的换行符
【发布时间】:2016-02-12 21:54:48
【问题描述】:

我正在寻找 clang-format 设置以防止该工具删除换行符。

例如,我将 ColumnLimit 设置为 120,这就是我重新格式化一些示例代码时发生的情况。

之前:

#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();
}

之后:

#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();
}

我想要的是该工具会中断超过 120 个字符的行,但不会仅仅因为它们少于 120 个字符而决定合并行。

有这样的选择吗?文档中的任何内容都没有让我印象深刻。

【问题讨论】:

  • 对于您的特定示例,设置AllowShortFunctionsOnASingleLine: None 将起作用。
  • 好吧,这会阻止它展开main,但我更关心一般的向量初始化。如果向量在另一个(更长的)函数中以这种方式初始化,它仍然会被解包。
  • 我想知道调整各种“惩罚”选项是否会有所帮助,但它们似乎都是与断线相关的惩罚,而不是“破坏”它们。
  • 你能举一个上面的设置不能按预期工作的例子吗?该工具不再缩短您的功能,并且应该尊重列限制。向量初始化也应该起作用。
  • 我更新了问题中的示例。使用AllowShortFunctionsOnASingleLine: Nonemain 不再展开,但正如您所见,向量初始化仍然混乱。

标签: c++ clang code-formatting clang-format


【解决方案1】:

使用 .clang 格式的这些规则

BasedOnStyle: LLVM
AlignAfterOpenBracket: AlwaysBreak
AllowShortBlocksOnASingleLine: Empty
BreakConstructorInitializers: AfterColon
BinPackArguments: false  // Important for this case
BinPackParameters: false  // Important for this case
AlignEscapedNewlines: DontAlign
SpacesBeforeTrailingComments: 2
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None
ContinuationIndentWidth: 2
IndentWidth: 2
Standard: c++17
UseTab: Never

我得到了接近预期结果的格式

#include <string>
#include <vector>

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();
}

【讨论】:

    【解决方案2】:

    在最后一个字符串后添加一个逗号。这告诉 clang-format 垂直格式化它。前任: https://godbolt.org/z/bZxr__右键>格式化文本

    #include <string>
    #include <vector>
    
    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", // comma here after last element
      };
    }
    
    int main() { auto vec = get_vec(); }
    

    【讨论】:

    • 我喜欢它,但这对我来说并不明显。为什么它起作用?是否有控制它的样式选项?
    • 枚举中的尾随逗号具有相同的作用
    【解决方案3】:

    所以,弄乱了 clang 格式的代码并做了一些补丁,这是我的两分钱:

    • Clang 格式基于,

      • 使用libclang解析AST,基本上消除了所有的空格
      • 将标记序列分解为“展开的行”,类似于“逻辑”代码行
      • 应用规则/配置信息有时将“展开的行”拆分为更小的单元
      • 用新的空格/缩进再次把它全部吐出来

      要让它尊重原始的 whitepsace 并不容易,当你第一次解析代码时会被扔掉。

    • 您可以通过以下方式最轻松地控制换行符的位置

      • 设置列限制
      • 使用“bin 包参数”选项
      • 为各种中断设置惩罚 -- 在函数返回类型后中断、在第一个调用参数之前中断、字符串文字中断、注释中断...
      • 将 cmets 放在行尾(clang 格式无法删除注释,因此必须拆分行)
      • 使用 clang 格式的 off / on 指令

    您可以尝试以下一件事:

    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" //
       };
    }
    

    // clang-format off 相比,它的优势在于,如果您稍后更改选项卡宽度或其他选项,这些代码行仍将获得这些格式更改,因此您无需手动进入// clang-format off 区域要解决这个问题。但是,它仍然有点 hack,YMMV。

    最终,clang-format 非常注重在整个代码库中采用统一的格式,确保所有字符串文字在程序中的任何地方都以相同的样式格式化。如果您想对换行决策进行微观层面的控制,这并不真正符合该工具的精神,您必须执行诸如禁用它之类的操作。

    这有时会令人沮丧,尤其是。当你想对数组做一些事情并让列对齐或其他东西时——例如,这里有一些来自 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},
    };
    

    当 clang-format 超过它时,它通常不会对齐右列,它会在逗号后面放置固定数量的空格,而且你无能为力。

    或者,如果您有用于 OpenGL 的 4 x 4 矩阵:

          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 };
    

    如果你让 clang-format 运行这样的东西,它只会破坏它们,而且 afaik 没有简单的方法让它很好地格式化它们,所以你只需要求助于“很多琐碎的 cmets”黑客, 或者当你有这样的东西时使用 clang-format off。这些只是该工具的内在限制。如果你对不得不做这样的事情感到不高兴,那么它可能不适合你。

    【讨论】:

    • 很好的答案。你的建议似乎比// clang-format off 好一点,而且解释为什么它会这样表现很有意义。
    • ColumnLimit 0 仍然保留换行符。这怎么解释?
    • 我必须调整您的技术,因为我使用的是多行 #define 宏。诀窍是用 ` /**/\` 结束每一行
    【解决方案4】:

    我不确定您的 clang-format 是否完全按照您的意愿行事,但可以告诉 clang-format 不理会部分代码。我将它用于您正在谈论的那种场景,即非常特殊的格式使其更易于阅读的代码块。

    std::vector<std::string> get_vec()
    {
       // clang-format off
       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"
       };
       // clang-format on
    }
    

    见: http://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code

    【讨论】:

    • 我并不是说这是一个糟糕的答案,而是这个问题的绝对可怕的解决方案。使用 cmets 使您的代码杂乱无章,以使自动格式化工作。
    • 也许吧,但在实践中,我很少在想破坏格式规则的地方使用它。我通常很欣赏有这样的出局,并且不欣赏它被“弄乱你的代码”所滥用。使用不当的工具往往是用户的责任
    【解决方案5】:

    我目前在documentation 中没有看到任何可以让您这样做的内容。

    将 ColumnLimit 设置为 0 仍将保留文本换行。

    clang-format-mp-3.4 test.c -style="{ ColumnLimit: 0 }"

    #include <vector>
    #include <memory>
    #include <string>
    
    int main() {
      std::vector<std::string> vec = {
        "this is a test",
        "with some strings",
        "that I want on separate lines"
      };
    }
    

    【讨论】:

    • 他还想将ColumnLimit设置为120?
    • 对。这保留了我的包装,但对修复太长的行没有任何作用(这是 IMO 工具的主要优点)。
    • 这是一个折衷方案,但对我来说很简单。我很高兴让程序员手动换行 100,如果 clang-format 不与我的数组定义中的新行混淆,在我更复杂的 std::cout 表达式中,我的 enum,我的参数列表,...
    猜你喜欢
    • 1970-01-01
    • 2022-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多