DevJourney · code I wrote while learning
format
1.4 KB#!/usr/bin/env bash
# Format staged source files with the standard formatter for each language.
set -euo pipefail
root=$(git rev-parse --show-toplevel)
cd "$root"
# Read staged paths safely, including paths containing whitespace.
mapfile -d '' files < <(git diff --cached --name-only --diff-filter=ACMR -z)
((${#files[@]})) || exit 0
format() {
local tool=$1
shift
command -v "$tool" >/dev/null 2>&1 || {
printf 'format: required formatter not found: %s\n' "$tool" >&2
exit 1
}
"$tool" "$@"
}
java=() c=() cpp=() go=() python=() js=() web=()
for file in "${files[@]}"; do
case "$file" in
*.java) java+=("$file") ;;
*.c|*.h) c+=("$file") ;;
*.cc|*.cpp|*.cxx|*.hpp|*.hh|*.hxx) cpp+=("$file") ;;
*.go) go+=("$file") ;;
*.py) python+=("$file") ;;
*.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.html|*.md|*.yaml|*.yml) web+=("$file") ;;
esac
done
((${#java[@]} == 0)) || format google-java-format --replace "${java[@]}"
((${#c[@]} == 0)) || format clang-format -i "${c[@]}"
((${#cpp[@]} == 0)) || format clang-format -i "${cpp[@]}"
((${#go[@]} == 0)) || format gofmt -w "${go[@]}"
((${#python[@]} == 0)) || format black "${python[@]}"
((${#web[@]} == 0)) || format prettier --write "${web[@]}"
# Include formatter output in the commit; never silently leave unstaged formatting.
git add -- "${files[@]}"