#!/usr/bin/env bash # Generates the compressed form of the code: every package, its size, and every top-level declaration # with the line to jump to. # # Usage: scripts/surface.sh print it # scripts/surface.sh --write regenerate docs/surface.md (`make surface`) # # Why this exists: reading a 400-line file to learn what is in it costs forty times what reading its # surface costs, and the answer to "where does X live" is almost never in the bodies. `go doc` already # does this for *exported* identifiers; this also covers unexported ones, which is where most of khosra # lives — nothing outside cmd/ has many exported names by design. # # Generated, never hand-edited, and gated: verify.sh regenerates and compares, so a stale surface fails # the build rather than misleading a reader. Purposes and intent stay in docs/state.md — this file is # mechanical and says only what is there. set -uo pipefail cd "$(dirname "$0")/.." || exit 1 emit() { printf '# Surface\n\n' printf 'Generated by `scripts/surface.sh` — do not edit. Regenerate with `make surface`.\n\n' printf 'Every top-level declaration in the engine, with its line. Read this before opening a source\n' printf 'file: it answers "where does X live" and "what is in this package" without the bodies. What each\n' printf 'file is *for* lives in `state.md`; why it is that way lives in `decisions.md`.\n' git ls-files '*.go' | grep -v '_test\.go$' | xargs -n1 dirname | sort -u | while read -r dir; do files=$(git ls-files "$dir/*.go" | grep -v '_test\.go$' | sort) [ -z "$files" ] && continue tests=$(git ls-files "$dir/*_test.go" | sort) code=$(echo "$files" | xargs wc -l | awk '$2!="total"{t+=$1} END{print t+0}') testloc=0 [ -n "$tests" ] && testloc=$(echo "$tests" | xargs wc -l | awk '$2!="total"{t+=$1} END{print t+0}') printf '\n## %s — %s lines' "$dir" "$code" [ "$testloc" -gt 0 ] && printf ' + %s test' "$testloc" printf '\n\n' # One manifest line per package, so the cost of opening any file is visible before you open it. echo "$files" | while read -r f; do printf '%s %s · ' "$(basename "$f")" "$(wc -l <"$f" | tr -d ' ')"; done | sed 's/ · $//' printf '\n\n' for f in $files; do # Top-level declarations only: in gofmt'd Go those are exactly the lines starting in column one. # The trailing brace and any body opener go, so a signature reads as one line. grep -nE '^(func|type|const|var) ' "$f" | sed -e 's/ {$//' -e 's/ ($//' -e 's/[[:space:]]*$//' | awk -F: -v n="$(basename "$f")" '{ line = $1; $1 = ""; sub(/^:/, ""); sub(/^ +/, ""); printf "- %s:%s %s\n", n, line, $0 }' done done } if [ "${1:-}" = "--write" ]; then emit >docs/surface.md printf 'wrote docs/surface.md (%s lines)\n' "$(wc -l