class

Scroll::AltRenderer

Inherits Reference < Object

Draws the tail on the terminal's alternate screen buffer. Unlike Renderer, which repaints N rows every frame, this appends complete lines and lets the terminal do the scrolling, which is what makes it keep up with a much faster stream. The whole screen is used: -N bounds the inline display, not this one.

A scrolling region (DECSTBM) is set only with --progress, to hold the bottom row back for the progress line; without it the screen scrolls naturally. On exit the alt screen is torn down and the original screen and scrollback are restored untouched — --leave then echoes the last -N lines onto the main screen, so the run leaves a tail behind.

STDOUT is never touched by any of this; the display lives entirely on the STDERR IO handed to the constructor.

Constants

CLEAR_EOL = "\e[K"
CLEAR_HOME = "\e[2J\e[H"
ENTER_ALT = "\e[?1049h"
HIDE_CURSOR = "\e[?25l"
LEAVE_ALT = "\e[?1049l"
LOAD_CURSOR = "\e8"
NEWLINE = '\n'.ord.to_u8
RESET_REGION = "\e[r"
SAVE_CURSOR = "\e7"
SHOW_CURSOR = "\e[?25h"

Constructors

new(io : IO, sanitize : Bool = true, progress : Bool = false, leave_lines : Int32 | Nil = nil, size : Tuple(Int32, Int32) | Nil = nil)

size overrides the terminal size query (rows, cols); it exists so specs can drive the renderer against an IO::Memory, which has no fd. In normal use it is nil and the size is read from the terminal on start and on every resize. leave_lines is how many lines --leave echoes onto the main screen on the way out; nil leaves nothing behind.

Source

Class methods

restore(io : IO) : Nil

Show the cursor, reset any scroll region, and leave the alt screen. Safe to call from an at_exit hook even if start never ran: \e[?1049l is a no-op when the alt screen was never entered, and \e[r a no-op with no region.

Source

Instance methods

draw_progress(text : String) : Nil

Paint the progress line on the bottom screen row, outside the scrolling band, and put the cursor back where the band left it.

Source
feed(bytes : Bytes, start : Int64) : Nil

Feed a chunk of raw bytes that begins at byte start in the stream. Splits into complete lines exactly as Tail#feed does: a gap (dropped chunk) skips the interrupted line's tail up to the next newline; the trailing partial is buffered until its newline arrives.

Source
finish(final : Bool) : Nil

On EOF: optionally promote a trailing newline-less line, drain the buffer, then tear down the alt screen. Under --leave the last -N lines are echoed onto the restored main screen; otherwise the run vanishes completely, like less.

Source
flush

Write the pending lines, letting the terminal scroll. Re-applies the region first if a resize was signalled. The pending buffer is capped to the screen height: scrolling through more than one screenful between frames is pointless, since the earlier lines would instantly scroll off.

Lines are separated by CRLF rather than terminated by one. A terminating newline scrolls the last line up and leaves the cursor on a blank row, so under a fast stream the bottom row alternates between blank and filled once a frame, which reads as a flicker. Separating instead leaves the newest line sitting on that row until the next one pushes it up.

Source
notify_resize

Flag a terminal resize. Called from the SIGWINCH trap; it only flips the atomic so the render fiber re-applies the region on its next flush — no escapes are written from the signal handler.

Source
start

Enter the alt screen and hide the cursor. With a progress line, a DECSTBM band covers every row but the last and the cursor parks at its bottom, so appended lines scroll within it and the bar below stays put.

Source
width

Columns a row may use.

Source