使用 clang 格式缩进预处理器指令
Posted
技术标签:
【中文标题】使用 clang 格式缩进预处理器指令【英文标题】:Indenting preprocessor directives with clang-format 【发布时间】:2014-08-20 00:00:49 【问题描述】:我正在做一个 c++ 项目,我在其中使用了很多 #pragma omp
。我使用美妙的 clang 格式来保持整洁,但它总是删除所有预处理器指令的缩进。有没有办法改变这种行为?还是有其他更值得推荐的格式化工具?还是我应该完全避免使用这些工具?
【问题讨论】:
从历史上看,预处理器指令必须从第一列开始,许多人仍然习惯于在第一列中至少放置前导#
指令标记行。
我明白...但你明白我的意思,不是吗?由于“#pragma omp”应用于块(缩进),因此看到这些指令也缩进更令人愉快......
我也有同样的问题。我只能找到一个开放的bug report。我希望他们能尽快实施。
我不知道错误报告。但他们似乎意识到了这个问题:) 随着即将到来的 OpenMP 功能在铿锵声中,我相信这将获得一些动力......
有两个相关的未解决的错误报告:36019 和 36020
【参考方案1】:
从 6.0 版开始,可以使用选项 IndentPPDirectives
。用法在this review 中描述。
使用IndentPPDirectives: None
会导致:
#if FOO
#if BAR
#include <foo>
#endif
#endif
虽然IndentPPDirectives: AfterHash
给出:
#if FOO
# if BAR
# include <foo>
# endif
#endif
编辑:有关clang-format
版本 9 中引入的BeforeHash
选项的详细信息,请参阅@Gabriel Staples 的answer。
【讨论】:
据我所知(通过尝试),这不会缩进# pragma omp...
以匹配周围的代码。相反,它只会根据语句嵌套在其他指令中的级别缩进,例如您显示的#if
。
现在还有IndentPPDirectives: BeforeHash
选项!在这里查看我的答案:***.com/a/66004745/4561887。
注意:这里是 Clang 格式的版本 6 文档:releases.llvm.org/6.0.0/tools/clang/docs/…。最新的文档(当前版本 12)总是可以在这里找到:clang.llvm.org/docs/ClangFormatStyleOptions.html。【参考方案2】:
您可能只想自己修补它并提出拉取请求。
这并不难,我曾经提出过类似的普通拉取请求。 clang 格式的代码非常整洁。 Clang-format 已经以您想要的方式处理代码 cmets,将它们与周围的代码对齐(至少它具有启用此功能的选项),因此制作一个补丁来以相同的方式处理某些 PP 指令应该很简单。
或者,您可以自己编写补丁并使用额外选项从源代码自己编译clang,以便在您的项目中使用。在决定将补丁发送给他们之前,我也这样做了。
我真的只花了几个小时就弄清楚了如何做到这一点,他们的代码比许多其他开源项目的代码干净得多。
【讨论】:
我会研究它,如果它真的不那么难,我会去做。但现在我正忙于工作,所以可能在 2 或 3 个月内...... 您在这方面取得了一些进展吗? :-) 高度赞赏的功能!【参考方案3】:已经很晚了,但这是您正在寻找的解决方案。 它将编译指示与代码块一起格式化。 您可以在他们最终支持 pragma 缩进之前使用它。
https://github.com/MedicineYeh/p-clang-format
主要概念是替换字符串,以便格式化程序在这些 pragma 上使用“正确”规则。动机示例如下。
# 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
【讨论】:
很好的答案,只要您的代码没有任何已被注释掉的#pragmas 被重新启用。如果您的代码确实有它们,#pragma omp
可以替换为 // AWRBHAWRBWAQ
之类的东西。几乎任何注释都可以,只要它还没有出现在源代码中。
如果#pragma 已经被注释掉了,这将再次注释掉它,然后在clang-format 之后恢复它。 //#pragma omp
变为 ////#pragma omp
,然后第二个 sed 将其还原为 //#pragma omp
。但是,在第二个 sed 中,我看不出有任何理由使用 \/\/ *#pragma
而不是 \/\/#pragma
来匹配空格。 /g
似乎也没有必要,因为每行只有一个#pragma。所以我会做sed -i 's/\/\/#pragma omp/#pragma omp/'
您需要clang-format -i ./main.c
进行就地编辑,对吧?【参考方案4】:
通过手动检查各种 Clang 格式样式选项页面,我确定 as of Clang-format version 9,第三个(我认为最好的)选项出现了,称为 BeforeHash
。
注意:截至撰写本文时,Clang 12 已发布。有关当前发布的任何版本的最新 Clang 格式选项文档,请参阅此处: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
参考文献
对于所有这些文档,以及我上面使用的确切示例的来源,请参阅此处 LLVM Clang 格式样式选项官方文档的 IndentPPDirectives 部分:https://clang.llvm.org/docs/ClangFormatStyleOptions.html。
【讨论】:
【参考方案5】:astyle
(艺术风格)缩进 #pragma omp
与代码很好,开箱即用。甚至似乎没有改变行为的选项。只有续行不缩进,如示例中所示——我更喜欢在omp
下缩进续行,可能是 8 个空格。其他 pragma 左对齐。
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 extension。
【讨论】:
以上是关于使用 clang 格式缩进预处理器指令的主要内容,如果未能解决你的问题,请参考以下文章