c++clang-format

Make clang-format order includes in a case-insensitive way


I'm trying to configure .clang-format. My intention is for it to keep my include groups as they are in the code, but sort them alphabetically. I managed to get close to what I wanted with IncludeBlocks: Preserve, but it sorts includes in each block in a case sensitive way:

This is what I get after applying my format

#include "A1.h"
#include "B2.h"
#include "a2.h"
#include "b1.h"

And this is what I want to achieve

#include "A1.h"
#include "a2.h"
#include "b1.h"
#include "B2.h"

I'm using clang-format version 10.0. My .clang-format file, in case it's relevant:

---
# Brompton's Clang Format file v0.0.1
#
# Changelog:
# v0.0.1 (25/9/2020):
# - First version of this file


# Base it on Google's Standard, with 4 spaces as indentation
BasedOnStyle: Google
IndentWidth: '4'
Standard: Cpp11
UseTab: Never

# Settings for C/C++
Language: Cpp
# 120 chars per line, reflow comments so they stay within limits
ColumnLimit: '120'
ReflowComments: 'true'

# Short includes alphabetically. Will respect "include groups"
SortIncludes: 'true'
IncludeBlocks: Preserve

# These control when to align text under certain conditions
# Align arguments after an open bracket ( '(', '[', '{'), on statements that are too long for a single line
AlignAfterOpenBracket: Align
# Align adjacent macros and variables, for enhanced readability.
AlignConsecutiveMacros: 'true'
AlignConsecutiveAssignments: 'true'
# Align the '\' on scaped newlines, because it looks neater
AlignEscapedNewlines: Left

# These keep statements that could go on a single line to be collapsed. They take more space, but are more readable
# ... Code Blocks { ... }
AllowShortBlocksOnASingleLine: 'false'
# ... Switch cases
AllowShortCaseLabelsOnASingleLine: 'false'
# ... short functions, like getters and setters
AllowShortFunctionsOnASingleLine: Empty
# ... single line ifs
AllowShortIfStatementsOnASingleLine: Never
# ... single line loops
AllowShortLoopsOnASingleLine: 'false'

# Provides a more compact view when a function parameters or arguments take more than one line
BinPackArguments: 'true'
BinPackParameters: 'true'

# Indent cases on a switch, instead of leaving them at the same level than the switch statement.
IndentCaseLabels: 'true'
# Indent preprocessor the same way than code
IndentPPDirectives: BeforeHash
IndentWrappedFunctionNames: 'true'
NamespaceIndentation: All

# Put the pointer operator next to the type, instead of next to the variable name:
PointerAlignment: Left

# All about those extra spaces...
# ... remove spaces after an open-curly brace and before a close-curly brace
Cpp11BracedListStyle: 'true'
# ... space before a list, when used to initialise an object
SpaceBeforeCpp11BracedList: 'true'
# ... logical not (!) next to expression
SpaceAfterLogicalNot: 'false'
# ... space between the '=' on assignments
SpaceBeforeAssignmentOperators: 'true'
# ... space after and before the parentheses in a C-style cast.
SpacesInCStyleCastParentheses: 'false'
# ... spaces inside () and []
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
# ... spaces before a ( or a [, but only on control statements.
SpaceBeforeParens: 'ControlStatements'

...

Thanks!


Solution

  • This has been added as of LLVM 12 and released with Clang 13, somewhat confusingly. Citing the release notes of LLVM 12/Clang 13 [emphasis mine]:

    clang-format

    Option SortIncludes has been updated from a bool to an enum with backwards compatibility. In addition to the previous true/false states (now CaseSensitive/Never), a third state has been added (CaseInsensitive) which causes an alphabetical sort with case used as a tie-breaker.

    // Never (previously false)
    #include "B/A.h"
    #include "A/B.h"
    #include "a/b.h"
    #include "A/b.h"
    #include "B/a.h"
    
    // CaseSensitive (previously true)
    #include "A/B.h"
    #include "A/b.h"
    #include "B/A.h"
    #include "B/a.h"
    #include "a/b.h"
    
    // CaseInsensitive
    #include "A/B.h"
    #include "A/b.h"
    #include "a/b.h"
    #include "B/A.h"
    #include "B/a.h"
    

    The most recent Clang Format docs have been updated with an example use of CaseSensitive:

    IncludeCategories (std::vector<IncludeCategory>)

    [...]

    Each regular expression can be marked as case sensitive with the field CaseSensitive, per default it is not.

    To configure this in the .clang-format file, use:

    IncludeCategories:
      - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
        Priority:        2
        SortPriority:    2
        CaseSensitive:   true
      - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
        Priority:        3
      - Regex:           '<[[:alnum:].]+>'
        Priority:        4
      - Regex:           '.*'
        Priority:        1
        SortPriority:    0