class TermBuf::Encoder

Overview

Turns paint operations into terminal bytes, as few of them as it can.

The encoder carries the state the terminal has: where the cursor is and what style is in force. That is what lets it drop a MoveTo that is already true, pick the shortest of the half-dozen ways to move the cursor a few columns, and emit an SGR delta instead of a reset plus everything.

It also holds the capability mask, and is the only place a style is narrowed to what the terminal can actually render. Colours are downgraded here rather than at write time, so the buffer keeps full fidelity and a later repaint against a wider mask comes out better.

Defined in:

termbuf/core/encoder.cr

Constant Summary

CSI = "\e["
RESETS = { {Attributes::Italic, "23"}, {Attributes::Reverse, "27"}, {Attributes::Conceal, "28"}, {Attributes::Strike, "29"}, {Attributes::Overline, "55"} }

Attributes with a reset of their own.

SHARED_RESETS = { {Attributes::Bold | Attributes::Faint, "22"}, {Attributes::SlowBlink | Attributes::RapidBlink, "25"}, {Attributes::Superscript | Attributes::Subscript, "75"} }

Attributes that share a reset with a sibling: turning one off turns the whole group off, so any member that should survive has to be reasserted.

Constructors

Instance Method Summary

Constructor Detail

def self.new(styles : StyleTable, capabilities : Capabilities, width : Int32, height : Int32) #

[View source]

Instance Method Detail

def capabilities : Capabilities #

What the terminal can do. Colours and attributes outside this are downgraded or dropped rather than emitted.


[View source]
def capabilities=(capabilities : Capabilities) : Capabilities #

Replaces the capability mask, discarding the style cache built under the old one.


[View source]
def cursor_x : Int32 | Nil #

Where the terminal's cursor is, or nil when it is not known and the next move has to be absolute.


[View source]
def cursor_y : Int32 | Nil #

Where the terminal's cursor is, or nil when it is not known and the next move has to be absolute.


[View source]
def effective(id : StyleId) : Style #

The style as this terminal can actually render it: unsupported attributes dropped, colours narrowed to the deepest supported space.


[View source]
def encode(ops : Array(Op), io : IO) : Nil #

Encodes ops straight to io.


[View source]
def encode(ops : Array(Op)) : String #

Encodes ops and returns the bytes.


[View source]
def move_to(x : Int32, y : Int32, io : IO) : Nil #

Emits the shortest sequence that puts the cursor at (x, y).


[View source]
def reset_state : Nil #

Forgets what the terminal was showing. The next operation re-establishes the cursor and the style from scratch, which is what a forced repaint needs.


[View source]
def resize(width : Int32, height : Int32) : Nil #

Tells the encoder the screen changed size, and forgets where the cursor was.


[View source]
def set_style(id : StyleId, io : IO) : Nil #

Emits whatever SGR takes the terminal from the style it is in to id, after capabilities have had their say. Nothing at all when they match.


[View source]