Skip to content

Console

The console interface: where human-readable output goes.

Console is abstract. The implementations provided are the host console (term.console) and SinkConsole.

Subclassing

Do classes may subclass Console to implement one. Supply write and flush; put, the sink protocol, and the capability members come from the base:

Console can_style is_tty geometry()
Console (the base) false false nil
Host (term.console) styling policy usable terminal never nil
SinkConsole as constructed false nil
class Recorder: term.Console
  pub field lines

  def (init) self
    term.Console.(init) $self
    self.lines = []

  pub def write self *data
    let line = ""
    for piece = data
      line = "$line$piece"
    self.lines.push $line
    line.len

  pub def flush _self
    nil

let recorder = Recorder()
term.capture $recorder do echo hello
assert_eq $recorder.lines ["hello\n"]

Override line_ending to change what echo appends; the base reports "\n".

A console whose own methods call echo does not recurse: while a write is being dispatched, console output falls through to the host.

Constructor

Console()

Initializes the base console. A subclass calls this from its own (init).

Fields

can_style @ Bool

Whether the console supports ANSI styling.

is_tty @ Bool

Whether the console is usable as a terminal.

This is the determinative test, unlike geometry(), which may answer nil for a real terminal that simply cannot report its size.

The host console reports false while an extension such as progress has taken the terminal over, even though geometry() still reports the terminal's size.

line_ending @ (Str | Bin)

The line ending appropriate to this console's device.

The console owns the policy but does not apply it: echo passes this to write as the last piece of the line. It is read once, when the console is installed, so changing it afterward does not affect an installation already in effect.

term.console.write done $term.console.line_ending

Every built-in console reports "\n": a console is a terminal-shaped stream rather than a file, and echo writes LF on Windows too. A subclass may report something else, and echo will honor it. For a file's native ending use shell.line_ending instead.

Methods

(sink)()

Accepts values as a sink.

A value contributes exactly its own bytes; no terminator is added. Ask for one with precrimp:

pipeline output: (term.console.precrimp())
  do strand.from ["building", "linking"]

flush()

Makes buffered output visible.

geometry() -> (Geometry | nil)

Returns the console's dimensions, or nil if it is just a stream.

nil is advisory: it also covers a real terminal whose size could not be determined. Use is_tty to test for a real terminal regardless of whether a size is available.

The host console never returns nil here -- see Geometry for how rows and cols are each independently nil when unknown, rather than the whole result being absent.

Example

let g = term.console.geometry()
if g
  echo "terminal is $(g.cols)x$(g.rows)"

write *data -> Int

Writes bytes verbatim.

A caller that wants a terminated line passes the text and its terminator to one write rather than making two calls -- concurrent strands writing to the same console would otherwise interleave between the text and its terminator.

Parameters

NameTypeDescription
*data (Str | Bin) Pieces to write, in order.

Returns

The number of bytes written.

Example

term.console.write b"\x1b[2K" "\r"