<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/.clang-format, branch master</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/.clang-format?h=master</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/.clang-format?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-08-17T12:21:40Z</updated>
<entry>
<title>sl0ppty: clang-format, and a hook that runs it on what you staged</title>
<updated>2026-08-17T12:21:40Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-17T12:21:40Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=1f52c39ab0875162be013e6d78720a780df1d889'/>
<id>urn:sha1:1f52c39ab0875162be013e6d78720a780df1d889</id>
<content type='text'>
`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.
</content>
</entry>
</feed>
