Skip to content

State & Lines

Two small contracts the rest of the API leans on: rune.state exposes live client state to renderers like bars and layout code, and line objects are what hook and trigger handlers receive for server output.

rune.state.connected -- bool, connection status
rune.state.address -- server address, scheme included
rune.state.scroll_mode -- "live" or "scrolled"
rune.state.scroll_lines -- new lines arrived while scrolled
rune.state.search_active -- true while scrollback search captures input
rune.state.width -- terminal width
rune.state.height -- terminal height
rune.line.new(text) -- build a line object from plain text
line:raw() -- the line with ANSI codes intact
line:clean() -- the line with ANSI codes stripped

A read-only proxy over live, client-owned state — reads always reflect the current values, and writing any field raises an error.

Field Type Description
connected bool Whether a connection is up
address string The connected address, scheme included (e.g. tls://mud.example.com:4000)
scroll_mode string "live", or "scrolled" while scrolled back
scroll_lines number New lines received while scrolled
search_active boolean Whether the scrollback-search navigator is active
width number Terminal width in columns
height number Terminal height in rows

To react to resizes rather than poll, register a window_size_changed hook; it fires with the new width and height after these fields update.

Because it’s always current, rune.state is the natural input for bar renderers:

rune.ui.bar("status", function(width)
local s = rune.state
local left = s.connected
and rune.style.green("") .. " " .. s.address
or rune.style.gray("● Disconnected")
return { left = left }
end)

Server output arrives in handlers as line objects, not plain strings: "output" and "prompt" hook handlers receive one, and trigger function actions get one as ctx.line. Two methods:

line:raw() -- ANSI codes included; use when re-emitting styled text
line:clean() -- ANSI stripped; use when matching or parsing

:clean() is computed lazily and cached, so calling it repeatedly is cheap.

rune.line.new(text) -> line
  • text (string) — the raw text, ANSI codes and all.

Builds a line object compatible with what handlers receive. You rarely need this — the main use is constructing a rewritten line to pass along, or feeding synthetic lines through code that expects the line contract:

local l = rune.line.new("\027[31malert\027[0m")
rune.echo(l:clean()) -- "alert"

Related: Hooks guide · rune.trigger · rune.ui · Core