VS Code 食用方法
VS Code 使用 clang-format 自定义 C++ 代码默认格式化样式
遇到的问题
Visual Studio 的 C++ 代码格式化可选使用 clang-format,但它只提供默认样式,如果想使用自定义样式则需要在每个项目目录下放一个.clang-format
或_clang-format
文件,没有对全部项目通用的可自定义样式。
解决方法
这里发现 VS 的格式设置中有一个使用自定义 clang-format.exe 文件选项,
所以我尝试制做一个 clang-format 的包装程序让 VS 使用(来骗)。
通过同级目录下rules.txt
来设置自定义的默认样式,具体设置参照 Clang-Format官方文档,也可以使用 Clang-Format交互式构建器。
(当启用了这个包装程序时,VS 自带的默认格式设置样式选项会失效)
包装程序的代码贴在了文章结尾,在 VS 中用 Std C++17 编译即可。
clang-format.exe
可以在%VS安装目录%\VC\Tools\Llvm\x64\bin
目录中找到,也可以在 LLVM发布页 下载。
贴上我习惯使用的代码格式化样式(Java 代码的习惯样式)。
以下是rules.txt
内容:
# 基于GNU格式
BasedOnStyle: GNU
# 使用支持的最新标准
Standard: Latest
# 行不限制长度
ColumnLimit: 0
# 缩进4个空格
IndentWidth: 4
# 左花括号在名称之后
BreakBeforeBraces: Attach
# 函数参数的小括号与函数名间不空格, 控制语句的小括号与语句间空格
SpaceBeforeParens: ControlStatements
# 换行时将二元运算符置后
BreakBeforeBinaryOperators: None
# 允许空的花括号在一行上
AllowShortBlocksOnASingleLine: Empty
# 函数返回值与函数在同一行
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
# 指针符号贴在类型边
PointerAlignment: Left
# 访问修饰符贴在左边
AccessModifierOffset: -4
# case和default之前缩进
IndentCaseLabels: true
# C式类型转换中间留空格
SpaceAfterCStyleCast: true
# 类继承冒号之前不留空格
SpaceBeforeInheritanceColon: false
# 构造函数初始化冒号之前不留空格
SpaceBeforeCtorInitializerColon: false
# 命名空间全部缩进
NamespaceIndentation: All
# 不排序头文件引用
SortIncludes: Never
# C++11式初始化对象花括号前留空格
SpaceBeforeCpp11BracedList: true
使用之前(二选一)
- 确保
clang-format.exe
在PATH
中并且可访问。
- 确保
clang-format.exe
位于clang-format-wrapper.exe
的同级目录下。
Visual Studio 使用方法
- 启用 ClangFormat 支持并使用自定义 clang-format.exe 文件,选择上一步的
clang-format-wrapper.exe
并确定。
- 现在可以回到编辑器测试一下了,默认格式化快捷键是
Ctrl + K + D
。
包装程序的代码
#include <filesystem>
#include <optional>
#include <string>
#include <process.h>
namespace fs = std::filesystem;
const wchar_t* clang_format_path = L"clang-format.exe";
const wchar_t* rule_text_path = L"rules.txt";
int wmain(int argc, wchar_t** argv) {
std::optional<std::wstring> args;
fs::path path = fs::absolute(argv[0]);
path.replace_filename(clang_format_path);
if (fs::exists(path)) {
args = path.wstring();
} else {
args = std::wstring(clang_format_path, 16);
}
args->push_back(L' ');
for (int i = 1; i < argc; i++) {
if (!wcsstr(argv[i], L"-style=")) {
args->append(argv[i]);
args->push_back(L' ');
}
}
args->append(L"-fallback-style=none -style=file:");
args->append(path.replace_filename(rule_text_path));
return _wsystem(args->data());
}