class TermBuf::WidthProbe

Overview

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.

Defined in:

termbuf/caps/width_probe.cr

Constant Summary

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("நி", "spacing_marks", 2, 1, "tamil na with a spacing vowel sign")]

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(input : IO, output : IO, timeout : Time::Span = DEFAULT_TIMEOUT) #

[View source]

Class Method Detail

def self.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.


[View source]

Instance Method Detail

def probe(base : Unicode::WidthPolicy = Unicode::WidthPolicy::DEFAULT) : Result #

Measures every sample and folds the answers into base.


[View source]
def timeout : Time::Span #

How long to wait for the last answer before giving up on the batch.


[View source]