Skip to main content

max / makeover-tui

3.1 KB · 74 lines History Blame Raw
1 # makeover-tui
2
3 The terminal renderer for
4 [`makeover-layout`]https://makenot.work/git/max/makeover-layout, on ratatui.
5
6 Named for the target and not for the library, the same way `makeover-immediate`
7 is named for the mode and not for egui.
8
9 ## What a terminal actually costs you
10
11 Not colour, on any terminal built this decade. Measured across the 31 shipped
12 themes
13 (`makeover`'s `well_fidelity` example):
14
15 | | ANSI-16 | ANSI-256 | truecolor |
16 |---|---|---|---|
17 | a well collapses onto its face | 18/31 | 4/31 | 2/31 |
18 | at least one bevel edge vanishes into its face | 31/31 | 4/31 | 0 |
19
20 The threshold is 256, not 24-bit. The two failures surviving at truecolor are
21 not terminal failures: they are the themes whose raised surface is already
22 white, so the lightening clamps and the well lands on its face. Those render
23 identically in a browser, and makeover already asserts them.
24
25 **What a terminal costs is geometry.** An edge occupies a whole cell per side,
26 and a cell is roughly 8x17 pixels, so a one-pixel bevel becomes an order of
27 magnitude heavier. `frame` returns a shrunk `Rect` rather than pretending the
28 region survived. There is nowhere to put a corner radius, so `radius_control`
29 and `radius_container` mean the same thing here. A fill begins and ends on a
30 cell boundary.
31
32 That is the constraint worth designing against. It does not improve, it is not
33 detectable, and it applies equally to the best terminal ever written.
34
35 ## Where fidelity matters
36
37 At `Fidelity::Ansi16` the depth vocabulary collapses: a well cannot be filled
38 distinctly on most themes *and* a bevel loses an edge on all of them, so a
39 raised card and a well both read as one single-tone box. Colour cannot carry
40 the distinction, so `frame` carries it with the glyphs, doubling the frame for
41 a raised surface and leaving a well light. Above sixteen colours that fallback
42 never fires, which is tested, because a doubled frame on every modern terminal
43 would be shouting.
44
45 `Fidelity::detect()` reads `COLORTERM` then `TERM` and is deliberately
46 credulous. A terminal that understates itself costs a slightly heavier frame; a
47 terminal that overstates itself was going to render wrongly whatever this crate
48 assumed.
49
50 `Palette::shows` is not a low-colour workaround. It is a correctness check that
51 a fill will be visible against what is behind it, and at truecolor it fires on
52 exactly the two clamping themes, which is when it should.
53
54 ## Substitution is renderer policy
55
56 Substituting one intent for another belongs to a renderer, never to the
57 description. Falling back from `Fill::Well` to `Page` is an answer for a
58 renderer that can always paint an exact colour; here it is wrong, because the
59 page is usually the surface a well is cut *into*, so the substitution produces
60 the invisibility it was meant to prevent. `makeover-immediate` wants that
61 fallback and this renderer does not.
62
63 ## Status
64
65 On crates.io. Intended first consumers are alloy_tui and shop, both of which
66 already take makeover and makeover-geometry from the registry.
67
68 Design lives in the wiki note `makeover-tui`; the backlog is in GoingsOn under
69 the project of the same name.
70
71 ## Licence
72
73 MIT.
74