---
# =============================================================================
# Modern C++ Systems House Style
#
# Language baseline : C++23
# Formatter baseline: clang-format 23.1.x
# Style philosophy  : Google-derived, compact, explicit, type-first,
#                     low-diff-noise, systems-oriented.
# =============================================================================

Language: Cpp
BasedOnStyle: Google
Standard: c++23

# -----------------------------------------------------------------------------
# Core layout
# -----------------------------------------------------------------------------

ColumnLimit: 100

IndentWidth: 4
ContinuationIndentWidth: 4
TabWidth: 4
UseTab: Never

# Keep multiline expressions visually anchored to their opening delimiter.
AlignAfterOpenBracket: true

# Avoid artificial visual tables that create noisy diffs when identifiers change.
AlignTrailingComments:
  Kind: Never
  OverEmptyLines: 0

SpacesBeforeTrailingComments: 2

# -----------------------------------------------------------------------------
# Type spelling: T*, T&, T&&
# -----------------------------------------------------------------------------

# Do not infer pointer style from legacy code in each individual file.
DerivePointerAlignment: false

# Type-first visual model:
#
#   T* ptr;
#   T& ref;
#   T&& ref;
#
PointerAlignment: Left
ReferenceAlignment: Left

# House style uses west-const in authored code:
#
#   const T*
#   const T&
#
# Do NOT ask clang-format to rewrite qualifiers automatically: clang-format
# explicitly warns that qualifier reordering can make incorrect semantic guesses.
QualifierAlignment: Leave
SpaceAroundPointerQualifiers: Default

# -----------------------------------------------------------------------------
# Classes / records
# -----------------------------------------------------------------------------

# Prefer:
#
# class Foo {
# public:
#     ...
#
# private:
#     ...
# };
#
IndentAccessModifiers: false
AccessModifierOffset: -4

EmptyLineBeforeAccessModifier: LogicalBlock
EmptyLineAfterAccessModifier: Never

# Empty marker/tag records may remain compact:
#
# struct EmptyTag {};
#
# Non-empty records remain multiline.
AllowShortRecordOnASingleLine: Empty

# -----------------------------------------------------------------------------
# Control flow
# -----------------------------------------------------------------------------

BreakBeforeBraces: Attach

# Never collapse control-flow bodies onto one line.
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false

# Keep switch structure shallow and visually obvious.
IndentCaseLabels: false

# -----------------------------------------------------------------------------
# Functions / lambdas
# -----------------------------------------------------------------------------

# Empty functions may stay compact; real implementations get a normal body.
AllowShortFunctionsOnASingleLine: Empty

# Small inline callback lambdas are often clearer on one line:
#
# std::ranges::find_if(values, [](int value) { return value > 0; });
#
AllowShortLambdasOnASingleLine: Inline

# If a parameter/argument list fits within 100 columns, keep it on one line.
# Once it must wrap, prefer one logical item per continuation line instead of
# dense partial bin-packing.
PackParameters:
  BinPack: OnePerLine

PackArguments:
  BinPack: OnePerLine

AllowAllParametersOfDeclarationOnNextLine: false
AllowAllArgumentsOnNextLine: false

# Keep noexcept attached to the function signature.
AllowBreakBeforeNoexceptSpecifier: Never

# -----------------------------------------------------------------------------
# Constructors / inheritance
# -----------------------------------------------------------------------------

# Short:
#
# Point::Point(float x, float y) : x_(x), y_(y) {}
#
# Long:
#
# RobotFrame::RobotFrame(...)
#     : samples_(...),
#       timestamp_(...) {}
#
BreakConstructorInitializers: BeforeColon
PackConstructorInitializers: CurrentLine

# Long inheritance lists use the same visual grammar.
BreakInheritanceList: BeforeColon

# -----------------------------------------------------------------------------
# C++20 / C++23 Concepts
# -----------------------------------------------------------------------------

# Prefer:
#
# template <typename T>
# concept Sensor = ...;
#
BreakBeforeConceptDeclarations: Always

# Prefer:
#
# template <typename T>
# requires Sensor<T>
# void process(T value);
#
RequiresClausePosition: OwnLine
IndentRequiresClause: false

# Avoid excessive indentation inside requires expressions.
RequiresExpressionIndentation: OuterScope

# Keep normal compound requirements readable and compact:
#
# { value.read() } -> std::same_as<int>;
#
AllowShortCompoundRequirementOnASingleLine: true

SpaceAfterTemplateKeyword: true

# -----------------------------------------------------------------------------
# Enums / namespaces
# -----------------------------------------------------------------------------

AllowShortEnumsOnASingleLine: false
AllowShortNamespacesOnASingleLine: false

NamespaceIndentation: None
FixNamespaceComments: true
ShortNamespaceLines: 1

# -----------------------------------------------------------------------------
# Vertical rhythm
# -----------------------------------------------------------------------------

MaxEmptyLinesToKeep: 1

KeepEmptyLines:
  AtStartOfBlock: false
  AtStartOfFile: false
  AtEndOfFile: false

# Give top-level definitions enough breathing room without allowing arbitrary
# vertical whitespace to accumulate.
SeparateDefinitionBlocks: Always

# -----------------------------------------------------------------------------
# String literals
# -----------------------------------------------------------------------------

# Do not manufacture adjacent string literals merely to satisfy ColumnLimit.
# Long human-facing strings should be intentionally structured by the author.
BreakStringLiterals: false

# -----------------------------------------------------------------------------
# Includes
# -----------------------------------------------------------------------------

# The main header corresponding to a .cpp automatically receives category 0.
#
# Example:
#
#   robot_frame.cpp
#   robot_frame.hpp       <- category 0 automatically
#
MainIncludeChar: Quote
IncludeIsMainRegex: "(_test)?$"

# Merge existing include blocks, sort them, then rebuild semantic groups.
IncludeBlocks: Regroup

SortIncludes:
  Enabled: true
  IgnoreCase: false
  IgnoreExtension: false

# clang-format uses the FIRST matching regex.
#
# Resulting order:
#
#   0. Current translation unit's main header
#   1. Standard library + OS/system headers
#   2. Known third-party libraries
#   3. Project-local headers
#
IncludeCategories:
  # Known third-party roots must appear before the generic <...> matcher.
  - Regex: '^["<](boost|fmt|spdlog|nlohmann|gtest|gmock|benchmark|Eigen|eigen3)/'
    Priority: 2
    CaseSensitive: true

  # Standard C/C++ library and platform/system headers.
  - Regex: "^<.*>$"
    Priority: 1
    CaseSensitive: true

  # Project-local headers.
  - Regex: '^".*"$'
    Priority: 3
    CaseSensitive: true
...
