Index: docs/ClangFormatStyleOptions.rst =================================================================== --- docs/ClangFormatStyleOptions.rst +++ docs/ClangFormatStyleOptions.rst @@ -1363,6 +1363,35 @@ #endif + **IndentReference** (``IndentReferenceStyle``) + Indent relative to the previous line or in absolute. + + Only useful for when formatting only certain lines. + + Possible values: + + * ``IRS_Relative`` (in configuration: ``Relative``) + Indent relative to previous line, e.g.: + + .. code-block:: c + + int a = 0; + int f(void) { + int i = 0; + return i; + } + + * ``IRS_Absolute`` (in configuration: ``Absolute``) + Indent as if the whole file was formatted, e.g.: + + .. code-block:: c + + int a = 0; + int f(void) { + int i = 0; + return i; + } + **IndentWidth** (``unsigned``) The number of columns to use for indentation. Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1094,6 +1094,30 @@ /// The preprocessor directive indenting style to use. PPDirectiveIndentStyle IndentPPDirectives; + /// Different styles for indenting, used for partial formatting. + enum IndentReferenceStyle { + /// Indent relative to previous line, e.g.: + /// \code + /// int a = 0; + /// int f(void) { // mis-indented by one space + /// int i = 0; <- those lines indented relative to + /// return i; <- the indentation of f(), including + /// } <- the one space mis-indentation + /// \endcode + IRS_Relative, + /// Indent as if the whole file was formatted, e.g.: + /// \code + /// int a = 0; + /// int f(void) { // mis-indented by one space + /// int i = 0; <- those lines indented absolutely; + /// return i; <- i.e. ignoring f()'s one space + /// } <- mis-indentation + /// \endcode + IRS_Absolute, + }; + + IndentReferenceStyle IndentReference; + /// The number of columns to use for indentation. /// \code /// IndentWidth: 3 @@ -1722,6 +1746,7 @@ IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories && IndentCaseLabels == R.IndentCaseLabels && IndentPPDirectives == R.IndentPPDirectives && + IndentReference == R.IndentReference && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && JavaScriptQuotes == R.JavaScriptQuotes && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -241,6 +241,13 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::IndentReferenceStyle &Value) { + IO.enumCase(Value, "Relative", FormatStyle::IRS_Relative); + IO.enumCase(Value, "Absolute", FormatStyle::IRS_Absolute); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); @@ -411,6 +418,7 @@ IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); + IO.mapOptional("IndentReference", Style.IndentReference); IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); @@ -670,6 +678,7 @@ LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; LLVMStyle.IndentCaseLabels = false; LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; + LLVMStyle.IndentReference = FormatStyle::IRS_Relative; LLVMStyle.IndentWrappedFunctionNames = false; LLVMStyle.IndentWidth = 2; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -1089,10 +1089,13 @@ format(Tok->Children, DryRun); // Adapt following lines on the current indent level to the same level - // unless the current \c AnnotatedLine is not at the beginning of a line. + // if indentation should be relative and unless the + // current \c AnnotatedLine is not at the beginning of a line. + bool RelativeIndentation = + Style.IndentReference != FormatStyle::IRS_Absolute; bool StartsNewLine = TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst; - if (StartsNewLine) + if (RelativeIndentation && StartsNewLine) IndentTracker.adjustToUnmodifiedLine(TheLine); if (!DryRun) { bool ReformatLeadingWhitespace = Index: test/Format/line-ranges-indent-abs.c =================================================================== --- /dev/null +++ test/Format/line-ranges-indent-abs.c @@ -0,0 +1,10 @@ +// RUN: grep -Ev "// *[A-Z-]+:" %s \ +// RUN: | clang-format -style="{BasedOnStyle: LLVM, IndentReference: Absolute}" -lines=2:2 \ +// RUN: | FileCheck -strict-whitespace %s +// CHECK: {{^\ int f\(void\) \{$}} + int f(void) { +// CHECK: {{^\ \ int i = 0;$}} + int i = 0; +// CHECK: {{^\ \ return i;$}} + return i; +} Index: test/Format/line-ranges-indent-abs.m =================================================================== --- /dev/null +++ test/Format/line-ranges-indent-abs.m @@ -0,0 +1,9 @@ +// RUN: grep -Ev "// *[A-Z-]+:" %s \ +// RUN: | clang-format -style="{BasedOnStyle: LLVM, IndentReference: Absolute}" -lines=2:2 \ +// RUN: | FileCheck -strict-whitespace %s +// CHECK: {{^\ \@protocol\ A$}} + @protocol A +// CHECK: {{^-\ \(void\)f;$}} +- (void)f; +// CHECK: {{^\@end$}} +@end Index: test/Format/line-ranges-indent-rel.c =================================================================== --- /dev/null +++ test/Format/line-ranges-indent-rel.c @@ -0,0 +1,10 @@ +// RUN: grep -Ev "// *[A-Z-]+:" %s \ +// RUN: | clang-format -style=LLVM -lines=2:2 \ +// RUN: | FileCheck -strict-whitespace %s +// CHECK: {{^\ int f\(void\) \{$}} + int f(void) { +// CHECK: {{^\ \ \ int i = 0;$}} + int i = 0; +// CHECK: {{^\ \ \ return i;$}} + return i; +}