TermBuf::WidthProbe
Stability: internal
Asks the terminal how wide it thinks a grapheme cluster is.
Every sample goes out followed by a cursor position report, and the column that comes back is the terminal's own measurement. One batch, one round trip, and the screen is cleared afterwards.
This cannot run with the capability probe. That one happens before the alternate screen is entered, and writing emoji onto the screen the person was looking at would scribble on their shell.
Constants
CURSOR_POSITION = /\A\e\[(\d+);(\d+)R\z/
DEFAULT_TIMEOUT = 250.milliseconds
Long enough for a terminal on the far end of a slow link, short enough not to be noticed when nothing answers.
SAMPLES = [Sample.new("a", nil, 1, 1, "latin small a"), Sample.new("漢", nil, 2, 2, "east asian wide"), Sample.new("→", "ambiguous_wide", 2, 1, "east asian ambiguous"), Sample.new("☺️", "emoji_presentation", 2, 1, "text pictograph with VS16"), Sample.new("👨\u200D👩\u200D👧\u200D👦", "joined_emoji", 2, 8, "four faces joined by ZWJ"), Sample.new("🇺🇸", "regional_indicators", 2, 4, "regional indicator pair"), Sample.new("🏋\u200D♀", "joined_emoji_wide", 2, 1, "joined sequence opening with a narrow pictograph"), Sample.new("நி", "spacing_marks", 2, 1, "tamil na with a spacing vowel sign"), Sample.new("क्ष", "conjunct_wide", 2, 1, "devanagari consonants joined by a virama"), Sample.new("क्षि", "conjunct_spacing_adds", 3, 2, "devanagari conjunct with a spacing vowel sign")]
Constructors
Class methods
run(input : IO, output : IO, base : Unicode::WidthPolicy = Unicode::WidthPolicy::DEFAULT, timeout : Time::Span = DEFAULT_TIMEOUT) : Result
Puts back whatever read deadline the stream had, and clears the samples off the screen.
Instance methods
probe(base : Unicode::WidthPolicy = Unicode::WidthPolicy::DEFAULT) : Result
Measures every sample and folds the answers into base.