使用clang-format缩进预处理器指令

46

我正在进行一个 c++ 项目,在这个项目中我使用了很多 #pragma omp。我使用了优秀的 clang-format 工具来整理代码格式,但它总是删除所有预处理指令的缩进。有没有办法改变这种行为?或者是否有其他更推荐的格式化工具?或者我应该避免使用这些工具呢?


2
历史上,预处理器指令必须从第一列开始,而且许多人仍然习惯将至少领先的 # 指令标记放在行的第一列。 - Some programmer dude
5
我明白...但你看到我的观点了,不是吗?由于“#pragma omp”应用于块(缩进的),因此看到这些指令也缩进会更加愉快... - dawirstejeck
2
我有同样的问题。我所能找到的只是一个开放的错误报告。我希望他们能尽快实现这个功能。 - mnme
我不知道有关于这个错误报告的事情。但他们似乎已经意识到了这个问题,这是一件好事 :) 随着clang即将推出的OpenMP功能,我相信这个问题会得到解决... - dawirstejeck
有两个相关的未解决错误报告:3601936020 - Rafael Vega
5个回答

23

从6.0版本开始,可以使用选项IndentPPDirectives。如何使用该选项,请参见此评论

使用IndentPPDirectives: None会产生以下结果:

#if FOO
#if BAR
#include <foo>
#endif
#endif

虽然 IndentPPDirectives: AfterHash 会产生以下效果:

#if FOO
#  if BAR
#    include <foo>
#  endif
#endif

修改:参见 @Gabriel Staples 的答案,详细了解在 clang-format 版本 9 中引入的 BeforeHash 选项。


9
据我尝试,就我所知,这不会使 #pragma omp... 缩进到 #if 所在代码的级别。相反,它将根据语句在其他指令中嵌套的级别进行缩进。 - GPMueller
现在也有一个 IndentPPDirectives: BeforeHash 选项!请看我的答案:https://dev59.com/AGAf5IYBdhLWcg3wmzpL#66004745。 - Gabriel Staples
注意:这里是Clang-format版本6的文档:https://releases.llvm.org/6.0.0/tools/clang/docs/ClangFormatStyleOptions.html。最新的文档(目前是版本12)始终可以在此处找到:https://clang.llvm.org/docs/ClangFormatStyleOptions.html。 - Gabriel Staples

7
你可以自己修补并提交一个拉取请求。
这并不难,我曾经也做过类似的普通拉取请求。clang-format代码非常整洁。clang-format已经以你想要的方式处理了代码注释,将它们与周围的代码对齐(至少它有一个启用此功能的选项),因此制作一个补丁来以同样的方式处理某些PP指令应该很简单。
或者,你可以自己编写补丁并从源代码中编译出带有额外选项的clang,供你的项目使用。在决定发送补丁之前,我也曾这样做过。
我只花了几个小时的时间就弄清楚了如何做到这一点,他们的代码比许多其他开源项目的代码要干净得多。

我会研究一下,如果它真的不难,我会去做。但现在我忙于工作,可能需要2到3个月... - dawirstejeck
1
你在这方面有进展了吗?:-) 非常感谢这个功能! - Gabriel

7

通过手动检查各种Clang-Format样式选项页面,我已经确定截至Clang-format 9版本, 第三个(也是我认为最好的)选项出现了,称为BeforeHash

注意:在撰写本文时,Clang 12已经发布。有关当前版本的最新Clang-format选项文档,请参见此处:https://clang.llvm.org/docs/ClangFormatStyleOptions.html

因此,在您的.clang-format文件中,您可以指定3个选项,如下所示:

1. 不缩进

IndentPPDirectives: None

例子:

#if FOO
#if BAR
#include <foo>
#endif
#endif

2. 在井号 (#) 后缩进

IndentPPDirectives: AfterHash

例子:

#if FOO
#  if BAR
#    include <foo>
#  endif
#endif

3. (我认为最新和最好的选项 - 可在Clang-Format version 9中使用)在井号(#)之前缩进

IndentPPDirectives: BeforeHash

例子:

#if FOO
  #if BAR
    #include <foo>
  #endif
#endif

如何在Ubuntu上安装clang-format最新版本

...以便您可以访问上面的9或更高版本功能:

请参见此处的详细说明。目前的最新版本是14.0.0

参考资料

  1. 有关所有此文档以及我上面使用的确切示例的来源,请参见LLVM Clang-format Style Options官方文档中的IndentPPDirectives部分,网址为:https://clang.llvm.org/docs/ClangFormatStyleOptions.html

相关内容

  1. 还可以查看我的基于clang-format的项目,网址为:eRCaGuy_CodeFormatter

5
这是你要找的解决方案,虽然有些迟了。它可以格式化#pragma和代码块。在他们最终支持#pragma缩进之前,您可以使用此功能。
主要理念是替换字符串,以便格式化程序在这些#pragma上使用“正确”的规则。以下是一个例子: https://github.com/MedicineYeh/p-clang-format
# Replace "#pragma omp" by "//#pragma omp"
sed -i 's/#pragma omp/\/\/#pragma omp/g' ./main.c
# Do format
clang-format ./main.c
# Replace "// *#pragma omp" by "#pragma omp"
sed -i 's/\/\/ *#pragma omp/#pragma omp/g' ./main.c

2
好的回答,只要你的代码没有任何已经注释掉的 #pragmas,这些 #pragmas 会因此重新启用。如果你的代码确实有这些 #pragmas,那么 #pragma omp 可以被类似于 // AWRBHAWRBWAQ 的东西所替换。几乎任何注释都可以,只要它不是已经存在于源代码中的即可。 - user743382
1
如果#pragma已经被注释掉了,这将再次注释掉它,然后在clang-format之后恢复它。 //#pragma omp 变成 ////#pragma omp, 然后第二个sed将其还原为 //#pragma omp。 但是,在第二个sed中,我看不到使用\/\/ *#pragma而不是\/\/#pragma来匹配空格的任何理由。此外,/g似乎是不必要的,因为每行只会有一个#pragma。所以我会这样做:sed -i 's/\/\/#pragma omp/#pragma omp/' - Mark Gates
1
你需要运行 clang-format -i ./main.c 来直接编辑文件,对吗? - Mark Gates

1
astyle(艺术风格)可以直接将#pragma omp与代码整齐地缩进,甚至没有更改行为的选项。只有行继续没有缩进,如示例所示-我希望行继续缩进,可能是8个空格,在omp下面。其他指示符左对齐。
void foo()
{
        #pragma omp parallel
#pragma omp master
    {
#pragma omp task depend( some_expression ) \
            depend( other_expression ) \
    priority(1)
        {
            code();
        }
    }

    #pragma other
    code();
}

变成

void foo()
{
    #pragma omp parallel
    #pragma omp master
    {
        #pragma omp task depend( some_expression ) \
        depend( other_expression ) \
        priority(1)
        {
            code();
        }
    }

#pragma other
    code();
}

有一个Astyle Visual Studio扩展


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接