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
//! **What a machine's answer hides when it is folded** (bl-90d0).
//!
//! litany bounds a tool stream at 16 KiB head plus 16 KiB tail before it ever
//! reaches a transcript, so up to 32 KiB per call arrives here — and the pane
//! painted all of it. One `bash` running `ls -la && git log` filled the whole
//! pane and continued below it; one `bl --help` was six screens; a `find` over
//! a home tree arrived essentially whole. The call above each of them is one
//! compact line, which is what makes the asymmetry sharp: the question is a
//! line and its answer is six screens.
//!
//! **This is a projection, not a control.** The fold is a value computed from
//! the content — a few lines, and a sentence saying what is not being shown —
//! so what the pane paints folded is a thing a test reads back rather than a
//! screen somebody has to look at. Whether one particular row is OPEN is the
//! toolkit's own memory, keyed on the row (`super::render`), for the reason
//! bl-83ae's scroll anchor is: a per-row view state that no other fact can be
//! asked for and that no gesture on the wire corresponds to.
/// **How much of a machine's answer stands without being asked for.**
///
/// Two bounds rather than one, because a tool result overruns in two different
/// shapes and either alone lets the other through: a `git log` is six hundred
/// short lines, and a JSON blob is thirty kilobytes on ONE line, which a pane
/// that wraps paints as three hundred rows of glass.
const HEAD_LINES: usize = 6;
/// The other bound, in characters — see [`HEAD_LINES`].
const HEAD_CHARS: usize = 500;
/// **What a folded row shows, and the word on the control that unfolds it.**
/// **The fold for one machine answer, or `None` where there is nothing to
/// hide.**
///
/// A short result is not folded at all — an expander over four lines is a
/// control that costs a gesture and saves nothing, and the row it would wrap
/// is already the glance it is supposed to be.
/// The first [`HEAD_LINES`] lines, and at most [`HEAD_CHARS`] characters of
/// them. Cut on a character boundary, never a byte one.
/// **What the same control says once the row is open** — the act it fires,
/// which is the other one. Two words rather than one that toggles, on the
/// pin's own rule (`crate::ui::roster::wall`): a control names the act it
/// fires, so an operator never has to work out which way it will go.
pub const UNFOLD: &str = "fold";
/// **The word on the control while the row is folded**: the act, and the two
/// counts a reader is choosing between. The line count is what a scroll costs
/// and the byte count is what the wire carried, and neither derives the other
/// — forty identical paths and one long JSON object are the same kilobytes and
/// nothing like the same read.