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
//! The selected-row gutter bar — one glyph, one width, one rule.
//!
//! User 2026-09-03: "why is there a space between the blue gutter here
//! and the a in auto-update, in other place we use gutter its right
//! next to the first char … what is standard or best practice and then
//! we should do that consistently."
//!
//! **The rule: no trailing space.** `▌` is U+258C LEFT HALF BLOCK — it
//! paints only the LEFT half of its cell, so the right half is already
//! background. The glyph carries its own optical gap. Adding a space
//! after it produces one and a half cells of air, which reads as the
//! bar having drifted away from the text it marks.
//!
//! This is not a majority-vote convention. Six of the eight call sites
//! already had it right; the two that appended a space (the picker and
//! the usage view) were the outliers, and they are what the user
//! noticed. Anything that needs MORE separation should widen the
//! content's own left pad, not pad the gutter — those are different
//! decisions and conflating them is how the two camps appeared.
//!
//! A row that is not selected paints [`BLANK`], never an empty string:
//! the column must be reserved on every row or the text jitters one
//! cell left and right as the cursor moves.
/// The bar itself. Left half-block, so it reads as a solid colour
/// column rather than the thin line `┃` gives.
pub const GLYPH: &str = "\u{258c}";
/// What an unselected row paints in the gutter column.
pub const BLANK: &str = " ";
/// Cells the gutter occupies. Always 1 — callers doing row-width
/// arithmetic should subtract this rather than a bare literal, so a
/// future change to the glyph cannot silently desync the budget from
/// the paint.
pub const WIDTH: u16 = 1;
/// The gutter cell for a row.
pub fn marker(selected: bool) -> &'static str {
if selected { GLYPH } else { BLANK }
}
#[cfg(test)]
mod tests {
use super::*;
/// The whole point of this module. If a trailing space ever comes
/// back, it comes back everywhere at once and this fails.
#[test]
fn the_gutter_carries_no_trailing_space() {
assert_eq!(GLYPH, "\u{258c}", "the glyph changed");
assert!(
!GLYPH.ends_with(' '),
"the gutter glyph regained a trailing space"
);
assert_eq!(
GLYPH.chars().count() as u16,
WIDTH,
"WIDTH disagrees with the glyph — row budgets will desync"
);
assert_eq!(
BLANK.chars().count() as u16,
WIDTH,
"an unselected row would not reserve the same column"
);
}
#[test]
fn selected_and_unselected_occupy_the_same_column() {
assert_eq!(marker(true).chars().count(), marker(false).chars().count());
}
}