如何让Clang-Format保留宏的反斜杠换行续行符?
如何让Clang-Format保留预处理器宏的反斜杠续行?
我有一段用反斜杠作为续行符的多行预处理器宏代码,执行Clang-Format后,原本的多行结构被强行合并成单行,完全忽略了手动添加的续行反斜杠,生成的单行甚至远超我设置的100列限制。
格式化前的代码
#include "uart0.h" #if \ defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega8A__) || \ defined(__AVR_ATmega16__) || \ defined(__AVR_ATmega16A__) || \ defined(__AVR_ATmega32__) || \ defined(__AVR_ATmega32A__) #define UART_RX_INTERRUPT USART_RXC_vect #define UART_TX_INTERRUPT USART_UDRE_vect ...
格式化后的代码
#include "uart0.h" #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega16A__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) #define UART_RX_INTERRUPT USART_RXC_vect #define UART_TX_INTERRUPT USART_UDRE_vect #define UART_STATUS UCSRA #define UART_CONTROL UCSRB
我已经设置了AlignEscapedNewlines: Left和ColumnLimit: 100,但问题依然存在,以下是我的完整Clang-Format配置:
Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: BlockIndent AlignArrayOfStructures: Left AlignConsecutiveAssignments: Enabled: True AcrossEmptyLines: False AcrossComments: False AlignCompound: True PadOperators: True AlignConsecutiveBitFields: Enabled: True AcrossEmptyLines: False AcrossComments: False AlignCompound: False PadOperators: False AlignConsecutiveDeclarations: Enabled: True AcrossEmptyLines: False AcrossComments: False AlignCompound: False PadOperators: False AlignConsecutiveMacros: Enabled: True AcrossEmptyLines: False AcrossComments: False AlignCompound: False PadOperators: False #AlignConsecutiveShortCaseStatements: # Version 17 # Enabled: True # AcrossEmptyLines: False # AcrossComments: False # AlignCaseColons: False AlignEscapedNewlines: Left AlignOperands: Align AlignTrailingComments: Kind: Always OverEmptyLines: 0 AllowAllArgumentsOnNextLine: True AllowAllParametersOfDeclarationOnNextLine: True AllowShortBlocksOnASingleLine: Always AllowShortCaseLabelsOnASingleLine: False AllowShortEnumsOnASingleLine: False AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: AllIfsAndElse AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: True AlwaysBreakAfterReturnType: All AlwaysBreakBeforeMultilineStrings: True AlwaysBreakTemplateDeclarations: Yes BinPackArguments: False BinPackParameters: False BitFieldColonSpacing: After BraceWrapping: AfterCaseLabel: True AfterClass: True AfterControlStatement: Always AfterEnum: True AfterExternBlock: True AfterFunction: True AfterNamespace: True AfterStruct: True AfterUnion: True BeforeCatch: True BeforeElse: True BeforeLambdaBody: True BeforeWhile: True IndentBraces: False SplitEmptyFunction: True SplitEmptyRecord: True SplitEmptyNamespace: True #BracedInitializerIndentWidth: 4 # Version 17 BreakAfterAttributes: Never BreakBeforeBinaryOperators: All BreakBeforeBraces: Allman BreakBeforeConceptDeclarations: Always BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: True BreakConstructorInitializers: AfterColon BreakInheritanceList: AfterColon BreakStringLiterals: True ColumnLimit: 100 CompactNamespaces: False ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 0 Cpp11BracedListStyle: False DerivePointerAlignment: False DisableFormat: False EmptyLineAfterAccessModifier: Always EmptyLineBeforeAccessModifier: Always FixNamespaceComments: False IncludeBlocks: Preserve IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 SortPriority: 0 CaseSensitive: False - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 SortPriority: 0 CaseSensitive: False - Regex: '.*' Priority: 1 SortPriority: 0 CaseSensitive: False IncludeIsMainRegex: '(Test)?$' IncludeIsMainSourceRegex: '' IndentAccessModifiers: True IndentCaseBlocks: False IndentCaseLabels: True IndentExternBlock: AfterExternBlock IndentGotoLabels: True IndentPPDirectives: BeforeHash IndentRequiresClause: False IndentWidth: 4 IndentWrappedFunctionNames: False InsertBraces: True # Possible incorrect code formatting InsertNewlineAtEOF: True InsertTrailingCommas: None IntegerLiteralSeparator: Binary: 0 BinaryMinDigits: 0 Decimal: 0 DecimalMinDigits: 0 Hex: 0 HexMinDigits: 0 #KeepEmptyLinesAtEOF: False # Version 17 KeepEmptyLinesAtTheStartOfBlocks: False LambdaBodyIndentation: Signature LineEnding: LF MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: All PPIndentWidth: -1 PackConstructorInitializers: Never PenaltyBreakAssignment: 0 PenaltyBreakBeforeFirstCallParameter: 0 PenaltyBreakComment: 0 PenaltyBreakFirstLessLess: 0 PenaltyBreakOpenParenthesis: 0 PenaltyBreakString: 0 PenaltyBreakTemplateDeclaration: 0 PenaltyExcessCharacter: 0 PenaltyIndentedWhitespace: 0 PenaltyReturnTypeOnItsOwnLine: 0 PointerAlignment: Left QualifierAlignment: Leave ReferenceAlignment: Right #RemoveParentheses: Leave # Version 17 RemoveSemicolon: True RequiresClausePosition: OwnLine RequiresExpressionIndentation: OuterScope SeparateDefinitionBlocks: Always ShortNamespaceLines: 0 SortIncludes: Never SortUsingDeclarations: LexicographicNumeric SpaceAfterCStyleCast: True SpaceAfterLogicalNot: False SpaceAfterTemplateKeyword: True SpaceAroundPointerQualifiers: Default SpaceBeforeAssignmentOperators: True SpaceBeforeCaseColon: False SpaceBeforeCpp11BracedList: True SpaceBeforeCtorInitializerColon: True SpaceBeforeInheritanceColon: True SpaceBeforeParens: Custom SpaceBeforeParensOptions: AfterControlStatements: True AfterForeachMacros: True AfterFunctionDefinitionName: False AfterFunctionDeclarationName: False AfterIfMacros: True AfterOverloadedOperator: False AfterRequiresInClause: False AfterRequiresInExpression: False BeforeNonEmptyParentheses: False SpaceBeforeRangeBasedForLoopColon: True SpaceBeforeSquareBrackets: False SpaceInEmptyBlock: False SpaceInEmptyParentheses: False # Deprecated SpacesBeforeTrailingComments: 1 SpacesInAngles: Never SpacesInCStyleCastParentheses: False # Deprecated SpacesInConditionalStatement: False # Deprecated SpacesInContainerLiterals: False SpacesInLineCommentPrefix: Minimum: 1 Maximum: -1 #SpacesInParens: Custom # Version 17 #SpacesInParensOptions: # Version 17 # InConditionalStatements: False # InCStyleCasts: False # InEmptyParentheses: False # Other: False SpacesInSquareBrackets: False Standard: Latest StatementAttributeLikeMacros: - Q_EMIT StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION TabWidth: 4 UseTab: Never WhitespaceSensitiveMacros: - BOOST_PP_STRINGIZE - PP_STRINGIZE - STRINGIZE
解决方案
要让Clang-Format尊重预处理器宏的反斜杠续行,需要调整以下几项配置:
修改
BreakBeforeBinaryOperators为NonAssignment
当前配置的All会让Clang-Format重新排列所有二元运算符,包括预处理器中的||,从而破坏手动续行。改为NonAssignment后,逻辑运算符的换行会被保留。启用
MacroBlockBegin和MacroBlockEnd
在配置中添加:MacroBlockBegin: '#if' MacroBlockEnd: '#endif'这会让Clang-Format将
#if到#endif的代码视为独立块,保留内部的换行结构。调整
IndentPPDirectives为None
当前的BeforeHash会修改预处理器指令的缩进,改为None可以确保续行的对齐符合手动编写的格式。保留
AlignEscapedNewlines: Left
该配置已正确设置,它会让续行的反斜杠保持左对齐,和原始格式一致。
修改后的关键配置片段:
BreakBeforeBinaryOperators: NonAssignment MacroBlockBegin: '#if' MacroBlockEnd: '#endif' IndentPPDirectives: None
如果还有特定宏需要完全保留格式,可以将其添加到WhitespaceSensitiveMacros列表中,但对于#if这类预处理器块,上述配置已经足够解决问题。
内容的提问来源于stack exchange,提问作者zambetti
相关产品推荐
相关产品推荐

