概述
ClangFormat是一组基于LibFormat的工具,它根据风格选项(Style Options)来格式化C系语言源代码,如C/C++/Java/JavaScript/Objective-C/C#语言的源代码,也可以格式化JSON/Protobuf这样描述数据的代码。ClangFormat可以以独立的或编辑器集成的方式工作。独立的程序名为clang-format。
工具下载与安装
对于Debian类的系统,直接使用apt install clang-format
即可安装clang-format,但这样安装的版本可能较旧,而clang-format仍在不断地更新中,新的版本可能增加了更多的格式化特性,推荐到LLVM Github Release页面下载最新的clang+llvm包。例如,对于LLVM 14.0.0版本,PC Linux可以下载clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz,64位Windows下载LLVM-14.0.0-win64.exe。
一般来讲,Linux系统里自带的clang-format包,其安装目录是在/usr下,我们下载的包可以解压到/usr/local下,即压缩包里面的bin、include、lib、libexec、share等目录是放在/usr/local下面的,在PATH环境变量的设置中,默认/usr/local/bin在/usr/bin之前,如此操作,不破坏系统自带的clang-format包,但会使用用户自己安装的clang-format。
下面的说明假设INSTALL_DIR代表了/usr/local,clang-format程序在/usr/local/bin下面。
独立工具clang-format
clang-format的基本用法是:clang-format [选项] [文件列表]
,clang-format将对文件列表中列出的文件进行格式化,若没有提供文件列表,则从标准输入读入内容进行格式化。若提供了文件列表及-i选项,则clang-format格式的结果直接写入文件,否则,结果写到标准输出。使用clang-format --help
可以查看支持的选项。
clang-format选项说明
以下选项以clang-format 14.0.0为基准。
- 格式化选项
1 | --Wclang-format-violations - 警告需要更改个别格式,仅与--dry-run或-n同时使用 |
- 通用选项
1 | --help - 显示有效的选项(--help-hidden可以查看更多) |
配置编码风格
.clang-format文件使用YAML格式来配置各种编码风格:
1 | key1: value1 |
配置文件由多个节组成,并可以用不同的Language:参数来说明,这一节的配置应用于何种语言。第一节没有语言设置,它设置用于所有语言的默认编码风格。特定语言节里的配置将覆盖默认节的同名设置。
当clang-format格式化一个文件时,会使用文件名来自动探测语言,当格式化标准输入,或者文件并没有一个扩展名时,--assume-filename=
选项可以覆盖clang-format用来探测语言的文件名。
以下是一个支持多语言的配置示例:
1 |
|
当我们要开始编写一个自己的配置时,最简单的方式就是从预定义的编码风格里生成一个包含所有配置项的.clang-format文件,然后再根据需要编辑它。
1 | clang-format --style=LLVM --dump-config > .clang-format |
最新版本支持的完整编码风格可以参考Clang-Format Style Options。
对局部代码禁止格式化
工具并不是万能,当有些时候,我们已经手工整理好一些内容,而不希望clang-format去改变它时,可以将它放在注释// clang-format off
和// clang-format on
之间,或者/* clang-format off */
和/* clang-format on */
之间。例如:
1 | int formatted_code; |
编辑器集成
vim集成
vim可配置为调用clang-format来格式化当前缓冲区,也可以仅格式化选定区域,要使用此功能,添加如下内容到.vimrc来调用<INSTALL_DIR>/share/clang/clang-format.py
脚本:
1 | if has('python') |
map行配置了NORMAL和VISUAL模式,imap行配置了INSERT模式,C-I表示Ctrl+i,如此,我们就绑定了Ctrl+i作为快捷键来执行clang-format.py。在NORMAL和INSERT模式时,按下Ctrl+i会格式化当前行,而在VISUAL模式时,按下Ctrl+i会格式化选定区域。被格式化的行或选定区域可能会扩展到一个更大的词法分析范围。
格式化操作对当前缓冲区有效,它并不创建也不保存任何文件,如果要撤消格式化,使用u命令撤消即可。
上述配置,要求vim带有python的支持。可以通过vim --verison
命令来查看,你所用的vim版本包含了哪些特性,如果输出中,python3前面有+号,表明支持Python 3,py3f命令是有效的,如果python前面有+号,则支持Python 2,pyf命令是有效的,若均不支持,则上述配置无效。
还有一个选择是保存文件时,格式化修改过的部分,只要把如下内容加到.vimrc里面就可以在保存扩展名为.h、.c、.cc、.cpp的文件时自动格式化修改过的行:
1 | function! FormatOnSave() |
CLion集成
clang-format已经作为一个可选的代码格式化器集成进CLion。若在打开的项目根目录下存在.clang-format文件,CLion会自动使用.clang-format文件中定义的代码样式,包括缩进、自动完成、代码生成、重构。此时,打开CLion->设置->编辑器->代码样式时,会提示“设置可能被 ClangFormat 重写”。若不需要使用clang-format,可在此提示旁边点击“禁用”。
Visual Studio集成
Visual Studio自2017 15.7 Preview 1版本起,已经内置了clang-format的支持,若是早期的版本,可从LLVM Snapshot Builds下载相应的扩展。默认绑定的快捷键是Ctrl+R,Ctrl+F。
Visual Studio Code集成
可从Visual Studio Marketplace下载最新的扩展。默认绑定的快捷键是Alt+Shift+F。
其它编辑器集成
ClangFormat还提供Emacs、BBEdit、Sublime等编辑器的插件,具体可以参考<INSTALL_DIR>/share/clang/目录下的文件。
应用于patch的格式化脚本
INSTALL_DIR/share/clang/clang-format-diff.py
解析合并差异(unified diff)的输出,并使用clang-format格式化所有包含的行。
所以,格式化最新一个git提交的所有行,如下操作即可:
1 | git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1 |
对于Mercurial/hg,则为如下命令:
1 | hg diff -U0 --color=never | clang-format-diff.py -i -p1 |
对于SVN,则为如下命令:
1 | svn diff --diff-cmd=diff -x -U0 | clang-format-diff.py -i |
选项-U0是用来创建无上下文行的差异,否则脚本会把上下文行也格式化了。
这些命令使用了差异输出中的文件路径,所以,仅能在仓库的根目录下工作。