add(pre-commit): add configuration files for pre-commit, markdownlint, and codespell; update README with setup instructions

This commit is contained in:
HendrikRauh 2026-03-06 11:26:47 +01:00
parent 26f56e8ca6
commit 732046b15e
7 changed files with 191 additions and 69 deletions

View file

@ -1,2 +1,9 @@
--- ---
BasedOnStyle: LLVM BasedOnStyle: LLVM
# Include sorting
SortIncludes: true
# Spacing
MaxEmptyLinesToKeep: 2
SeparateDefinitionBlocks: Always

9
.codespellignore Normal file
View file

@ -0,0 +1,9 @@
# Words that codespell should ignore
# Add common false positives here
inout
uart
dout
din
Tage
alle
Aktion

32
.markdownlint.json Normal file
View file

@ -0,0 +1,32 @@
{
"default": true,
"MD013": {
"line_length": 300,
"tables": true,
"code_blocks": true
},
"MD033": false,
"MD012": {
"maximum": 2
},
"MD026": {
"punctuation": ".,;:!"
},
"MD024": {
"siblings_only": false
},
"MD029": {
"style": "ordered"
},
"MD046": {
"style": "fenced"
},
"MD049": {
"style": "underscore"
},
"MD050": {
"style": "asterisk"
},
"MD052": false,
"MD053": false
}

101
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,101 @@
# yaml-language-server: $schema=https://json.schemastore.org/pre-commit-config.json
# Global exclude pattern for build artifacts and dependencies
exclude: |
(?x)^(
build/|
managed_components/|
.*\.bin|
.*\.elf|
.*\.hex|
.*\.o|
flake.lock|
dependencies.lock|
assets/case/
)
repos:
# General file checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
# Line ending checks
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
args: [--fix=lf]
# Whitespace & formatting
- id: trailing-whitespace
# File format checks
- id: check-added-large-files
args: [--maxkb=1000]
- id: check-ast
- id: check-case-conflict
- id: check-docstring-first
- id: check-json
- id: check-merge-conflict
- id: detect-private-key
- id: debug-statements
- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: [--py38-plus]
# Spell checking
- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
hooks:
- id: codespell
args: [--ignore-words=.codespellignore]
# YAML linting
- repo: https://github.com/adrienverge/yamllint
rev: v1.37.1
hooks:
- id: yamllint
args:
[
--strict,
-d,
"{extends: default, rules: {line-length: {max: 120}, document-start: disable}}",
]
# Markdown linting
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.17.1
hooks:
- id: markdownlint-cli2
# Python formatting
- repo: https://github.com/psf/black
rev: 26.1.0
hooks:
- id: black
language_version: python3
args: [--quiet]
# JavaScript/JSON/CSS/HTML/YAML formatting and C/C++ formatting
- repo: local
hooks:
- id: prettier
name: prettier
entry: prettier
language: system
types_or: [javascript, jsx, json, css, scss, html, yaml]
exclude: \.md$
args: [--write, --ignore-unknown]
- id: clang-format
name: clang-format
entry: clang-format
language: system
types_or: [c, c++]
args: [-i]
- id: nixfmt
name: nixfmt
entry: nixfmt
language: system
types: [nix]

View file

@ -70,14 +70,14 @@ You have to short-circuit `R0` on the RS485 boards to enable the termination res
### Required tools ### Required tools
- `ESP-IDF` (includes `idf.py`) - `ESP-IDF` (includes `idf.py`)
- `Python 3`
- `invoke` (for project tasks) - `invoke` (for project tasks)
- Optional but recommended formatters:
- `clang-format` - Optional but recommended for development:
- `black` - `pre-commit` (for code quality hooks)
- `prettier` - `clang-format` (C/C++)
- `svgo` - `prettier` (JavaScript/CSS/HTML/YAML)
- `nixfmt` - `svgo` (SVG optimization)
- `nixfmt` (Nix formatting)
### Environment setup ### Environment setup
@ -101,6 +101,20 @@ invoke reset
invoke config invoke config
``` ```
### Pre-commit hooks
This project uses [pre-commit](https://pre-commit.com/) to automatically check code quality, formatting, and common mistakes before committing.
**Setup:**
```bash
# Install pre-commit hooks
pre-commit install
# Optionally, run all hooks on all files
pre-commit run --all-files
```
--- ---
## 📦 Case ## 📦 Case

View file

@ -24,11 +24,11 @@
pkgs.python3 pkgs.python3
pkgs.python3Packages.invoke pkgs.python3Packages.invoke
# Formatting tools pkgs.pre-commit
pkgs.clang-tools pkgs.clang-tools
pkgs.nodePackages.prettier pkgs.svgo
pkgs.nodePackages.svgo pkgs.prettier
pkgs.black
pkgs.nixfmt pkgs.nixfmt
]; ];
}; };

View file

@ -46,6 +46,13 @@ def clean(c):
@task @task
def config(c): def config(c):
"""Open menuconfig to edit project settings""" """Open menuconfig to edit project settings"""
is_windows = os.name == "nt"
if is_windows:
# Windows doesn't provide a POSIX pty, not sure how to open menuconfig interactive
print(
"Please run 'idf.py menuconfig' directly in the terminal to edit project settings. This option is not supported in the invoke task on Windows."
)
else:
c.run("idf.py menuconfig --color-scheme=monochrome", pty=True) c.run("idf.py menuconfig --color-scheme=monochrome", pty=True)
@ -76,66 +83,18 @@ def reset(c):
@task @task
def format(c): def format(c):
"""Format all source files with clang-format, black, prettier, nixfmt, and svgo""" """Format all source files using pre-commit hooks and optimize SVGs"""
missing_tools = [] print("\nOptimizing SVG files...")
c.run(
print("Formatting C files...") "find . -name '*.svg' -not -path './build/*' -not -path './managed_components/*' | xargs -r svgo --quiet --final-newline",
result = c.run(
"find main components -name '*.c' -o -name '*.h' | xargs clang-format -i",
warn=True, warn=True,
hide=False,
) )
if result.exited == 127 or (not result.ok and result.exited != 0): is_windows = os.name == "nt"
# Check if tool exists if is_windows:
check = c.run("command -v clang-format", warn=True, hide=True) # Windows doesn't provide a POSIX pty
if not check.ok: c.run("pre-commit run --all-files")
missing_tools.append("clang-format")
print("Formatting Python files...")
result = c.run("black tasks.py", warn=True, hide=False)
if result.exited == 127 or (not result.ok and result.exited != 0):
check = c.run("command -v black", warn=True, hide=True)
if not check.ok:
missing_tools.append("black")
print("Formatting Nix files...")
result = c.run("nixfmt flake.nix", warn=True, hide=False)
if result.exited == 127 or (not result.ok and result.exited != 0):
check = c.run("command -v nixfmt", warn=True, hide=True)
if not check.ok:
missing_tools.append("nixfmt")
print("Formatting SVG files...")
result = c.run(
"find . -name '*.svg' -not -path './build/*' -not -path './managed_components/*' | xargs -r svgo",
warn=True,
hide=False,
)
if result.exited == 127 or (not result.ok and result.exited != 0):
check = c.run("command -v svgo", warn=True, hide=True)
if not check.ok:
missing_tools.append("svgo")
print("Formatting other files...")
result = c.run(
"prettier --write '**/*.{js,json,yaml,yml,md,html,css}'", warn=True, hide=False
)
if result.exited == 127 or (not result.ok and result.exited != 0):
check = c.run("command -v prettier", warn=True, hide=True)
if not check.ok:
missing_tools.append("prettier")
if missing_tools:
print("\n" + "=" * 60)
print(f"❌ ERROR: Missing formatting tools: {', '.join(missing_tools)}")
print("=" * 60)
print("Please install them or reload the nix-shell.")
print("=" * 60 + "\n")
sys.exit(1)
else: else:
print("\n" + "=" * 60) c.run("pre-commit run --all-files", pty=True)
print("✅ All files formatted successfully!")
print("=" * 60 + "\n")
@task @task