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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
//! The session: a diagram being edited, the steps behind and ahead of it, and how far along them
//! it stands. See the _Vocabulary_ rows for `Session` and for `Position`, and §4 and §6 of
//! [`docs/editing-model.md`](../../../docs/editing-model.md).
use ;
use VectorSync;
use cratekept_first;
use crate::;
/// A diagram being edited, the steps behind and ahead of it, and a position among them.
///
/// **Nothing here changes a session, and the type system says so rather than a rule this file
/// keeps.** No method takes `&mut self`: every one of them is asked over `&self` and hands a new
/// [`Session`] back, so a caller that forgets to keep what it was given changes nothing, and a
/// caller that keeps it still cannot have changed this one. **The guarantee §4 of the model makes —
/// the diagram a session owns is changed through the session and nowhere else — is what the absence
/// of a `&mut self` anywhere in this surface means**, and it is a stronger answer than the one a
/// private field was: nothing in this crate can break it, because there is no borrow that would let
/// it. **The price is that a caller has to keep what it is given**: discarding the result of
/// [`perform`](Session::perform) changes nothing at all, which is a warning rather than a failure.
/// The field below is written once on top of that: a command changes the diagram by way of the
/// steps, never by way of the field.
///
/// **The field holds the diagram the session was created over, and the steps hold every state after
/// it.** A step is the diagram a command *left*, so the state before the first command is the one
/// state no step holds, and it is the field — which is why nothing writes the field again, and why
/// the diagram in hand is either that field or a step and never anything else. One diagram per step
/// and one to start with, which is the model's "memory proportional to the diagram times the number
/// of steps", and each of them held once.
///
/// **What a session is made of is shareable, and the sharing is what pays for the copies.** Two
/// sessions standing at different positions in one history hold the same `VectorSync<Step>` and the
/// same `Diagram`s, and a new one costs a new position and at most a new leaf. Nothing in the layer
/// needs two sessions at once today — the demonstration walks one — but this is the property a
/// caller gets for free the first time one does, and it is why the steps are a persistent sequence
/// and not a `Vec`.
///
/// **Giving a step back moves the position and changes nothing else.** [`undo`](Session::undo) and
/// [`redo`](Session::redo) are one expression each for that reason, and neither removes a step or
/// rebuilds a diagram: the state that comes back is the state that was there, held since the command
/// that made it. Nothing is inverted, and every step stays where it is while the history walks over
/// them, which is what makes the walk go both ways.
///
/// **The history is a line, and `position` is where in it the session stands.** It is how many
/// steps are behind rather than an index into a pair of stacks, so it cannot disagree with either
/// of them: there is something behind exactly when `position` is above zero, and something ahead
/// exactly when it is below `steps.len()`. A command carried out from behind the end discards what
/// was ahead, which is the only end a line can discard from without changing what giving a step
/// back means.
///
/// **A command that changes nothing records nothing and discards nothing** (#285): the session
/// comes back as it was, so a branch is only ever cut by a command that moved the drawing.
///
/// **The steps are held in the same persistent sequence the diagram holds its figures in**, so a
/// session standing at one place in a history shares every step with one standing at another
/// rather than copying them — and a step is a whole diagram beside a command, which is what makes
/// the difference between sharing and copying the difference between 949 B and 40 122 B per step.
/// That sequence has no truncation, so what was ahead is dropped by a walk of `drop_last_mut`
/// rather than in one step: each of those is a trie descent where a `Vec` was one, and it is paid
/// only on the branch that carries a command out from behind the end. See `kept_first`, which is
/// where that walk is written and tested.
///
/// # The absence, shown rather than described
///
/// The rule that nothing here changes a session is held by nothing in this file, so it
/// is worth one documentation example that says it out loud: everything up to the last line compiles, and the
/// last line is a method this crate does not have.
///
/// ```compile_fail
/// use monospace_core::{Buffer, Pos, Size, Window};
/// use monospace_diagram::Diagram;
/// use monospace_editing::Session;
///
/// let session = Session::new(Diagram::new());
/// session.diagram().draw(&mut Buffer::new(Window {
/// origin: Pos { x: 0, y: 0 },
/// size: Size { width: 1, height: 1 },
/// }));
///
/// session.diagram_mut();
/// ```