Skip to content

Commit 8d87fad

Browse files
tapclaude
andcommitted
Adopt TapHouse rules and the tap::python namespace
Bring the renamed PythonTap (was Python-Max) under the shared Tap House Rules and the family C++ namespace convention. - Sync the four canonical TapHouse configs (.clang-format, .clang-tidy, STYLE.md, .pre-commit-config.yaml) at v4, and add scripts/tidy.sh (the local clang-tidy gate mirror). - Namespace: tap::python_runtime -> tap::python (the runtime alias and its uses are unchanged; the Min external class `python` stays global, per the family's Min-object convention). - Apply the house layout with clang-format, and add braces to every control-flow body (the mandatory-braces rule; clang-format does not insert them, so this was a one-time InsertBraces pass, verified complete). Naming already matched the house scheme (m_ members, k_/s_ prefixes, snake_case). - Add .github/workflows/style.yml: the TapHouse drift check (v4) and a clang-format gate on Linux, plus the clang-tidy naming + braces gate on macOS — tap.python~ only configures with the embedded Python runtime, which installs on macOS/Windows only, so Linux cannot produce the compile database. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRTDgYKY38WH8Bqz17W9k1
1 parent b98556a commit 8d87fad

13 files changed

Lines changed: 896 additions & 387 deletions

.clang-format

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Tap House Rules — the Tap family house style. Copy verbatim into every *Tap repo.
2+
# 4-space indent (incl. namespaces), aligned declaration/assignment columns,
3+
# attached braces (else/catch break), comma-first ctor initializers,
4+
# left-bound pointers, 120-column limit. Layout only — naming and mandatory
5+
# braces are enforced separately by .clang-tidy (clang-format cannot check
6+
# identifier names, and its brace insertion is not semantically aware).
7+
Language: Cpp
8+
BasedOnStyle: LLVM
9+
Standard: c++20
10+
11+
ColumnLimit: 120
12+
IndentWidth: 4
13+
AccessModifierOffset: -2
14+
NamespaceIndentation: All
15+
16+
PointerAlignment: Left
17+
DerivePointerAlignment: false
18+
BreakBeforeBinaryOperators: NonAssignment
19+
SpaceBeforeCpp11BracedList: false
20+
AlwaysBreakTemplateDeclarations: Yes
21+
22+
# Braces attach everywhere (including functions); only else/catch break.
23+
BreakBeforeBraces: Custom
24+
BraceWrapping:
25+
AfterFunction: false
26+
AfterClass: false
27+
AfterStruct: false
28+
AfterNamespace: false
29+
AfterControlStatement: Never
30+
BeforeElse: true
31+
BeforeCatch: true
32+
BreakConstructorInitializers: BeforeComma
33+
PackConstructorInitializers: Never
34+
35+
AlignConsecutiveAssignments: true
36+
AlignConsecutiveDeclarations: true
37+
AlignTrailingComments: true
38+
39+
# Short accessor functions and lambdas may stay inline, but control-flow
40+
# statements never do: every if/for/while is braced AND expanded (see
41+
# .clang-tidy readability-braces-around-statements).
42+
AllowShortFunctionsOnASingleLine: Inline
43+
AllowShortLambdasOnASingleLine: All
44+
AllowShortIfStatementsOnASingleLine: Never
45+
AllowShortLoopsOnASingleLine: false
46+
AllowShortBlocksOnASingleLine: Never
47+
48+
BreakStringLiterals: false
49+
KeepEmptyLinesAtTheStartOfBlocks: false
50+
InsertNewlineAtEOF: true
51+
52+
# Include ordering: main header (auto, priority 0) -> C++ standard ->
53+
# third-party -> this project. Regroup enforces it; blank lines between groups.
54+
SortIncludes: CaseSensitive
55+
IncludeBlocks: Regroup
56+
IncludeCategories:
57+
# C++ standard library: <angle> with no '/' and no '.' (e.g. <vector>)
58+
- Regex: '^<[[:alnum:]_]+>$'
59+
Priority: 2
60+
# Other angle-bracket headers (third-party, e.g. <gtest/gtest.h>)
61+
- Regex: '^<.*>$'
62+
Priority: 3
63+
# This project: quoted includes
64+
- Regex: '^".*"$'
65+
Priority: 4
66+
67+
# Min-DevKit declarative DSL (Max/Min externals: TapTools, AmbiTap-Max, ...).
68+
# MIN_FUNCTION / MIN_ARGUMENT_FUNCTION expand to a lambda; teach clang-format
69+
# their shape so attribute/message/argument setter bodies format as lambda
70+
# blocks instead of being shredded. Completely inert for repos that don't use
71+
# these macros (the pure-C++ libraries). Requires clang-format >= 15.
72+
Macros:
73+
- 'MIN_FUNCTION=[](const atoms& args, int inlet) -> atoms'
74+
- 'MIN_ARGUMENT_FUNCTION=[](const atom& arg, int index) -> void'

.clang-tidy

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Tap House Rules — naming + mandatory-braces enforcement. Copy verbatim into
2+
# every *Tap repo. This is what actually checks m_ members, k_ constants, snake_case
3+
# types/functions, PascalCase template parameters, and braces around every
4+
# control-flow body — clang-format cannot (and its InsertBraces is not
5+
# semantically aware). Scope is intentionally limited to these for now;
6+
# correctness/modernize checks can be layered on later.
7+
#
8+
# NOTE: WarningsAsErrors is intentionally NOT set here so local runs only warn.
9+
# CI passes --warnings-as-errors=readability-* to make the gate blocking.
10+
Checks: >
11+
-*,
12+
readability-identifier-naming,
13+
readability-braces-around-statements
14+
# Analyze this project's own headers only (under include/); vendored third_party
15+
# and fetched deps live outside include/ and are excluded. Generated tables
16+
# (room_data.h, hrtf_data.h, tdesigns.h) live under include/ but carry
17+
# // NOLINTBEGIN(readability-identifier-naming) markers from their generators.
18+
# NOTE: clang-tidy uses llvm::Regex, which has NO negative lookahead — a
19+
# '^(?!...)' pattern silently matches nothing and disables the check.
20+
HeaderFilterRegex: '.*/(include|tests)/.*'
21+
22+
# --- Linear-algebra notation carve-out --------------------------------------
23+
# The DSP math deliberately uses capitalized matrix/vector symbols (Y = SH
24+
# matrix, D = decoder, R = rotation, ...). Permit a leading-capital symbol with
25+
# an optional short subscript and _snake suffixes (Y, Yd, R9, Y_virtual). This
26+
# Also matrix products (DtD, YtD). Still rejects camelCase (frameCount).
27+
# Applied below per category via <Category>IgnoredRegexp.
28+
CheckOptions:
29+
# --- Types: snake_case ---
30+
- key: readability-identifier-naming.ClassCase
31+
value: lower_case
32+
- key: readability-identifier-naming.StructCase
33+
value: lower_case
34+
- key: readability-identifier-naming.UnionCase
35+
value: lower_case
36+
- key: readability-identifier-naming.EnumCase
37+
value: lower_case
38+
- key: readability-identifier-naming.EnumConstantCase
39+
value: lower_case
40+
- key: readability-identifier-naming.ScopedEnumConstantCase
41+
value: lower_case
42+
- key: readability-identifier-naming.TypeAliasCase
43+
value: lower_case
44+
- key: readability-identifier-naming.TypedefCase
45+
value: lower_case
46+
- key: readability-identifier-naming.NamespaceCase
47+
value: lower_case
48+
49+
# --- Concepts: snake_case (like the types they constrain, per P1754) ---
50+
- key: readability-identifier-naming.ConceptCase
51+
value: lower_case
52+
53+
# --- Functions / methods: snake_case ---
54+
- key: readability-identifier-naming.FunctionCase
55+
value: lower_case
56+
- key: readability-identifier-naming.MethodCase
57+
value: lower_case
58+
59+
# --- Variables / parameters / locals: snake_case, no prefix ---
60+
- key: readability-identifier-naming.VariableCase
61+
value: lower_case
62+
- key: readability-identifier-naming.ParameterCase
63+
value: lower_case
64+
- key: readability-identifier-naming.LocalVariableCase
65+
value: lower_case
66+
- key: readability-identifier-naming.LocalConstantCase
67+
value: lower_case
68+
# Math-notation carve-out (see header): capitalized matrix/vector symbols.
69+
- key: readability-identifier-naming.ParameterIgnoredRegexp
70+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
71+
- key: readability-identifier-naming.LocalVariableIgnoredRegexp
72+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
73+
- key: readability-identifier-naming.LocalConstantIgnoredRegexp
74+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
75+
- key: readability-identifier-naming.VariableIgnoredRegexp
76+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
77+
78+
# --- Data members: private/protected get m_; public struct fields bare ---
79+
- key: readability-identifier-naming.PrivateMemberCase
80+
value: lower_case
81+
- key: readability-identifier-naming.PrivateMemberPrefix
82+
value: 'm_'
83+
- key: readability-identifier-naming.ProtectedMemberCase
84+
value: lower_case
85+
- key: readability-identifier-naming.ProtectedMemberPrefix
86+
value: 'm_'
87+
- key: readability-identifier-naming.PublicMemberCase
88+
value: lower_case
89+
# const (non-static) data members are still members -> keep the m_ marker
90+
- key: readability-identifier-naming.ConstantMemberCase
91+
value: lower_case
92+
- key: readability-identifier-naming.ConstantMemberPrefix
93+
value: 'm_'
94+
# Math-notation carve-out for capitalized matrix/vector member symbols.
95+
- key: readability-identifier-naming.PublicMemberIgnoredRegexp
96+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
97+
- key: readability-identifier-naming.PrivateMemberIgnoredRegexp
98+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
99+
- key: readability-identifier-naming.ProtectedMemberIgnoredRegexp
100+
value: '^[A-Z][A-Za-z0-9]*(_[A-Za-z0-9]+)*$'
101+
102+
# --- Constants at namespace/class/static scope: k_ + snake_case ---
103+
# (constexpr/const LOCALS stay bare via LocalConstantCase above)
104+
- key: readability-identifier-naming.GlobalConstantCase
105+
value: lower_case
106+
- key: readability-identifier-naming.GlobalConstantPrefix
107+
value: 'k_'
108+
- key: readability-identifier-naming.ClassConstantCase
109+
value: lower_case
110+
- key: readability-identifier-naming.ClassConstantPrefix
111+
value: 'k_'
112+
- key: readability-identifier-naming.StaticConstantCase
113+
value: lower_case
114+
- key: readability-identifier-naming.StaticConstantPrefix
115+
value: 'k_'
116+
117+
# --- Template parameters: PascalCase (the ONLY leading-capital names) ---
118+
# Applies to type AND non-type params: template <int Order>, not <int order>.
119+
- key: readability-identifier-naming.TemplateParameterCase
120+
value: CamelCase
121+
- key: readability-identifier-naming.TypeTemplateParameterCase
122+
value: CamelCase
123+
- key: readability-identifier-naming.ValueTemplateParameterCase
124+
value: CamelCase
125+
126+
# --- Macros: ALL_CAPS ---
127+
- key: readability-identifier-naming.MacroDefinitionCase
128+
value: UPPER_CASE
129+
130+
# --- Mandatory braces: brace every control-flow body, even one-liners ---
131+
- key: readability-braces-around-statements.ShortStatementLines
132+
value: '0'

.github/workflows/style.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Tap House Style
2+
3+
# Enforces the shared Tap House Rules: (1) a drift check against the canonical
4+
# TapHouse configs, (2) a clang-format layout check, and (3) clang-tidy naming +
5+
# mandatory-braces over the external's own translation units.
6+
#
7+
# tap.python~ only configures with the embedded Python runtime present, and that
8+
# runtime installs on macOS/Windows only — so the clang-tidy gate (which needs a
9+
# compile database) runs on macOS. The drift and clang-format checks are
10+
# platform-independent and stay on Linux.
11+
on: [push, pull_request]
12+
13+
jobs:
14+
drift:
15+
uses: tap/taphouse/.github/workflows/drift-check.yml@v4
16+
with:
17+
ref: v4
18+
19+
clang-format:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: Install clang-format
24+
run: sudo apt-get update -q && sudo apt-get install -y -q clang-format-18
25+
- name: clang-format check (own sources)
26+
run: clang-format-18 --dry-run --Werror $(git ls-files 'source/projects/*.cpp' 'source/projects/*.h')
27+
28+
clang-tidy:
29+
runs-on: macos-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
with:
33+
submodules: recursive
34+
- name: Install the embedded Python runtime (needed to configure)
35+
run: ./scripts/install-runtime.sh
36+
- name: Install clang-tidy (LLVM 18)
37+
run: brew install llvm@18
38+
- name: Configure (compile database)
39+
run: cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
40+
- name: clang-tidy (project TUs; min-api and fetched deps excluded)
41+
run: |
42+
tidy="$(brew --prefix llvm@18)/bin/clang-tidy"
43+
files=$(python3 -c "import json; print('\n'.join(e['file'] for e in json.load(open('build/compile_commands.json')) if 'source/projects' in e['file']))")
44+
fail=0
45+
for f in $files; do
46+
out=$("$tidy" -p build --warnings-as-errors='readability-*' "$f" 2>/dev/null || true)
47+
if echo "$out" | grep -qE "warning:|error:"; then echo "$out"; fail=1; fi
48+
done
49+
[ "$fail" -eq 0 ] && echo "clang-tidy clean." || { echo "::error::clang-tidy found violations"; exit 1; }

.pre-commit-config.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Canonical Tap House pre-commit config — the single source of truth for the
2+
# Tap family's local formatting hook. Distributed to every Tap repo by
3+
# scripts/sync.sh (alongside .clang-format / .clang-tidy / STYLE.md) and kept
4+
# honest by the drift-check workflow, so every repo runs the SAME hook at the
5+
# SAME pinned clang-format version.
6+
#
7+
# Why the pin matters: an ad-hoc hook using each machine's own clang-format
8+
# would format differently than CI and be worse than none. The `rev` below is
9+
# the Tap-wide clang-format version — bump it HERE, re-sync, and every repo
10+
# (and its CI, which runs `pre-commit run --all-files`) moves together.
11+
#
12+
# Adopt in a consumer repo:
13+
# 1. taphouse/scripts/sync.sh /path/to/your-repo # copies this file in
14+
# 2. cd your-repo && pre-commit install # once per clone
15+
# Thereafter `git commit` formats staged C/C++ before it can be pushed, so the
16+
# clang-format CI gate can never fail on a local commit again.
17+
repos:
18+
- repo: https://github.com/pre-commit/mirrors-clang-format
19+
rev: v18.1.3 # Tap-wide clang-format version (matches CI)
20+
hooks:
21+
- id: clang-format
22+
types_or: [c, c++]
23+
exclude: '^third_party/' # vendored sources are formatted upstream, never by us

0 commit comments

Comments
 (0)