CLang-Format 代码格式化工具
2022-10-12 10:50:55
## 简述
Clang-Format是基于 clang 的一个命令行工具,这个工具能够自动化格式C/C++/Obj-C代码,支持多种代码风格(Google, Chromium, LLVM, Mozilla, WebKit),同时也支持自定义风格(通过编写.clang-format文件)。
## 安装方式
```
# Ubuntu
$ sudo apt install clang-format
# CentOS
$ yum install clang
# macOS
$ brew install clang-format
# Windows 需要访问 LLVM 官网下载 Windows 安装包(Windows installer)。http://llvm.org/builds/
```
## 参数解析
官方文档的参数解析为:http://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle样式信息:
* LLVM:一种遵循LLVM coding standards的样式;
* Google:一种遵循Google’s C++ style guide的样式;
* Chromium:一种遵循Chromium’s style guide的样式;
* Mozilla:一种遵循Mozilla’s style guide的样式;
* WebKit:一种遵循WebKit’s style guide的样式;
```
clang-format --style=LLVM -dump-config > .clang-format
```
```
---
# 语言
Language: Cpp
# BasedOnStyle: LLVM
#类的访问修饰关键字(private,public,protected···)缩进
# private:
# int a;
# 1表示不缩进
# 大于1的值表示访问修饰关键字的左侧从int a的左侧列开始往右侧移动的距离
AccessModifierOffset: -2
# 在未封闭(括号的开始和结束不在同一行)的括号中的代码是否对齐
# if(a &;&;
#b)
#
AlignAfterOpenBracket: Align
# 多行赋值语句按 = 号对齐
AlignConsecutiveAssignments: false
# 多行声明语句按 = 号对齐
AlignConsecutiveDeclarations: false
# (EscapedNewlineAlignmentStyle)用于在转义换行符中对齐反斜杠的选项,可能的值如下所示:
AlignEscapedNewlines: Right
+ ENAS_DontAlign:在配置DontAlign中不要对齐转义的换行符;
+ ENAS_Left:在配置Left中尽可能向左对齐转义的换行符;
+ ENAS_Right:在配置Right中对齐最右列中的转义换行符
# (bool)是否水平对齐二进制和三元表达式的操作数
AlignOperands: true
# 是否把注释右对齐,下面为右对齐的效果
#void someFunction() {
#doWork(); // Does something
#doMoreWork(); // Does something else
#}
AlignTrailingComments: true
# (bool)是否允许将函数声明的所有参数放到下一行(BinPackParameters为false不影响该参数)
AllowAllParametersOfDeclarationOnNextLine: true
# 是否允许短代码块在一行写完
# 如 if (a) { return; }
AllowShortBlocksOnASingleLine: false
# 是否允许短switch的case 语句在一行写完
AllowShortCaseLabelsOnASingleLine: false
# 是否允许短的函数在一行写完
AllowShortFunctionsOnASingleLine: All
# 是否允许短的语句在一行写完
AllowShortIfStatementsOnASingleLine: false
# 是否允许短的循环在一行写完,如果为真(true), 语句“while (true) continue;” 能被放到单行
AllowShortLoopsOnASingleLine: false
# 用于函数定义返回类型换行样式,这个选项是过时的并且被保留向后兼容(可选值如下所示)
AlwaysBreakAfterDefinitionReturnType: None
+ DRTBS_None (在配置中: None) 再返回类型后自动换行,PenaltyReturnTypeOnItsOwnLine 会被考虑到;
+ DRTBS_All (在配置中: All) 总是在返回类型后换行;
+ DRTBS_TopLevel (在配置中: TopLevel) 总是在返回类型的顶级函数后换行;
# 用于函数声明返回类型换行样式(可选值如下所示)
AlwaysBreakAfterReturnType: None
+ RTBS_None (在配置中: None) 在返回类型后自动换行。“PenaltyReturnTypeOnItsOwnLine”会被考虑.
+ RTBS_All (在配置中: All) 再返回类型后总是换行;
+ RTBS_TopLevel (在配置中: TopLevel) 在方法的顶层的返回类型后总是换行;
+ RTBS_AllDefinitions (在配置中: AllDefinitions) 在方法定义中的返回类型后总是换行;
+ RTBS_TopLevelDefinitions (在配置中: TopLevelDefinitions) 在顶层定义的返回类型后总是换行
# 使在文件中有多行字符串的情况看起来更一致。因此,如果字符串被“ContinuationIndentWidth”空格导致换行,它将会在行首生效。如果为真(true), 在多行字面量字符串前总是换行
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
# 如果为假(false), 函数调用的参数要么是在同一行上,要么将在同一行上有一行
BinPackArguments: true
# 如果为假(false), 函数声明或函数定义的参数将都在同一行上,或各有一行
BinPackParameters: true
# 控制单独的大括号换行事件,如果“BreakBeforeBraces”设置为“BS_Custom”, 使用这个指定如何处理每个单独的括号的情况。否则,这是被忽略的嵌套结构的标志
BraceWrapping:
# 使类定义换行
AfterClass: false
# 使控制语句(if/for/while/switch/..)换行
AfterControlStatement: false
# 使枚举定义换行
AfterEnum: false
# 使方法定义换行
AfterFunction: false
# 使命名空间定义换行
AfterNamespace: false
# 使OC定义(@autoreleasepool, interfaces, ..)换行
AfterObjCDeclaration: false
# 使结构体定义换行
AfterStruct: false
# 使共同体定义换行
AfterUnion: false
AfterExternBlock: false
# 在catch之前换行
BeforeCatch: false
# 在else之前换行
BeforeElse: false
# 缩进换行的大括号
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
# 在二元运算符前断行
BreakBeforeBinaryOperators: None
# 括号的断行模式
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
# 在三元运算符前断行
BreakBeforeTernaryOperators: true
# 在构造函数初始化时按逗号断行,并以冒号对齐
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
# 当格式化时,总是对字面量字符串换行
BreakStringLiterals: true
# 最大宽度,如果代码超过这个宽度会按语义折行
ColumnLimit: 80
# 一个固定的表达式,它描述了具有特殊意义的注释,不应该被分裂成行或以其他方式改变
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
# 如果构造函数初始化器不适合在一行,把每个初始化放到单独的行
ConstructorInitializerAllOnOneLineOrOnePerLine: false
# 使用构造函数初始化列表缩进的字符数
ConstructorInitializerIndentWidth: 4
# 在续行(/下一行)时的缩进长度
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
# 禁用当前format文件
DisableFormat: false
# 如果为真(true), clang-format检测函数调用和定义格式化为每行一个参数。每个调用都可以被包装,每行一个或不确定的。如果是不确定的,例如完全在一行,但需要做出一个决定,clang-format分析文件中是否有其他被包装的事例和相应的行动。
# 注意:这是一个实验标志,可能会消失或被重命名。不要在配置文件中使用。你自己要为你的使用负责
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
# 一个宏,应解释为foreach循环而不是作为函数调用矢量
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
# 正则表达式表示不同的#include类别被用于#includes命令,这些正则表达式与一个包含(包括< >或“)的文件的文件名相匹配。属于第一匹配正则表达式的值被分配,并且#include首先根据增加类别数然后在每个类别按字母的顺序排序。如果正则表达式都不匹配,int_max分配类别。源文件的主要头引用自动获取类别0。因此,它通常是保持在#include开头(http://llvm.org/docs/CodingStandards.html#include-style)。然而,如果你有总是需要排在首位的头引用,你也可以分配负面的优先事项。为了在.clang-format文件中配置这个, 请使用
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
# 指定一个常用的可以在文件主要包括映射的正则表达式的表达式,在猜测是否#include是“main”include(指定类别0,见上文),使用这个正则表达式允许后缀的头引用源。部分匹配完成,所以说:-“”意思是任意后缀,-“$”的意思是没有后缀,例如,如果配置”(_test)?$”,然后.h将被视为包括在a.cc和a_test.ccde中的“main”。
IncludeIsMainRegex: '(Test)?$'
# case语句的位置总是在switch语句后缩进一级
IndentCaseLabels: false
IndentPPDirectives: None
# 用于缩进的列数
IndentWidth: 2
# 缩进如果函数定义或声明后包的类型
IndentWrappedFunctionNames: false
# JavaScriptQuotes中可能的值如下所示
JavaScriptQuotes: Leave
+ JSQS_Leave (在配置中: Leave) 留下字符串原本的括号;
+ JSQS_Single (在配置中: Single) 总是使用单括号;
+ JSQS_Double (在配置中: Double) 总是使用双括号
JavaScriptWrapImports: true
# 在block从空行开始
KeepEmptyLinesAtTheStartOfBlocks: true
# block开始的正则
MacroBlockBegin: ''
# block开始的正则
MacroBlockEnd: ''
# 允许最大连续空行数
MaxEmptyLinesToKeep: 1
# 命名空间缩进
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
# block内的缩进
ObjCBlockIndentWidth: 2
# 是否需要在"@property"后加上空格
ObjCSpaceAfterProperty: false
# 是否需要在协议名后加上空格
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
# 在调用小括号“(”后给一个方法调用换行的处罚
PenaltyBreakBeforeFirstCallParameter: 19
# 包含在一个注释中的每一个换行的处罚
PenaltyBreakComment: 300
# 在第一个“<<”前的换行的处罚
PenaltyBreakFirstLessLess: 120
# 包含一个字面量的字符串中的每一个换行的处罚
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
# 最多能超出ColumnLimit多少个字符
PenaltyExcessCharacter: 1000000
# 把一个方法返回类型放到函数的同一行
PenaltyReturnTypeOnItsOwnLine: 60
# 指针在类型那边还是在变量名那边还是在中间
PointerAlignment: Right
# 如果为真(true), clang-format 将会尝试将注释重新流布局
ReflowComments: true
# 如果为真(true), clang-format 将会分类#includes
SortIncludes: true
SortUsingDeclarations: true
# 如果为真(true), 可能在一个C样式描述后插入一个空格
SpaceAfterCStyleCast: false
# 如果为真(true), 在“template”关键字后插入一个空格
SpaceAfterTemplateKeyword: true
# 如果为假(false),移除分配操作符(=)前空格
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
# 是否在括号前加上空格
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
# 是否在空括号中加空格
SpaceInEmptyParentheses: false
# 单行注释前的空格数
SpacesBeforeTrailingComments: 1
# 是否在<>中间插入空格
SpacesInAngles: false
# 是否在容器字面量(@[@"1",@"2"])中插入空格
SpacesInContainerLiterals: true
# 如果为真(true), 将会在C样式描述中插入空格
SpacesInCStyleCastParentheses: false
# 是否在非空的括号中插入空格
SpacesInParentheses: false
# 如果为真(true),将会在“[”之后和“]”之前插入空格
SpacesInSquareBrackets: false
# 用这个标准格式化:例如:在LS_Cpp03中使用 A<A<int> > 而不是 A<A<int>>(可能的值如下所示)
+ LS_Cpp03 (在配置中: Cpp03) 使用Use C++03统一语法;
+ LS_Cpp11 (在配置中: Cpp11) 使用C++11的特征(例如 A<A<int>>而不是A<A<int> >);
+ LS_Auto (在配置中: Auto) 基于输入自动检查;
Standard: Cpp11
# tab的缩进空格数
TabWidth: 8
# 在结果文件中使用制表符字符的方式可能的值如下所示)
UseTab: Never
+ UT_Never (在配置中: Never) 从不使用制表符;
+ UT_ForIndentation (在配置中: ForIndentation) 仅缩排时使用制表符;
+ UT_Always (在配置中: Always) 使用标签时,我们需要填补的空白,至少从一个制表位到下一个;
...
```
## 使用示例
```
clang-format [-参数] <输入文件>
参数说明:
-style=LLVM|Google|Chromium|Mozilla|Webkit
设定风格;目前只支持这5种风格;默认是LLVM风格
-i
文件替换;如果指定了这个参数则直接替换源文件,否则将美化过的代码打印到标准输出
$ clang-format -i hello.cpp
$ clang-format -style='{IndentWidth:4}' -i hello.cpp
$ clang-format --style=Webkit -i hello.cpp
```