1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Which surface an attempted action came from (DESIGN §7.3, §11) — the one
//! fact the ops row lacked, and without which "the originating surface renders
//! the failure" was unhonorable.
//!
//! A row's exit and its stderr say what went wrong and nothing about *whose*
//! failure it is, so every banner surface asked the same global question ("did
//! the last op fail?") and a single start failure painted itself on all of them
//! at once (bl-48f8). The attribution is a fact of the **gesture**,
//! not of the row's bytes: `bl close` and `litany message` are told apart by
//! their argv, but `litany prompt` / `litany new` / `["yog-step","mkdir"]` are
//! written identically by a ball-rung start and by the composer's own Enter. So
//! origin is recorded once, where the op fires and the rung is known, and every
//! surface reads it back rather than re-deriving it from a shape that cannot say.
//!
//! It is the op's **subject**, not the pixel the pointer was over: one gesture
//! has one body however many hands reach it (`ball_bar::close_ball` is the
//! composer's button, the `c` key and the §11 row menu), and forking that body
//! per hand to record a pointer position would buy a distinction no operator
//! makes. A ball verb is about a ball wherever it was clicked.
/// The subject an attempted action acted on — the §7.3 attribution a banner
/// surface filters by, and the field it groups the answered rows standing
/// [`Live`](super::Standing::Live) under ([`super::standings`]).
///
/// Three, because yog has three kinds of subject and one banner surface each:
/// the roster's balls section paints [`Balls`](Self::Balls), the composer (the
/// empty world's bootstrap box being the same box with no workspace yet) paints
/// [`Conversation`](Self::Conversation), and [`World`](Self::World) is what the
/// config editors, the marks knob, the login pane and the delete dialog render
/// *themselves* — those surfaces already say their own errors, and routing them
/// through a banner on an unrelated surface is the bug this enum closes.
/// The token a line's `origin` field carries (§4.2) — short, stable, and the
/// only spelling; [`Origin::parse`] is its exact inverse.
const BALLS: &str = "balls";
const CONVERSATION: &str = "conversation";
const WORLD: &str = "world";