aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-17 14:21:40 +0200
committeruser <user@clank>2026-08-17 14:21:40 +0200
commit1f52c39ab0875162be013e6d78720a780df1d889 (patch)
tree29e9d72aa85a39d5aec52fafcecd80deb3bdf2a7 /docs
parentsl0ppty: a dead pane says what it ran (diff)
downloadslosh-1f52c39ab0875162be013e6d78720a780df1d889.tar.gz
slosh-1f52c39ab0875162be013e6d78720a780df1d889.tar.xz
slosh-1f52c39ab0875162be013e6d78720a780df1d889.zip
sl0ppty: clang-format, and a hook that runs it on what you staged
`make hooks` points `core.hooksPath` at `.githooks`, and from then on committing C formats it first, so what lands in git is already formatted. `make fmt` does the whole tree, `make fmt-check` only reports. The reformat itself is the next commit. **The config was chosen by measuring, not by taste.** LLVM is the base because it is what this code was already written in by hand -- two spaces, 80 columns, `char *p`, braces attached -- but LLVM alone rewrote 38% of the lines. Three disagreements account for most of that, and each is a real house idiom rather than an accident: - `if (!p) return false;` on one line, which is the guard idiom throughout. LLVM splits every one of them in two, two thirds of the churn on its own. `WithoutElse`, so an `if` that has an `else` still opens up: a one-line `if` hiding an `else` is the arrangement that hides a bug. - Comments are not reflowed. They are prose, wrapped by hand, and the breaks sometimes carry meaning -- a paragraph, a list, a diagram of a pane. A comment that runs long is a thing for a person to fix, not for a formatter to even out. - Include order is left alone. It is grouped by hand here and is not alphabetical within a group; sorting it would be churn at best and, at worst, a build that depends on an order nobody wrote down. Those three, plus one-line `case` labels and loops, bring the reformat from 38% to 17% -- and what is left is alignment and the hand-packed tables, which is the part a formatter is *for*. The vendored terminal core is excluded everywhere: `.githooks/pre-commit`, `make fmt` and `make fmt-check` all filter `^vendor/`. It is pinned by commit (D12) and reformatting it would turn every future re-vendor into a merge. **The hook refuses a partly staged file rather than widening the commit.** `clang-format -i` rewrites the working tree, so re-staging afterwards would commit work somebody deliberately left out with `git add -p`. It says which files and what to do instead. It also says when it formatted something, because a hook that edits your commit silently is a hook people learn to distrust, and it fails with the package name when `clang-format` is missing rather than letting unformatted C through the one check meant to stop it. `--no-verify` still escapes. Verified in a scratch clone, all four paths: a badly formatted file is committed formatted; a partly staged one is refused with `HEAD` unchanged and the index untouched; a commit with no C in it draws no comment; and `--no-verify` puts unformatted code in, which is what asking for it means.
Diffstat (limited to 'docs')
-rw-r--r--docs/design.md20
1 files changed, 20 insertions, 0 deletions
diff --git a/docs/design.md b/docs/design.md
index 3775fef..d24641f 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -48,3 +48,23 @@ src/kdl.c a hand-rolled KDL subset, for configs and layouts
About 15k lines of C. The vendored terminal core does VT parsing, scrollback,
selection, images and key encoding; everything above is ours.
+
+## How it is formatted
+
+`clang-format`, with the config in `.clang-format`. `make fmt` applies it,
+`make fmt-check` only reports, and `make hooks` installs a pre-commit hook that
+formats the C you staged so what lands in git is already formatted.
+
+The base is LLVM, because that is what this code was written in by hand — two
+spaces, 80 columns, `char *p`, braces attached. The settings that differ from it
+were chosen by measuring the reformat rather than by taste: LLVM alone rewrote 38%
+of the lines, mostly by splitting `if (!p) return false;` in two and reflowing
+comments that are prose. Keeping those two and leaving include order alone brings
+it to 17%, which is alignment and table packing.
+
+Comments are not reflowed. They are prose here, wrapped by hand, and sometimes the
+line breaks carry meaning — a paragraph, a list, a diagram of a pane. A comment
+that runs long is a thing for a person to fix.
+
+The vendored terminal core is never formatted: it is pinned by commit (D12), and
+reformatting it would turn every re-vendor into a merge.