如何在 clang-format 中为外部 headers 创建类别?
How to create category for external headers in clang-format?
我想配置 clang-format 以在 C++ 中对包含的 header 进行排序,如下所示:
- main header(关联当前cpp文件),
- 本地 headers 通过“”包含,
- 其他 header 通过 <> 收录,
- headers 来自特定的外部库(例如 boost、catch2),
- system/standard headers.
我在 macOS 上使用 clang-format 8.0.0。
我当前的配置(仅与包含相关的代码段)如下:
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
# Headers in <> without extension.
- Regex: '<([A-Za-z0-9\/-_])+>'
Priority: 4
# Headers in <> from specific external libraries.
- Regex: '<((\bboost\b)|(\bcatch2\b))\/([A-Za-z0-9.\/-_])+>'
Priority: 3
# Headers in <> with extension.
- Regex: '<([A-Za-z0-9.\/-_])+>'
Priority: 2
# Headers in "" with extension.
- Regex: '"([A-Za-z0-9.\/-_])+"'
Priority: 1
在此配置中,我假设 system/standard header 没有扩展名。它不适用于 UNIX/POSIX header 秒。 Main header 被自动检测并分配优先级 0。到目前为止,除了外部库的类别外,一切似乎都按预期工作。看起来 clang-format 正在将其分配给优先级 2。
预期结果:
#include "test.h"
#include <allocator/region.hpp>
#include <page.hpp>
#include <page_allocator.hpp>
#include <test_utils.hpp>
#include <utils.hpp>
#include <zone_allocator.hpp>
#include <catch2/catch.hpp> // <--------
#include <array>
#include <cmath>
#include <cstring>
#include <map>
实际结果:
#include "test.h"
#include <allocator/region.hpp>
#include <catch2/catch.hpp> // <--------
#include <page.hpp>
#include <page_allocator.hpp>
#include <test_utils.hpp>
#include <utils.hpp>
#include <zone_allocator.hpp>
#include <array>
#include <cmath>
#include <cstring>
#include <map>
如何配置优先级 3 以获得预期的结果?
问题是 Clan-format 使用 POSIX ERE regexes。而且那些不支持单词边界。
所以<catch2/catch.hpp>
永远不会匹配第二条规则。然后,为匹配的第三条规则评估相同的字符串。
如果它符合第二条规则,它就会到此为止,但由于没有,它会继续下一条规则。
只需删除正则表达式中的所有 \b
。删除它们是安全的,因为你已经有了单词边界:左边有 <
,右边有 /
,所以即使你可以使用单词边界,也没有用。
- Regex: '<(boost|catch2)\/([A-Za-z0-9.\/-_])+>'
Priority: 3
注意: 请记住,[]
中的 -
应该用反斜杠转义,除非它放在最后一个位置。那是因为它用于范围。因此,当您写 [A-Za-z0-9.\/-_]
时,您的意思是 A-Za-z0-9.
或 range 从 /
到 _
,这可能不是您的意思。
我通过使用和修改 clang-format 文档中的示例来实现此选项:
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
# Headers in <> without extension.
- Regex: '<([A-Za-z0-9\Q/-_\E])+>'
Priority: 4
# Headers in <> from specific external libraries.
- Regex: '<(catch2|boost)\/'
Priority: 3
# Headers in <> with extension.
- Regex: '<([A-Za-z0-9.\Q/-_\E])+>'
Priority: 2
# Headers in "" with extension.
- Regex: '"([A-Za-z0-9.\Q/-_\E])+"'
Priority: 1
特别是,我将优先级 3 正则表达式更改为更像原来的 example:
'^(<|"(gtest|gmock|isl|json)/)'
此外,我添加了 \Q 和 \E 修饰符来避免 Julio 提到的问题。
现在一切都按预期工作。但是我仍然不知道为什么问题 post 的解决方案不起作用。
我想配置 clang-format 以在 C++ 中对包含的 header 进行排序,如下所示:
- main header(关联当前cpp文件),
- 本地 headers 通过“”包含,
- 其他 header 通过 <> 收录,
- headers 来自特定的外部库(例如 boost、catch2),
- system/standard headers.
我在 macOS 上使用 clang-format 8.0.0。 我当前的配置(仅与包含相关的代码段)如下:
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
# Headers in <> without extension.
- Regex: '<([A-Za-z0-9\/-_])+>'
Priority: 4
# Headers in <> from specific external libraries.
- Regex: '<((\bboost\b)|(\bcatch2\b))\/([A-Za-z0-9.\/-_])+>'
Priority: 3
# Headers in <> with extension.
- Regex: '<([A-Za-z0-9.\/-_])+>'
Priority: 2
# Headers in "" with extension.
- Regex: '"([A-Za-z0-9.\/-_])+"'
Priority: 1
在此配置中,我假设 system/standard header 没有扩展名。它不适用于 UNIX/POSIX header 秒。 Main header 被自动检测并分配优先级 0。到目前为止,除了外部库的类别外,一切似乎都按预期工作。看起来 clang-format 正在将其分配给优先级 2。
预期结果:
#include "test.h"
#include <allocator/region.hpp>
#include <page.hpp>
#include <page_allocator.hpp>
#include <test_utils.hpp>
#include <utils.hpp>
#include <zone_allocator.hpp>
#include <catch2/catch.hpp> // <--------
#include <array>
#include <cmath>
#include <cstring>
#include <map>
实际结果:
#include "test.h"
#include <allocator/region.hpp>
#include <catch2/catch.hpp> // <--------
#include <page.hpp>
#include <page_allocator.hpp>
#include <test_utils.hpp>
#include <utils.hpp>
#include <zone_allocator.hpp>
#include <array>
#include <cmath>
#include <cstring>
#include <map>
如何配置优先级 3 以获得预期的结果?
问题是 Clan-format 使用 POSIX ERE regexes。而且那些不支持单词边界。
所以<catch2/catch.hpp>
永远不会匹配第二条规则。然后,为匹配的第三条规则评估相同的字符串。
如果它符合第二条规则,它就会到此为止,但由于没有,它会继续下一条规则。
只需删除正则表达式中的所有 \b
。删除它们是安全的,因为你已经有了单词边界:左边有 <
,右边有 /
,所以即使你可以使用单词边界,也没有用。
- Regex: '<(boost|catch2)\/([A-Za-z0-9.\/-_])+>'
Priority: 3
注意: 请记住,[]
中的 -
应该用反斜杠转义,除非它放在最后一个位置。那是因为它用于范围。因此,当您写 [A-Za-z0-9.\/-_]
时,您的意思是 A-Za-z0-9.
或 range 从 /
到 _
,这可能不是您的意思。
我通过使用和修改 clang-format 文档中的示例来实现此选项:
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
# Headers in <> without extension.
- Regex: '<([A-Za-z0-9\Q/-_\E])+>'
Priority: 4
# Headers in <> from specific external libraries.
- Regex: '<(catch2|boost)\/'
Priority: 3
# Headers in <> with extension.
- Regex: '<([A-Za-z0-9.\Q/-_\E])+>'
Priority: 2
# Headers in "" with extension.
- Regex: '"([A-Za-z0-9.\Q/-_\E])+"'
Priority: 1
特别是,我将优先级 3 正则表达式更改为更像原来的 example:
'^(<|"(gtest|gmock|isl|json)/)'
此外,我添加了 \Q 和 \E 修饰符来避免 Julio 提到的问题。 现在一切都按预期工作。但是我仍然不知道为什么问题 post 的解决方案不起作用。