regex 如何为clang格式的外部标题创建类别?

7nbnzgx9  于 2023-03-09  发布在  其他
关注(0)|答案(3)|浏览(110)

我想配置clang-format在C++中对包含的头进行排序,如下所示:

  • 主报头(与当前CPP文件相关联),
  • 通过“"包括的本地报头,
  • 通过〈〉包括的其它报头,
  • 来自特定外部库(例如boost、catch 2)的标头,
  • 系统/标准标头。

我在macOS上使用clang-format 8.0.0,我当前的配置(仅与includes相关的片段)如下:

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头文件没有扩展。它对UNIX/POSIX头文件不起作用。Main头文件被自动检测并分配优先级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以获得预期结果?

huwehgph

huwehgph1#

我使用并修改了clang-format docs中的一个例子来实现这个选项:

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

特别是,我修改了priority 3正则表达式,使其更像原始的example

'^(<|"(gtest|gmock|isl|json)/)'

另外,我添加了\Q和\E修饰语以避免Julio提到的问题。现在一切都如预期的那样工作。但是我仍然不知道为什么问题帖子中的解决方案不起作用。

mklgxw1f

mklgxw1f2#

问题是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/_,这可能不是你的意思。

zhte4eai

zhte4eai3#

如果你遵循把所有的外部头文件放在<>中,本地头文件放在""中的惯例,你可以使用下面的配置文件,它会根据头文件的类别对它们进行很好的排序:
.clang-format

SortIncludes: CaseSensitive
IncludeBlocks: Regroup
IncludeCategories:
  # Specific external headers in <> to put first
  - Regex: '<(catch2|gtest).*>'
    Priority: 1
  # External headers in <> with extension or /
  - Regex: '<[\w\/-_]+[\.\/][\w\/-_]+>'
    Priority: 2
  # Standard headers in <>
  - Regex: '<[\w\/-_]+>'
    Priority: 3
  # Local headers in ""
  - Regex: '"[\w\/-_]*"'
    Priority: 4

这将像这样对包含进行排序:

#include <catch2/catch_test_macros.hpp>

#include <Eigen/Core>
#include <fmt/format.h>

#include <algorithm>
#include <cmath>
#include <concepts>
#include <filesystem>

#include "../some_other_local_header"
#include "./some_local_header.hpp"

相关问题