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
# 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
- `ESP-IDF` (includes `idf.py`)
- `Python 3`
- `invoke` (for project tasks)
- Optional but recommended formatters:
- `clang-format`
- `black`
- `prettier`
- `svgo`
- `nixfmt`
- Optional but recommended for development:
- `pre-commit` (for code quality hooks)
- `clang-format` (C/C++)
- `prettier` (JavaScript/CSS/HTML/YAML)
- `svgo` (SVG optimization)
- `nixfmt` (Nix formatting)
### Environment setup
@ -101,6 +101,20 @@ invoke reset
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

View file

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

View file

@ -46,7 +46,14 @@ def clean(c):
@task
def config(c):
"""Open menuconfig to edit project settings"""
c.run("idf.py menuconfig --color-scheme=monochrome", pty=True)
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)
@task
@ -76,66 +83,18 @@ def reset(c):
@task
def format(c):
"""Format all source files with clang-format, black, prettier, nixfmt, and svgo"""
missing_tools = []
print("Formatting C files...")
result = c.run(
"find main components -name '*.c' -o -name '*.h' | xargs clang-format -i",
"""Format all source files using pre-commit hooks and optimize SVGs"""
print("\nOptimizing SVG files...")
c.run(
"find . -name '*.svg' -not -path './build/*' -not -path './managed_components/*' | xargs -r svgo --quiet --final-newline",
warn=True,
hide=False,
)
if result.exited == 127 or (not result.ok and result.exited != 0):
# Check if tool exists
check = c.run("command -v clang-format", warn=True, hide=True)
if not check.ok:
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)
is_windows = os.name == "nt"
if is_windows:
# Windows doesn't provide a POSIX pty
c.run("pre-commit run --all-files")
else:
print("\n" + "=" * 60)
print("✅ All files formatted successfully!")
print("=" * 60 + "\n")
c.run("pre-commit run --all-files", pty=True)
@task