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
//! 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.
//!
//! [`super::rows::SurfaceFailure`] carries argv + a stderr tail and nothing that
//! says *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 `lernie message` are told apart by
//! their argv, but `lernie prompt` / `lernie 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 ([`AppModel::last_failure`](crate::AppModel::last_failure)).
///
/// 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";