class TermBuf::SgrScanner

Overview

Reads the escape sequences an application writes to a cursor and turns the ones about appearance into Style changes.

This is what makes io.print "\e[1mbold\e[0m" set the bold attribute on cells rather than putting escape bytes into them. A cursor marked raw skips it, which is the whole point of that flag: an application that changes style by assigning to Cursor#style pays nothing for a scan that would find nothing.

Sequences that say something a cell cannot hold — cursor movement, screen clearing, anything addressing the terminal rather than the text — are consumed and dropped. Honouring them would mean a second, competing idea of where the cursor is, and the buffer already has one.

The parser is separate from the encoder's SGR writer on purpose. They are each other's inverse, and a spec that ran text through both would pass on a pair of matching mistakes.

Defined in:

termbuf/sgr_scanner.cr

Constant Summary

ATTRIBUTES = {1 => Attributes::Bold, 2 => Attributes::Faint, 3 => Attributes::Italic, 5 => Attributes::SlowBlink, 6 => Attributes::RapidBlink, 7 => Attributes::Reverse, 8 => Attributes::Conceal, 9 => Attributes::Strike, 53 => Attributes::Overline, 73 => Attributes::Superscript, 74 => Attributes::Subscript}

The attributes, by the code that sets and the code that clears each.

CLEARS = {22 => Attributes::Bold | Attributes::Faint, 23 => Attributes::Italic, 25 => Attributes::SlowBlink | Attributes::RapidBlink, 27 => Attributes::Reverse, 28 => Attributes::Conceal, 29 => Attributes::Strike, 55 => Attributes::Overline, 75 => Attributes::Superscript | Attributes::Subscript}

A clearing code often undoes more than one attribute: 22 covers both weights, 25 both blink rates, and 75 both scripts.

Constructors

Instance Method Summary

Constructor Detail

def self.new #

[View source]

Instance Method Detail

def clear : Nil #

Drops anything held back. For a cursor being pointed at something else, where half a sequence from the old text has no business colouring the new.


[View source]
def pending? : Bool #

Whether an incomplete sequence is being held back.


[View source]
def scan(bytes : Bytes, style : Style, &emit : String, Style -> ) : Style #

Feeds bytes in, yielding each run of printable text with the style in force at the time. Returns the style left in force afterwards.

Bytes that do not yet form a complete sequence are held until the rest of them arrives, so an application is free to write an escape sequence in as many pieces as it likes.


[View source]