Skip to content

🤖 Format Automation

🔧 Setup

VSCode

{
  "editor.formatOnSave": true,
  "C_Cpp.clang_format_style": "file"
}

CLion

Settings → Editor → Code Style → C/C++ → Scheme: Project (reads .clang-format)

Vim/Neovim

" .vimrc
autocmd BufWritePre *.cpp,*.hpp,*.h :%!clang-format

Emacs

;; .emacs
(add-hook 'c++-mode-hook 'clang-format-buffer-on-save)

📜 Pre-commit Hook

Create .git/hooks/pre-commit:

#!/bin/bash
# Format staged C++ files

echo "Running clang-format on staged files..."

# Get staged C++ files
files=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(cpp|hpp|h)$')

if [ -n "$files" ]; then
    # Format files
    echo "$files" | xargs clang-format -i

    # Re-add formatted files
    echo "$files" | xargs git add

    echo "✓ Formatting complete"
else
    echo "No C++ files to format"
fi

exit 0

Make it executable:

chmod +x .git/hooks/pre-commit

🚀 CI Check

GitHub Actions

name: Format Check

on: [pull_request]

jobs:
  format:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install clang-format
        run: sudo apt-get install -y clang-format

      - name: Check Formatting
        run: |
          find src -name '*.cpp' -o -name '*.hpp' | \
            xargs clang-format --dry-run --Werror

GitLab CI

format-check:
  image: ubuntu:latest
  before_script:
    - apt-get update && apt-get install -y clang-format
  script:
    - clang-format --dry-run --Werror src/**/*.cpp src/**/*.hpp
  only:
    - merge_requests

🛠️ Manual Commands

Format single file

clang-format -i src/audio_engine.cpp

Format entire project

find src -name '*.cpp' -o -name '*.hpp' | xargs clang-format -i

Check formatting (no changes)

clang-format --dry-run --Werror src/**/*.cpp

Format changed files only

git diff --name-only | grep -E '\.(cpp|hpp)$' | xargs clang-format -i

📊 Validation

Before commit

# Check if any files would change
git diff --name-only | grep -E '\.(cpp|hpp)$' | \
  xargs clang-format --dry-run --Werror

# If no errors, formatting is correct

In CI

# Exit with error if formatting is needed
clang-format --dry-run --Werror $(find src -name '*.cpp' -o -name '*.hpp')

🔄 Gradual Adoption

For large existing codebases:

  1. Phase 1: Format new files only
  2. Phase 2: Format on touch (when editing)
  3. Phase 3: Mass format (scheduled, approved)

Format-on-touch strategy

# Only format files modified in current branch
git diff --name-only main...HEAD | \
  grep -E '\.(cpp|hpp)$' | \
  xargs clang-format -i

⚠️ Troubleshooting

Formatter not found

# Install clang-format
# Ubuntu/Debian
sudo apt-get install clang-format

# macOS
brew install clang-format

# Windows
choco install llvm

Wrong version

Ensure clang-format version ≥ 10:

clang-format --version

Config not detected

Verify .clang-format is in project root:

ls -la .clang-format

Pre-commit hook not running

# Check hook is executable
ls -l .git/hooks/pre-commit

# Make executable
chmod +x .git/hooks/pre-commit