Files
vamp/docs/diff-hatching-investigation.md
T

6.7 KiB
Raw Blame History

Diff hatching: two-column diagonal feasibility

Finding

Yes: Unicode has the exact two line segments needed. Repeat the following pair, in this order, with each character occupying one terminal column:

Position Character Code point Official Unicode name
Left cell 🯐 U+1FBD0 BOX DRAWINGS LIGHT DIAGONAL MIDDLE RIGHT TO LOWER LEFT
Right cell 🯑 U+1FBD1 BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO MIDDLE LEFT

These are listed under Character cell diagonals on page 6 of the official Unicode 17.0 Symbols for Legacy Computing chart; the exact names are also in UnicodeData.txt. They were introduced in Unicode 16.0 (1FBCB..1FBEF in DerivedAge.txt). The names specify endpoints, not a drawing direction: together they join the pair's bottom-left corner to the shared edge's midpoint, then to the pair's top-right corner.

Sample (glyphs may be missing or differently rendered in the Markdown viewer):

🯐🯑🯐🯑🯐🯑🯐🯑
🯐🯑🯐🯑🯐🯑🯐🯑

Equivalent escaped sequence: \u{1FBD0}\u{1FBD1}. This is two separate characters/cells, not one double-width character.

Geometry

For physical cell width W and height H, the ideal joined stroke has horizontal run 2W and vertical rise H, so its angle above horizontal is:

θ = atan(H / (2W))

This is 45° iff H = 2W. The current full-cell ╱ has ideal angle atan(H / W); at H = 2W, that is approximately 63.4°. Thus the pair is shallower, but the actual angle depends on the terminal's cell dimensions, including line spacing. These are geometric deductions from the chart's endpoints, not measured rendering results.

Do not substitute U+1FBA0–U+1FBAE: their centre/cell-edge endpoints describe different segments (see page 5 of the same chart). In particular, a side midpoint to top/bottom centre has run W/2 and rise H/2, preserving the full-cell diagonal's slope rather than halving it.

Line segments, not filled mosaics

U+1FBD0/U+1FBD1 are light box-drawing strokes. The chart separately labels U+1FB3C–U+1FB6F as Smooth mosaic terminal graphic characters: their BLOCK DIAGONAL names describe filled regions bounded by diagonals, not thin lines. For example, U+1FB48 is LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT and U+1FB42 is LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT (chart, pages 3–4, UnicodeData.txt). Those are not equivalent replacements for light hatching.

Support limits and current code

  • Unicode 16.0 repertoire support is a prerequisite; the existence of these characters does not establish coverage in the selected terminal/font. Missing glyphs or fallback glyphs remain possible, and fallback geometry must be checked in the intended renderer. Unicode explicitly says its chart glyph shapes are not prescriptive and actual fonts may vary (chart, page 1). Pixel-perfect joins or 45° rendering cannot be promised.
  • The pair has East Asian Width Neutral (N), from 1FB94..1FBEF in EastAsianWidth.txt. This is not a terminal-width guarantee: UAX #11, §2 and §4 explicitly requires terminal-specific tailoring and distinguishes font/layout width from the property. Both the application and terminal must agree on one column per glyph.
  • Rendering now alternates 🯐 and 🯑, starting at each pane's left content edge, with DarkGray foreground and reset background in src/tui.rs:3308–3316. The phase stays fixed during scrolling; odd widths clip the final pair. Actual empty source lines remain unhatched. See docs/editing.md:426.

Terminal support

  • Ghostty 1.3.1: The released drawing source explicitly implements both segments with the required endpoints. Ghostty's codepoint resolver normally selects procedural sprite rendering before ordinary font lookup, so this does not require font coverage; explicit codepoint font overrides take precedence.
  • Kitty: Current font dispatch routes this range to native box drawing, and drawing source explicitly implements the two segments. This establishes support in inspected upstream source, not a minimum released version.
  • The local environment reported Herdr 0.9.3; installed binaries reported Ghostty 1.3.1 and Kitty 0.45.0. Herdr runs inside an outer terminal, so its presence and these installations do not prove which renderer displays this session. Visual verification through the actual terminal/multiplexer remains necessary.

Recommendation: Use the two-character text tile if it looks correct in the target terminal. No image protocol or new dependency is needed. Older/other terminals may lack glyph coverage; exact 45° remains conditional on cell geometry.

Runtime evidence

An executed disposable rustc smoke program used the repository's actual compiled ratatui and unicode-width dependencies, a fixed viewport, Terminal<CrosstermBackend<Vec<u8>>>, and the same per-cell set_symbol/style logic as the current renderer. Both U+1FBD0 and U+1FBD1 returned width Some(1). At three rows high, widths 1, 2, 3, and 12 emitted exactly 3, 6, 9, and 36 glyphs respectively: no dropped or double-width cells. This establishes application-side width/emission behavior, not actual terminal glyph coverage, pixel joins, or the visible angle; those were not visually verified. The disposable program and binary were removed.

Implemented with no new dependency or graphics protocol. Verification: cargo test diff_ (94 passing checks), cargo build, and cargo fmt --package vamp --check. A live PTY session opened :diff against a disposable jj baseline with two removed rows and emitted paired hatching at 100, 101, and 77 terminal columns; no U+2571 was emitted, the editor exited cleanly, and fixture content stayed unchanged. The fixture was removed. Terminal pixel joins remain visually unverified. The TODO item is complete.