max / quasi
| 1 | //! What a renderer is, for the one question where the three differ. |
| 2 | //! |
| 3 | //! <!-- wiki: quasi-overview --> |
| 4 | //! |
| 5 | //! The renderers share no trait and looking for one is the wrong move, which |
| 6 | //! this crate's header already says. This is not that: it is a single fact |
| 7 | //! about a renderer that a *description* has no way to ask and that the |
| 8 | //! [`Destination::Local`](crate::Destination::Local) mark needs an answer to. |
| 9 | |
| 10 | /// Whether a renderer has to be told what is local. |
| 11 | /// |
| 12 | /// [`Destination::Local`](crate::Destination::Local). |
| 13 | /// |
| 14 | /// ```text |
| 15 | /// Client -> quasi-immediate (egui), quasi-tui may ignore the mark |
| 16 | /// Hybrid -> quasi-webview must read it |
| 17 | /// ``` |
| 18 | /// |
| 19 | /// # Why classify at all, rather than let each renderer ignore what it likes |
| 20 | /// |
| 21 | /// A client app has no real need to model the two differently, especially an |
| 22 | /// immediate-mode one. Every frame redraws from memory, so arrow keys moving a |
| 23 | /// highlight is not a special kind of thing there — it is what a list does. The |
| 24 | /// split exists because a browser has no built-in stateful control, so someone |
| 25 | /// has to say whether a keystroke goes to the server. |
| 26 | /// |
| 27 | /// Two of three renderers can therefore skip the whole area, and the choice was |
| 28 | /// between saying why and leaving it to convention. Convention erodes: the next |
| 29 | /// person to read `quasi-tui` and find no handling for a mark the vocabulary |
| 30 | /// carries reads it as an omission and fixes it, and the fix is a distinction |
| 31 | /// that means nothing in a terminal. Naming the class states the reason in the |
| 32 | /// one place both renderers can point at. |
| 33 | /// |
| 34 | /// Rejected: every renderer models the split — uniform, and egui and the TUI |
| 35 | /// carry a distinction that means nothing to them. Rejected: local interaction |
| 36 | /// is browser-only with the others degrading — cheapest, and audiofiles is a |
| 37 | /// live egui consumer, so the loss would be real rather than hypothetical. |
| 38 | /// |
| 39 | /// # What this is not |
| 40 | /// |
| 41 | /// Not a capability list and not a feature flag. It answers one question and |
| 42 | /// gaining a second variant is a sign something else is being smuggled in. |
| 43 | /// Whether a terminal can open a browser, whether a host can upload — those are |
| 44 | /// [`Destination::External`](crate::Destination::External) and |
| 45 | /// [`Action::by_host`](crate::Action::by_host), which say their piece on the |
| 46 | /// action rather than about the renderer. |
| 47 | |
| 48 | |
| 49 | /// Everything is local by construction: the renderer holds the state it |
| 50 | /// draws and redraws it from memory. |
| 51 | /// |
| 52 | /// A local action is something such a renderer already performs natively — |
| 53 | /// moving a highlight, closing a notice — so the mark tells it nothing it |
| 54 | /// did not know. It is free to ignore it, and the vocabulary promises it |
| 55 | /// loses nothing by doing so. |
| 56 | /// |
| 57 | /// What it may not do is dispatch one. There is no route on a local |
| 58 | /// destination, so [`Destination::route`](crate::Destination::route) |
| 59 | /// answers `None` and the renderer's own dispatch already declines; that is |
| 60 | /// the floor, and it holds without any code being written against this |
| 61 | /// type. |
| 62 | Client, |
| 63 | |
| 64 | /// The split is real and must be honoured. |
| 65 | /// |
| 66 | /// A hybrid renderer emits markup that some other runtime performs later, |
| 67 | /// so it has to decide at emit time whether a keystroke becomes a request. |
| 68 | /// Getting that wrong is not a slower screen, it is a route asked on every |
| 69 | /// arrow key. |
| 70 | Hybrid, |
| 71 | |
| 72 | |
| 73 | |
| 74 | /// Whether this renderer has to read the locality mark. |
| 75 | |
| 76 | pub const |
| 77 | matches! |
| 78 | |
| 79 | |
| 80 |