class TermBuf::Buffer

Overview

The in-memory terminal screen.

Two grids: back is what the application has drawn, front is what the terminal is believed to be showing. Every write lands in the back grid and marks damage; a paint diffs the two, and #commit_paint brings the front grid up to date once the bytes have gone out.

A single dirty-flag scheme would be smaller, but it leaves nothing to diff against after a forced repaint or a resize, and nothing for the scroll detector to verify a shift against.

Not fibre-safe, and deliberately so: one fibre owns the buffer and every mutation reaches it as a command.

Defined in:

termbuf/core/buffer.cr

Constructors

Instance Method Summary

Constructor Detail

def self.new(width : Int32, height : Int32) #

[View source]

Instance Method Detail

def back : Grid #

What the application has drawn.


[View source]
def bounds : Rect #

The rectangle covering every cell.


[View source]
def clear(style : Style = Style::DEFAULT) : Nil #

Blanks every cell.


[View source]
def clusters : ClusterPool #

The interned multi code point clusters, for cells a Char cannot hold.


[View source]
def commit_paint : Nil #

Brings the front grid up to date after a paint has been written out, and clears the damage and scroll hints it was built from.


[View source]
def damage : Damage #

What has changed since the last paint.


[View source]
def dirty? : Bool #

Whether anything has changed since the last paint.


[View source]
def fill(rect : Rect, char : Char = ' ', style : Style = Style::DEFAULT) : Nil #

Sets every cell of rect to char.


[View source]
def front : Grid #

What the terminal is believed to be showing.


[View source]
def height : Int32 #

Rows down.


[View source]
def invalidate : Nil #

Marks the whole screen dirty and forgets what the terminal was showing, so the next paint rewrites every cell.


[View source]
def painted? : Bool #

Whether the two grids agree, which is to say a paint would emit nothing.


[View source]
def policy : Unicode::WidthPolicy #

How clusters are measured. Set by the driver from what the terminal said when it was asked, because how many cells an emoji takes is a question about the terminal rather than about Unicode. See Unicode::WidthPolicy.

Changing it does not remeasure what is already written: cells carry the width they were placed with. Invalidate and redraw after changing it.


[View source]
def policy=(policy : Unicode::WidthPolicy) #

How clusters are measured. Set by the driver from what the terminal said when it was asked, because how many cells an emoji takes is a question about the terminal rather than about Unicode. See Unicode::WidthPolicy.

Changing it does not remeasure what is already written: cells carry the width they were placed with. Invalidate and redraw after changing it.


[View source]
def region(x : Int32, y : Int32, width : Int32, height : Int32, scrollback : Int32 = 0) : Region #

Registers a region. Regions are for scrolling and scrollback; they do not clip writes, and the buffer does not stop them overlapping.


[View source]
def region(bounds : Rect, scrollback : Int32 = 0) : Region #

Declares a region over bounds, keeping up to scrollback rows of what scrolls off the top.


[View source]
def regions : Array(Region) #

Regions declared with #region, in the order they were made.


[View source]
def resize(width : Int32, height : Int32, style : Style = Style::DEFAULT) : Nil #

Resizes both grids, keeping whatever content still fits anchored at the top left. Leaves everything dirty and drops any scroll hints, since the next paint has to redraw the screen outright.


[View source]
def scroll(rect : Rect, lines : Int32, style : Style = Style::DEFAULT) : Nil #

Scrolls rect by lines rows, positive moving content up. Records a hint for the painter.


[View source]
def scroll_hints : Array(ScrollHint) #

Scrolls performed since the last paint, oldest first.


[View source]
def scroll_region(region : Region, lines : Int32, style : Style = Style::DEFAULT) : Nil #

Scrolls a region, keeping the rows that leave the top if the region has scrollback capacity.


[View source]
def styles : StyleTable #

The interned styles both grids refer to by id.


[View source]
def take_scroll_hints : Array(ScrollHint) #

Takes the scroll hints recorded since the last paint, leaving none behind.


[View source]
def to_text : String #

The back grid as text, one line per row, for specs and debugging.


[View source]
def width : Int32 #

Columns across.


[View source]
def write(x : Int32, y : Int32, text : String, style : Style = Style::DEFAULT) : Int32 #

Writes text starting at (x, y), one grapheme cluster per cell, stopping at the right edge of the row. Returns the columns consumed.

Zero width clusters are skipped: a combining mark with no base character in front of it has nothing to attach to, and a control character is never stored in the buffer.


[View source]
def write_char(x : Int32, y : Int32, char : Char, style : Style = Style::DEFAULT) : Int32 #

Writes a single character at (x, y). Returns the columns it consumed: zero if it is zero width, if it is a control character, or if it is wide and the right edge is one column away.


[View source]