| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #!/bin/bash
- # hooks/post-edit-format.sh
- # PostToolUse hook - auto-formats files after Write or Edit operations
- # Matcher: Write|Edit
- #
- # Configuration in .claude/settings.json:
- # {
- # "hooks": {
- # "PostToolUse": [{
- # "matcher": "Write|Edit",
- # "hooks": ["bash hooks/post-edit-format.sh $FILE_PATH"]
- # }]
- # }
- # }
- FILE="$1"
- # Skip if no file path provided
- if [[ -z "$FILE" || ! -f "$FILE" ]]; then
- exit 0
- fi
- EXT="${FILE##*.}"
- FORMATTED=false
- format_js_ts() {
- if command -v npx &>/dev/null; then
- if [[ -f "node_modules/.bin/prettier" ]]; then
- npx prettier --write "$FILE" 2>/dev/null && FORMATTED=true
- return 0
- elif [[ -f "node_modules/.bin/biome" ]]; then
- npx biome format --write "$FILE" 2>/dev/null && FORMATTED=true
- return 0
- fi
- fi
- # Fallback: dprint if available
- if command -v dprint &>/dev/null; then
- dprint fmt "$FILE" 2>/dev/null && FORMATTED=true
- fi
- }
- format_python() {
- if command -v ruff &>/dev/null; then
- ruff format "$FILE" 2>/dev/null && FORMATTED=true
- elif command -v black &>/dev/null; then
- black --quiet "$FILE" 2>/dev/null && FORMATTED=true
- fi
- # Also fix import sorting
- if command -v ruff &>/dev/null; then
- ruff check --fix --select I "$FILE" 2>/dev/null
- elif command -v isort &>/dev/null; then
- isort --quiet "$FILE" 2>/dev/null
- fi
- }
- format_go() {
- if command -v goimports &>/dev/null; then
- goimports -w "$FILE" 2>/dev/null && FORMATTED=true
- elif command -v gofmt &>/dev/null; then
- gofmt -w "$FILE" 2>/dev/null && FORMATTED=true
- fi
- }
- format_rust() {
- if command -v rustfmt &>/dev/null; then
- rustfmt "$FILE" 2>/dev/null && FORMATTED=true
- fi
- }
- format_php() {
- if [[ -f "vendor/bin/pint" ]]; then
- ./vendor/bin/pint "$FILE" 2>/dev/null && FORMATTED=true
- elif command -v php-cs-fixer &>/dev/null; then
- php-cs-fixer fix "$FILE" --quiet 2>/dev/null && FORMATTED=true
- fi
- }
- format_css() {
- if command -v npx &>/dev/null && [[ -f "node_modules/.bin/prettier" ]]; then
- npx prettier --write "$FILE" 2>/dev/null && FORMATTED=true
- fi
- }
- format_json_yaml() {
- if command -v npx &>/dev/null && [[ -f "node_modules/.bin/prettier" ]]; then
- npx prettier --write "$FILE" 2>/dev/null && FORMATTED=true
- elif command -v dprint &>/dev/null; then
- dprint fmt "$FILE" 2>/dev/null && FORMATTED=true
- fi
- }
- case "$EXT" in
- ts|tsx|js|jsx|mjs|cjs)
- format_js_ts
- ;;
- py|pyi)
- format_python
- ;;
- go)
- format_go
- ;;
- rs)
- format_rust
- ;;
- php)
- format_php
- ;;
- css|scss|less)
- format_css
- ;;
- json|yaml|yml)
- format_json_yaml
- ;;
- md)
- # Markdown formatting is optional and sometimes unwanted
- # Uncomment to enable:
- # if command -v npx &>/dev/null && [[ -f "node_modules/.bin/prettier" ]]; then
- # npx prettier --write --prose-wrap preserve "$FILE" 2>/dev/null && FORMATTED=true
- # fi
- ;;
- esac
- # Silent success - only output on format to keep context clean
- if [[ "$FORMATTED" == "true" ]]; then
- echo "Formatted: $(basename "$FILE")"
- fi
- exit 0
|