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
//! The cell-aware word wrap shared by the transcript pane and the overlays.
//!
//! One wrapper, many consumers: the transcript flattens its blocks through
//! [`wrap_cells`], and the approval panel measures **and** paints its fact
//! body with the same rows — so what a panel counts is what it draws, and a
//! wide body can never be counted short of its paint (re-audit R01: three
//! wrappers is how that defect happened). The budgets that truncate instead
//! of wrap — the busy bar's action and its detail head, the folded chapter
//! summary — cut through [`truncate_cells`] and measure through
//! [`cell_width`], so no site rediscovers the units.
//!
//! The budget is measured in terminal cells (`unicode_width`), not scalar
//! values: `日` is one `char` but two cells, a combining mark is several
//! `char`s but no cell. Breaks land on grapheme boundaries
//! (`unicode_segmentation`), so a base never loses its accent and a ZWJ
//! emoji sequence is never cut in half. A single grapheme wider than the
//! whole budget is emitted alone and the loop advances — every iteration
//! consumes at least one grapheme, so wide and zero-width content cannot
//! spin. Control characters (`width() == None`) cost one cell, keeping the
//! pure-ASCII break points identical to a scalar-count loop.
use UnicodeSegmentation;
use UnicodeWidthStr;
/// Wraps one logical line to `width` display cells, preferring the last
/// whitespace inside the cell window so words are not split mid-word;
/// over-long single tokens still split (they have nowhere else to go). An
/// empty input yields one empty row — a blank logical line still paints.
pub
/// A string's cost in terminal cells — the unit every column budget in the
/// TUI is counted in. A `char` is not a cell (`日` is one char, two cells; a
/// combining mark is two chars, no cell), so a site that compares against a
/// `width` measures with this and never with `chars().count()`.
pub
/// Cuts `raw` to at most `width` display cells, on a grapheme boundary — the
/// single-line companion to [`wrap_cells`] for the budgets that truncate
/// rather than wrap. The cut stops before the grapheme that would exceed the
/// budget, so a base never loses its combining mark, a ZWJ sequence is never
/// split, and the result never overruns; a lone grapheme wider than the
/// whole budget yields an empty cut rather than an exception to that, and
/// the loop advances without spinning. An ellipsis the caller appends is the
/// caller's one cell to reserve out of `width`.
pub