headwater-paint 0.4.0

The terminal palette HW-DR-0045 rules on: a color mode, the semantic roles, and the pure functions every renderer of this engine applies them through
Documentation
  • Coverage
  • 68.75%
    11 out of 16 items documented0 out of 5 items with examples
  • Size
  • Source code size: 13.2 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 282.0 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 4s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • headwater-ai/headwater
    0 0 65
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • jameswbaxter

The palette HW-DR-0045 rules on, and the pure functions every renderer applies it through.

Why this is a leaf crate and not a module of headwater-check

These primitives lived in headwater-check until #479, beside headwater_check::fill, because the four crates that needed them then — headwater-check itself, headwater-query, headwater-sweep and headwater-cli — all sit above that crate and reach it without a cycle. That placement held for as long as every renderer that wanted color sat above headwater-check, and it stopped holding the moment one did not.

headwater-check depends on headwater-census, headwater-resolve and headwater-lock. A renderer inside any of those three cannot name headwater_check::paint at all: cargo refuses the cycle before a line compiles. Six of the eleven command lines whose interface contract still promises terminal sensing render inside exactly those three crates — headwater derived in headwater-census, and taxonomy validate, resolve, publish, vendor and migrate in headwater-resolve and headwater-lock. Wiring any of them was not expensive, it was impossible, and nothing recorded that until the dependency graph was read against HW-OBL-0180.

So the palette moved to the bottom of the graph, where every renderer of this engine reaches it. This crate depends on nothing, for the reason headwater-hash and headwater-mark depend on nothing: a rule that two components on opposite sides of the engine both read must have one implementation, and a second copy of a palette is two palettes.

What stayed in headwater-check, and why

Severity is a type of the check layer, so glyph, severity_role and severity_word stayed with it rather than dragging Severity down here behind them. headwater_check::paint re-exports everything below unchanged, so every caller that wrote headwater_check::paint::Role before the move still compiles — the same re-export chain engine/crates/cli/src/paint.rs already ran one level up.

Deciding whether a stream renders color stays in headwater-cli: stdout_color and its stderr twin read the terminal a process is attached to, which is a fact about the binary rather than about a corpus.

ColorMode is a parameter, never a read

Every function here is pure: given the same [Role] and the same [ColorMode], it returns the same bytes. Nothing here opens a stream or reads an environment variable, which is what makes every renderer that takes a mode unit-testable with a case table and no real terminal.

That purity is also the defect HW-OBL-0180 records: a renderer threaded with a mode and a call site that hands it [ColorMode::Plain] forever passes every headless test there is. What catches that is tools/engine/color-fixtures.sh, which attaches a pseudo-terminal and counts escape bytes, and nothing else in this repository can.

Plain writes no escape sequence, ever

HW-DR-0045 is explicit that the fallback is "no escape sequence at all", and NO_COLOR_TEXT (engine/crates/cli/src/lib.rs) promises the same thing to every caller of --no-color. So [paint] and [dim] write text back unchanged under [ColorMode::Plain].