moon_tui.ansi
Returns the escape sequence that enters the alternate screen.
Returns the escape sequence that leaves the alternate screen.
Returns the escape sequence that hides the cursor.
Returns the escape sequence that shows the cursor.
Returns the escape sequence that enables bracketed paste.
Returns the escape sequence that disables bracketed paste.
Returns the escape sequence that enables focus events.
Returns the escape sequence that disables focus events.
Returns the escape sequence that enables mouse events.
Returns the escape sequence that disables mouse events.
Returns the escape sequence that clears the screen.
Returns the escape sequence that saves the cursor.
Returns the escape sequence that restores the cursor.
Returns the escape sequence that moves the cursor.
position: Cell to move the cursor to.
Encodes a complete style from reset. Runs share styles, so this is emitted once per changed run rather than once per cell.
value: Style to encode from a reset.
Encoded terminal output and its final cursor position.
bytes: string | The escape sequence and text to write. |
|---|---|
changed_cells: int | How many cells the encoding redraws. |
cursor_y: int | Row the cursor ends on, for the next relative move. |
Encodes one desired frame in the portable xterm subset. Application text is already sanitized into cells; this module is the package's sole escape producer.
previous: What the terminal is believed to be showing.next: What it should show.before_cursor: Cursor state of the presented frame.after_cursor: Cursor state the new frame asks for.origin: Absolute cell the grid is placed at.force: True to emit every cell rather than only the changes.
Inline viewports use relative row movement from the presenter's own last known position, avoiding cursor-position queries and absolute row guesses.
previous: What the terminal is believed to be showing.next: What it should show.before_cursor: Cursor state of the presented frame.after_cursor: Cursor state the new frame asks for.origin: Absolute cell the grid is placed at.force: True to emit every cell rather than only the changes.relative: True to move by relative rows instead of absolute ones.last_y: Row the presenter last left the cursor on.
moon_tui.buffer
Dense row-major cell grid. The backing array is reused by reset/resize.
size: Size | Grid extent in cells. |
|---|---|
cells: [Cell] | The grid itself, row-major. |
epochs: [int] | Per-cell generation stamps, so a reset costs no clearing pass. |
active: [int] | Indices touched since the last reset. |
diff_epochs: [int] | Per-cell stamps for the diff pass, kept apart from |
state: *BufferState | The generation counters shared by every value-copy of this handle. |
Scalar generations shared by every value-copy of a Buffer handle.
generation: int | Bumped by each reset, retiring every |
|---|---|
diff_generation: int | The same trick for the diff pass. |
Creates a new value with the supplied configuration.
size: Grid extent to allocate.
Returns the buffer bounds.
Returns the linear buffer index for a coordinate.
x: Column, counting from zero.y: Row, counting from zero.
Returns the cell at a coordinate, or a blank cell when out of bounds.
x: Column, counting from zero.y: Row, counting from zero.
Resets the value to its initial state.
Resizes the target while preserving valid content.
size: New extent; content inside both extents is preserved.
Writes a grapheme head and continuation cells when it fits.
x: Column of the head cell.y: Row of the head cell.grapheme: Text to write.span: Display columns it occupies; a span that overruns the row is refused.value: Style the written cells carry.
Writes a clipped printable-ASCII slice into one row with one bounds calculation and one shared mutation setup.
x: Column the slice starts at.y: Row to write into.text: Printable-ASCII source text.start: First byte index of the slice.end: One past the last byte index of the slice.value: Style the written cells carry.
Fills the target area.
area: Region to fill, clipped to the buffer.grapheme: Text written into every cell.value: Style the written cells carry.
Applies a style patch to the target area.
area: Region to restyle, clipped to the buffer.delta: The partial update laid over each cell.
moon_tui.cell
One dense grid cell. Wide heads have span=2; their following cell has continuation=true and span=0.
grapheme: string | The text this cell draws; empty for a blank or a continuation. |
|---|---|
style: Style | Foreground, background, and attributes for the cell. |
span: int | Display columns the grapheme occupies: 1 normally, 2 for a wide head, 0 for a continuation. |
continuation: bool | Whether this cell is the second half of a wide grapheme. |
Creates a blank terminal cell.
Creates a blank cell with the supplied style.
value: Style the blank cell carries.
Creates the head cell for a grapheme of the supplied display span.
grapheme: Text the cell draws.value: Style the cell carries.span: Display columns it occupies; 2 makes the next cell a continuation.
Creates a wide-cell continuation marker.
value: Style the continuation cell carries, matching its head.
moon_tui.clock
Runtime clock seam. Production uses host monotonic time and real sleeping; tests inject a reference-backed fake with no wall-clock delay.
now_ms: fn() -> int | Reads monotonic milliseconds. |
|---|---|
sleep_ms: fn(int) -> void | Waits the requested milliseconds. |
Deterministic clock handle for runtime tests.
clock: Clock | The seam to hand to code under test. |
|---|---|
state: *FakeClockState | The time and sleep log the seam reads and writes. |
Shared mutable time and sleep counters for a fake clock.
now: int | Current fake time in milliseconds. |
|---|---|
sleeps: [int] | Every sleep the code under test asked for, in order. |
Returns the system implementation.
Creates a deterministic fake implementation.
start_ms: Time the fake clock starts at.
moon_tui.decoder
Bounded incremental VT decoder. The constructor returns one managed stream; copied pointers share it while separate decoders remain independent.
pending: string | Bytes held back because they do not yet form a complete sequence. |
|---|---|
paste: string | Bracketed-paste text accumulated so far. |
in_paste: bool | Whether a bracketed paste is currently open. |
escape_deadline: int | Monotonic time a lone Escape resolves at. |
max_pending: int | Byte ceiling on |
max_paste: int | Byte ceiling on one paste. |
escape_timeout_ms: int | How long a lone Escape waits for a continuation. |
Creates a new value with the supplied configuration.
max_pending: Byte ceiling on held-back input.max_paste: Byte ceiling on one paste.escape_timeout_ms: How long a lone Escape waits for a continuation.
use moon_tui.decoder
use moon_tui.event.{Event, KeyCode}
fn main() {
let escape = std.strings.from_code(27)
let input = decoder.new(max_pending: 4096, max_paste: 1024, escape_timeout_ms: 25)
for event in input.push(escape + "[A", 0) {
match event {
Event.Key(key) => match key.code {
KeyCode.Up => println("up"),
_ => {},
},
_ => {},
}
}
println(input.flush_deadlines(25))
}Pushes a byte chunk and returns all complete typed events. A trailing Escape remains pending until another byte arrives or its deadline fires.
chunk: Bytes just read from the terminal.now_ms: Current monotonic time, which arms the Escape deadline.
Resolves a pending bare Escape once its injected monotonic deadline is due. It never sleeps and is deterministic under a fake clock.
now_ms: Current monotonic time; a due Escape resolves to a key event.
moon_tui.diff
One adjacent row segment whose desired cells share a style.
y: int | Row the run sits on. |
|---|---|
start: int | First column of the run. |
end: int | One past the last column of the run. |
style: Style | Style every cell in the run shares. |
Finds changed, style-coalesced row runs. Continuation cells remain in the run extent so a wide-to-narrow replacement clears both physical columns.
previous: What the terminal is believed to be showing.next: What it should show.force: True to emit every cell rather than only the changes.
moon_tui.driver
Terminal feature flags supported by a backend.
vt: bool | Whether the terminal understands VT escape sequences at all. |
|---|---|
true_color: bool | Whether 24-bit colour is supported. |
mouse_sgr: bool | Whether SGR-encoded mouse reporting is supported. |
bracketed_paste: bool | Whether bracketed paste is supported. |
focus_reporting: bool | Whether focus in/out events are reported. |
Returns the conservative terminal capabilities.
Enumerates the supported ReadResult cases.
Data(string) | Bytes that were available. |
|---|---|
WouldBlock | Nothing was available; try again later. |
Eof | The input stream ended. |
Failure(string) | The read failed, with the reason. |
Injected terminal backend. Closures capture reference-backed driver state; there is no package-global handle or saved-mode storage.
is_terminal: fn() -> bool | Whether the backend is attached to a real terminal. |
|---|---|
open: fn() -> bool | Enters raw mode and claims the terminal; false on failure. |
close: fn() -> void | Restores the modes |
size: fn() -> Size | Reads the current terminal extent. |
read: fn() -> ReadResult | Takes whatever input is available without blocking. |
write_all: fn(string) -> bool | Writes one whole transaction; false means the write failed. |
flush: fn() -> bool | Pushes buffered output out; false means the flush failed. |
capabilities: Capabilities | What this backend reports it can do. |
Shared mutable queues and counters for a fake terminal driver.
opened: bool | Whether |
|---|---|
close_calls: int | How many times |
write_calls: int | How many times |
flush_calls: int | How many times |
terminal: bool | What |
fail_open: bool | Whether the next |
fail_flush: bool | Whether the next |
fail_after_bytes: int | Byte budget after which the next write fails; negative disables it. |
size: Size | What |
reads: [ReadResult] | Queued read results, taken in order. |
writes: [string] | Everything written so far, in order. |
Creates a deterministic fake implementation.
size: Extent the fake terminal reports.
use moon_tui.driver
use moon_tui.geometry
use moon_tui.style
use moon_tui.terminal
fn main() {
let backend = driver.fake(geometry.size(20, 4))
let term = terminal.open_with(terminal.options(), backend.driver).unwrap()
let frame = term.begin_frame()
frame.root().write_text(0, 0, "moon", style.plain())
term.present()
println(backend.output())
backend.push_read(driver.ReadResult.Data("q"))
println(term.poll(0).unwrap())
term.close()
println(backend.close_count())
}Reports whether the fake terminal backend remains open.
Returns how many times the fake driver was closed.
Records whether terminal mode is enabled.
enabled: Whatis_terminalshould answer.
Makes the fake driver fail its next write after a byte limit.
bytes: Byte budget the next write fails past.
Queues a read result in the fake driver.
result: Read result to queue behind the ones already there.
Returns output captured by the fake driver.
moon_tui.driver_posix
Returns the platform terminal driver.
moon_tui.driver_win
Returns the platform terminal driver.
moon_tui.event
Modifier mask bit for Shift.
Modifier mask bit for Alt.
Modifier mask bit for Control.
Modifier mask bit for Super/Command.
Enumerates the supported KeyCode cases.
Char(string) | A printable grapheme the terminal delivered. |
|---|---|
Enter | The return key. |
Escape | The escape key. |
Backspace | The backspace key. |
Tab | The tab key. |
Up | The up arrow. |
Down | The down arrow. |
Left | The left arrow. |
Right | The right arrow. |
Home | The home key. |
End | The end key. |
PageUp | The page-up key. |
PageDown | The page-down key. |
Insert | The insert key. |
Delete | The forward-delete key. |
Function(int) | A function key, by its number. |
Decoded key code and modifier mask.
code: KeyCode | Which key was pressed. |
|---|---|
modifiers: int | Modifier bits held at the time, OR-ed together. |
Enumerates the supported MouseKind cases.
Down | A button was pressed. |
|---|---|
Up | A button was released. |
Move | The pointer moved. |
ScrollUp | The wheel turned up. |
ScrollDown | The wheel turned down. |
Decoded mouse action, button, modifiers, and cell position.
kind: MouseKind | What the mouse did. |
|---|---|
button: int | Button index for a press or release; 0 otherwise. |
x: int | Column of the pointer, counting from zero. |
y: int | Row of the pointer, counting from zero. |
modifiers: int | Modifier bits held at the time, OR-ed together. |
Enumerates the supported Event cases.
Key(Key) | A key press, with its modifiers. |
|---|---|
Mouse(Mouse) | A mouse action, with its position. |
Paste(string) | Bracketed-paste text, delivered whole. |
Focus(bool) | The terminal window gained (true) or lost (false) focus. |
Resize(Size) | The terminal was resized to this extent. |
Unknown(string) | A sequence the decoder did not recognise, kept verbatim. |
Creates a keyboard event.
code: Which key was pressed.modifiers: Modifier bits held at the time.
moon_tui.focus
Optional app-owned focus order. Rendering reads the current id but never mutates it; applications call next/previous/focus from their update step.
ids: [string] | The focus order, as the application declared it. |
|---|---|
index: int | Position of the focused id within |
Creates a new value with the supplied configuration.
ids: Widget identifiers in focus order.
use moon_tui.focus
fn main() {
let ring = focus.new(["search", "results", "footer"])
println(ring.current())
println(ring.next())
println(ring.previous())
println(ring.focus("footer"))
println(ring.contains("search"))
}Returns the currently focused identifier.
Reports whether the requested value is present.
id: Identifier to look for.
Moves focus to the requested identifier when present.
id: Identifier to move focus to; an unknown one leaves focus alone.
Moves to and returns the next item.
Moves to and returns the previous item.
moon_tui.frame
Enumerates the supported CursorShape cases.
Block | A full-cell block. |
|---|---|
Underline | A line under the cell. |
Bar | A vertical bar at the left of the cell. |
Requested cursor visibility, position, and shape for a frame.
visible: bool | Whether the cursor is shown this frame. |
|---|---|
position: Position | Where the cursor sits, in screen cells. |
shape: CursorShape | How the terminal draws it. |
A frame is a complete desired grid plus declarative cursor state.
buffer: Buffer | The dense grid this frame draws into. |
|---|---|
area: Rect | The whole drawable region of the frame. |
cursor: *CursorRequest | Cursor request for the frame, owned by the screen. |
width_policy: WidthPolicy | How grapheme display widths are measured. |
A translating, clipped view over the frame's shared dense buffer.
buffer: Buffer | The frame's grid, shared with every other window over it. |
|---|---|
origin: Position | Where this window's (0, 0) sits in the frame. |
clip: Rect | Region of the frame writes are confined to. |
area: Rect | The window's own extent, in its local coordinates. |
cursor: *CursorRequest | Cursor request for the frame, owned by the screen. |
width_policy: WidthPolicy | How grapheme display widths are measured. |
Creates a new value with the supplied configuration.
buffer: The dense grid to draw into.policy: How grapheme display widths are measured.
Constructs a Frame over cursor storage owned by Screen.
buffer: The dense grid to draw into.cursor: Cursor storage owned by the screen.policy: How grapheme display widths are measured.
Returns a window clipped to the requested frame area.
area: Region of the frame the window covers, clipped to it.
Returns a window spanning the complete frame.
Requests cursor visibility, position, and shape for this frame.
visible: Whether the cursor is shown.position: Where it sits.shape: How the terminal draws it.
Returns a child window clipped to the requested local area.
area: Region in this window's coordinates the child covers.
Fills the target area.
grapheme: Text written into every cell.value: Style the written cells carry.
Applies a style patch to the target area.
area: Region to restyle, in local coordinates.delta: The partial update laid over each cell.
Writes the supplied value.
x: Local column of the head cell.y: Local row of the head cell.grapheme: Text to write.span: Display columns it occupies.value: Style the written cells carry.
Writes sanitized grapheme clusters. Newline and tab are interpreted by the grid; all other C0/C1 controls have already become U+FFFD.
x: Local column to start at.y: Local row to write into.text: Text to segment and write.value: Style the written cells carry.
Writes a prefix of an already-segmented cluster array. Widgets use this to measure, align, and paint Unicode text without segmenting it twice.
x: Local column to start at.y: Local row to write into.clusters: Already-segmented clusters.count: How many of them to write.value: Style the written cells carry.
Requests a cursor at a position relative to this window.
visible: Whether the cursor is shown.position: Where it sits, in this window's coordinates.shape: How the terminal draws it.
moon_tui.geometry
A zero-based terminal cell position.
x: int | Column, counting from zero at the left edge. |
|---|---|
y: int | Row, counting from zero at the top edge. |
A terminal cell extent. Constructors clamp negative dimensions to zero.
width: int | Columns spanned; never negative. |
|---|---|
height: int | Rows spanned; never negative. |
A half-open terminal-cell rectangle.
x: int | Column of the left edge. |
|---|---|
y: int | Row of the top edge. |
width: int | Columns spanned; the right edge is exclusive. |
height: int | Rows spanned; the bottom edge is exclusive. |
Enumerates the supported Direction cases.
Horizontal | Lay out along the row, left to right. |
|---|---|
Vertical | Lay out down the column, top to bottom. |
Creates a terminal-cell position.
x: Column, counting from zero.y: Row, counting from zero.
Creates a terminal-cell extent with non-negative dimensions.
width: Columns spanned; negative is clamped to zero.height: Rows spanned; negative is clamped to zero.
Creates a clamped terminal-cell rectangle.
x: Column of the left edge.y: Row of the top edge.width: Columns spanned; negative is clamped to zero.height: Rows spanned; negative is clamped to zero.
use moon_tui.geometry
use moon_tui.layout
use moon_tui.layout.{Constraint}
fn main() {
let screen = geometry.rect(0, 0, 80, 24)
let rows = layout.split(
screen,
geometry.Direction.Vertical,
[Constraint.Length(3), Constraint.Weight(1), Constraint.Length(1)],
)
println(rows.map(|row| row.height))
println(screen.inset(1).contains(geometry.position(2, 2)))
println(screen.intersect(geometry.rect(70, 20, 20, 10)))
println(screen.translate(1, 1).right())
}Returns the rectangle's exclusive right edge.
Returns the rectangle's exclusive bottom edge.
Reports whether empty.
Reports whether the half-open rectangle contains a position.
p: Position to test against the half-open bounds.
Returns the overlap of two rectangles.
other: Rectangle to overlap with; no overlap yields an empty rectangle.
Returns the rectangle inset by a non-negative margin.
margin: Cells to pull in on every side; negative is treated as zero.
Returns the rectangle translated by the supplied offset.
dx: Columns to shift by.dy: Rows to shift by.
moon_tui.layout
Enumerates the supported Constraint cases.
Length(int) | Exactly this many cells, assigned before anything else. |
|---|---|
Percent(int) | This percentage of the original usable span. |
Weight(int) | This share of whatever remains after lengths and percentages. |
Deterministic one-axis integer layout. Fixed lengths are assigned first, percentages use the original usable span, and weights divide the remainder.
area: Region to divide.direction: Axis to divide along.constraints: One constraint per resulting region, in order.spacing: Cells left between adjacent regions.margin: Cells trimmed from every side before dividing.
moon_tui.runtime
Enumerates the supported RuntimeEvent cases.
Terminal(Event) | Input from the terminal. |
|---|---|
Message(Msg) | An application message, from an effect or a timer. |
Refresh | A repaint request with no new information. |
Application model, update callback, and view callback.
use moon_tui.frame.{Frame}
use moon_tui.runtime
use moon_tui.runtime.{Program, RuntimeEvent, Update}
use moon_tui.style
use moon_tui.terminal
use moon_tui.tui
enum Msg { Tick, Quit }
struct Model { count: int }
fn init() -> Update<Model, Msg> {
runtime.with_commands(
runtime.redraw(Model { count: 0 }),
[runtime.after(1000, Msg.Tick)],
)
}
fn update(model: Model, event: RuntimeEvent<Msg>) -> Update<Model, Msg> {
match event {
RuntimeEvent.Message(Msg.Tick) => runtime.with_commands(
runtime.redraw(Model { count: model.count + 1 }),
[runtime.after(1000, Msg.Tick)],
),
RuntimeEvent.Message(Msg.Quit) => runtime.quit(model),
_ => runtime.unchanged(model),
}
}
fn view(model: Model, frame: Frame) {
frame.root().write_text(0, 0, "ticks: ${model.count}", style.plain())
}
async fn main() {
let program = Program { init: init, update: update, view: view }
let _final = (await tui.run(program, runtime.options(), terminal.options())).unwrap()
}init: fn() -> Update<Model, Msg> | Builds the first model and its opening commands. |
|---|---|
update: fn(Model, RuntimeEvent<Msg>) -> Update<Model, Msg> | Folds one event into the model. |
view: fn(Model, Frame) -> void | Paints the model into the frame. |
Terminal-runtime timing and input configuration.
max_fps: int | Upper bound on repaints per second. |
|---|---|
max_events_per_cycle: int | How many events one cycle may fold in before repainting. |
completion_queue_capacity: int | How many effect results may queue up. |
idle_sleep_ms: int | How long to sleep when there is nothing to do. |
Returns the default options.
Returns an update that requests a redraw.
model: The model the next cycle sees.
Returns an update that leaves the model without a redraw.
model: The model the next cycle sees.
Returns an update that requests runtime shutdown.
model: The model returned to the caller of the loop.
Returns a model update with follow-up commands.
update: The transition to attach work to.commands: Follow-up work the runtime should start.
Creates a command backed by an asynchronous effect.
run: Called once; the message it resolves to is delivered toupdate.
Creates a command that emits a message after a delay.
delay_ms: How long to wait before delivering.message: What to deliver.
Enumerates the supported EffectOutcome cases.
Success(int, Msg) | The effect with this id produced this message. |
|---|---|
Failure(int, string) | The effect with this id failed, with the reason. |
Runtime bookkeeping for one asynchronous effect.
id: int | Identifier the completion is reported under. |
|---|---|
future: Future<void> | The running effect. |
Delayed message scheduled for a monotonic deadline.
deadline: int | Monotonic time the message is due at. |
|---|---|
sequence: int | Tie-breaker so timers due at the same instant keep their order. |
message: Msg | What is delivered when it fires. |
Runs the serial model/update/view loop over an already-open Terminal. The same low-level begin_frame/present path is used by custom-loop callers.
program: The init, update, and view callbacks to drive.terminal: An already-open session to draw on.clock: Time source, so tests can drive the loop without waiting.config: Frame rate, event batching, and idle behaviour.
moon_tui.screen
Byte and cell counts from one terminal presentation.
success: bool | Whether both the write and the flush succeeded. |
|---|---|
bytes: int | How many bytes the transaction wrote. |
changed_cells: int | How many cells the diff decided to redraw. |
full_refresh: bool | Whether every cell was redrawn rather than just the changes. |
Reusable previous/next grids. One managed state object lets a Terminal and its copied Frames observe the same buffers without singleton arrays.
state: *ScreenState | The buffers and cursor tracking shared by every copy of this handle. |
|---|---|
width_policy: WidthPolicy | How grapheme display widths are measured. |
Shared mutable backing state for a terminal screen.
previous: Buffer | What the terminal is believed to be showing. |
|---|---|
next: Buffer | What the frame under construction wants it to show. |
previous_cursor: CursorRequest | Cursor placement of the last presented frame. |
next_cursor: *CursorRequest | Cursor placement the frame under construction asked for. |
force_full: bool | Whether the next presentation redraws every cell. |
origin: Position | Absolute cell the drawing is placed at. |
relative: bool | Whether placement is inline rather than full-screen. |
cursor_y: int | Row the terminal cursor is believed to sit on. |
Creates a screen with blank current and previous buffers.
size: Grid extent for both buffers.policy: How grapheme display widths are measured.
Returns the current size.
Returns the current terminal cursor row.
Resets tracked cursor placement.
Returns the last presented buffer.
Sets the absolute origin used for terminal cursor placement.
origin: Absolute cell the drawing is placed at.
Selects relative inline presentation instead of full-screen placement.
enabled: True for inline placement, false for full-screen.
Starts drawing a new frame.
Forces the next presentation to redraw all cells.
Resizes the target while preserving valid content.
size: New extent; content inside both extents is preserved.
Builds and writes one transaction. The logical previous frame advances only after both the single write_all call and flush report success.
write_all: Called once with the whole transaction; false means the write failed.flush: Called after the write; false means the flush failed.
moon_tui.style
Portable terminal colors. Indexed uses the xterm 0..255 palette.
Default | The terminal's own foreground or background. |
|---|---|
Indexed(int) | A slot in the xterm 0..255 palette. |
Rgb(int, int, int) | A direct color, as red, green, and blue in 0..255. |
Style attribute mask bit for bold text.
Style attribute mask bit for dim text.
Style attribute mask bit for italic text.
Style attribute mask bit for underlined text.
Style attribute mask bit for reversed colors.
Style attribute mask bit for hidden text.
Style attribute mask bit for struck-through text.
A composable style delta. Missing colors leave the destination unchanged.
fg: Optional<Color> | Foreground to set; absence leaves the destination alone. |
|---|---|
bg: Optional<Color> | Background to set; absence leaves the destination alone. |
add_attrs: int | Attribute bits to turn on. |
remove_attrs: int | Attribute bits to turn off; applied after |
Returns the default unstyled value.
Creates a style from foreground, background, and attributes.
fg: Foreground color.bg: Background color.attrs: Attribute bits, OR-ed together.
use moon_tui.style
use moon_tui.style.Color
fn main() {
let base = style.styled(Color.Indexed(14), Color.Default, style.BOLD)
let changed = base.apply(
style.patch(none, some(Color.Rgb(20, 30, 40)), style.UNDERLINE, style.BOLD),
)
println(changed)
println(style.plain())
}Creates a partial style update.
fg: Foreground to set; absence leaves it alone.bg: Background to set; absence leaves it alone.add_attrs: Attribute bits to turn on.remove_attrs: Attribute bits to turn off.
Applies the patch and returns the resulting value.
delta: The partial update to lay over this style.
moon_tui.terminal
Terminal backend, viewport, width, and polling configuration.
viewport: Viewport | Whether to take the alternate screen or reserve inline rows. |
|---|---|
mouse: bool | Whether to enable mouse reporting. |
paste: bool | Whether to enable bracketed paste. |
focus: bool | Whether to enable focus reporting. |
width_policy: WidthPolicy | How grapheme display widths are measured. |
Returns the default options.
Shared mutable state for an open terminal session.
closed: bool | Whether cleanup has already run. |
|---|---|
inline: bool | Whether the session draws inline rather than on the alternate screen. |
clear_inline: bool | Whether the reserved inline rows are cleared on close. |
last_size: Size | Extent last observed, so a resize can be detected. |
Open terminal session with drawing and input operations.
driver: Driver | The backend the session reads and writes through. |
|---|---|
screen: Screen | The previous/next grids the session presents from. |
decoder: *Decoder | The incremental VT decoder input is fed to. |
options: TerminalOptions | The configuration the session was opened with. |
state: *TerminalState | Session bookkeeping shared by every copy of this handle. |
Opens a terminal using the default platform backend.
config: Viewport, input modes, and width policy for the session.
use moon_tui.event.{Event, KeyCode}
use moon_tui.style
use moon_tui.terminal
fn main() {
let term = terminal.open(terminal.options()).unwrap()
defer term.close()
let frame = term.begin_frame()
frame.root().write_text(0, 0, "press Escape", style.plain())
println(term.present().success)
for event in term.poll(std.time.monotonic_ms()).unwrap() {
match event {
Event.Key(key) => match key.code { KeyCode.Escape => return, _ => {} },
_ => {},
}
}
term.refresh()
}Opens a terminal with an explicit backend.
options: Viewport, input modes, and width policy for the session.backend: Driver to read and write through, in place of the platform one.
Starts drawing a new frame.
Writes the pending terminal frame and returns statistics.
Forces the next presentation to redraw all cells.
Polls the terminal for decoded input events.
now_ms: Current monotonic time, which resolves a pending bare Escape.
Idempotent reverse-order cleanup. Mode restoration is attempted even if output cleanup fails, because the platform driver owns raw-mode state.
moon_tui.tui
Runs the configured application loop.
program: The init, update, and view callbacks to drive.runtime_options: Frame rate, event batching, and idle behaviour.terminal_options: Viewport, input modes, and width policy.
Runs the application loop with explicit dependencies.
program: The init, update, and view callbacks to drive.terminal: An already-open session to draw on.injected_clock: Time source, so tests can drive the loop without waiting.runtime_options: Frame rate, event batching, and idle behaviour.
moon_tui.unicode_data
Unicode data version used by the generated width tables.
SHA-256 of the source Unicode data used to generate these tables.
Sorted Unicode code-point ranges for extend.
Sorted Unicode code-point ranges for spacing mark.
Sorted Unicode code-point ranges for prepend.
Sorted Unicode code-point ranges for wide.
Sorted Unicode code-point ranges for ambiguous.
Sorted Unicode code-point ranges for emoji presentation.
Sorted Unicode code-point ranges for extended pictographic.
moon_tui.viewport
Enumerates the supported Viewport cases.
Alternate | Take the whole alternate screen. |
|---|---|
Inline(int, bool) | Reserve this many rows on the primary screen, clearing them on exit when the flag is set. |
Screen origin and drawable size selected for a viewport.
size: Size | Drawable extent selected for the viewport. |
|---|---|
inline: bool | Whether drawing happens inline on the primary screen. |
clear_on_exit: bool | Whether the reserved rows are cleared when the viewport ends. |
Computes viewport geometry for the terminal size.
mode: Which viewport to compute for.terminal_size: Extent the terminal reported.
Reserves fixed-height primary-screen rows without a cursor-position query.
height: Rows to reserve on the primary screen.
Returns escape sequences that clear an inline viewport.
height: Rows the inline viewport occupies.
Returns the escape sequence that moves to the inline anchor.
current_y: Row the cursor currently sits on.
Finishes inline rendering and optionally clears its rows.
height: Rows the inline viewport occupies.clear: Whether to clear those rows on the way out.current_y: Row the cursor currently sits on.
moon_tui.widget
Shared alignment and text helpers used by the pure widget modules.
Left | Flush with the left edge. |
|---|---|
Center | Centred, with an odd remainder on the right. |
Right | Flush with the right edge. |
Clamps a value to the inclusive bounds.
value: Value to constrain.low: Lowest value allowed.high: Highest value allowed.
Repeats the value the requested number of times.
text: Text to repeat.count: How many copies to emit.
Clips on grapheme boundaries and never emits a partial wide cluster.
text: Text to clip.max_width: Columns the result must fit in.policy: How grapheme display widths are measured.
Deterministic grapheme wrapping. Newlines are honored; long logical lines wrap at cell boundaries without splitting a cluster.
text: Text to wrap; newlines are honoured.max_width: Columns each line must fit in.policy: How grapheme display widths are measured.
Writes a styled, width-aware line into a window.
window: Window to draw into.y: Local row to write.text: Text to draw, clipped to the window width.value: Style the written cells carry.alignment: How the text sits within the row.
moon_tui.widget_block
Border mask bit for the top edge.
Border mask bit for the right edge.
Border mask bit for the bottom edge.
Border mask bit for the left edge.
Border mask containing every edge.
Border, title, and style configuration for a block widget.
title: string | Text drawn on the top border; empty draws none. |
|---|---|
borders: int | Which edges are drawn, as OR-ed edge bits. |
style: Style | Style the interior is filled with. |
border_style: Style | Style the border glyphs carry. |
title_style: Style | Style the title carries. |
Creates a bordered block widget.
title: Text drawn on the top border.
use moon_tui.buffer
use moon_tui.frame
use moon_tui.geometry
use moon_tui.geometry.{Direction}
use moon_tui.layout
use moon_tui.layout.{Constraint}
use moon_tui.widget.{Alignment}
use moon_tui.widget_block
use moon_tui.widget_gauge
use moon_tui.widget_list
use moon_tui.widget_paragraph
use moon_tui.widget_separator
use moon_tui.widget_table
use moon_tui.widget_tabs
fn main() {
let grid = buffer.new(geometry.size(60, 16))
let root = frame.new(grid).root()
let inner = widget_block.render(
widget_block.block("Build"),
root.window(geometry.rect(0, 0, 60, 16)),
)
let rows = layout.split(
inner,
Direction.Vertical,
[Constraint.Length(2), Constraint.Weight(1), Constraint.Length(1)],
)
widget_paragraph.render(
widget_paragraph.paragraph("moon build dashboard"),
root.window(rows[0]),
)
let columns = [
widget_table.column("Stage", Constraint.Weight(2)),
widget_table.column("State", Constraint.Weight(1), Alignment.Right),
]
widget_table.render(
widget_table.table(columns, [["compile", "done"], ["test", "green"]]),
widget_table.state(),
root.window(rows[1]),
)
widget_gauge.render(widget_gauge.gauge(0.75, "75%"), root.window(rows[2]))
let list_state = widget_list.state()
list_state.select(1, 2)
list_state.scroll_into_view(2, 2)
println(widget_list.list([widget_list.item("one"), widget_list.item("two")]))
println(widget_tabs.tabs(["Build", "Logs"], 0))
println(widget_separator.separator(Direction.Horizontal))
}Paints the block and returns its local content rectangle.
value: The block to paint.window: Window to draw into.
moon_tui.widget_gauge
Ratio, label, and style configuration for a gauge widget.
ratio: float | How full the bar is, from 0.0 to 1.0. |
|---|---|
label: string | Text drawn over the bar; empty draws none. |
filled_style: Style | Style the filled portion carries. |
empty_style: Style | Style the empty portion carries. |
filled: string | Glyph the filled portion is drawn with. |
empty: string | Glyph the empty portion is drawn with. |
Creates a gauge widget.
ratio: How full the bar is, from 0.0 to 1.0.label: Text drawn over the bar.
Renders the value into its target.
value: The gauge to paint.window: Window to draw into.
moon_tui.widget_list
Text and style for one list row.
text: string | The row text. |
|---|---|
style: Style | Style the row carries when it is not selected. |
Mutable selection and scroll state for a list.
selected: int | Index of the selected item. |
|---|---|
offset: int | Index of the first visible item. |
Creates a list item.
text: The row text.value: Style the row carries.
Creates mutable widget state.
selected: Index of the selected item.offset: Index of the first visible item.
Creates a list widget.
items: Rows to draw, in order.
Returns the selected item index.
Returns the first visible item index.
Moves the selection to a clamped index.
index: Index to move to, clamped into range.count: How many items the list holds.
Adjusts the offset so the selection is visible.
height: How many rows are visible.count: How many items the list holds.
Rendering only observes ListState; selection/scroll changes belong in update.
value: The list to paint.state: Selection and scroll position, read but not changed.window: Window to draw into.
moon_tui.widget_paragraph
Creates a paragraph widget.
text: The text to draw.
Renders the value into its target.
value: The paragraph to paint.window: Window to draw into.
moon_tui.widget_separator
Creates a separator widget.
direction: Whether the rule runs across or down.
Renders the value into its target.
value: The separator to paint.window: Window to draw into.
moon_tui.widget_table
Columns are the table's schema: headers, layout constraints, and alignment drive rendering without hardcoded field positions.
header: string | Text drawn in the header row. |
|---|---|
constraint: Constraint | How much width the column takes. |
alignment: Alignment | How cells sit within the column. |
Mutable selection and scroll state for a table.
selected: int | Index of the selected row. |
|---|---|
offset: int | Index of the first visible row. |
Column, row, and style configuration for a table widget.
columns: [Column] | The schema: header, width, and alignment per column. |
|---|---|
rows: [[string]] | Row data, each a list of cell texts. |
style: Style | Style unselected rows carry. |
header_style: Style | Style the header row carries. |
selected_style: Style | Style the selected row carries. |
spacing: int | Cells left between adjacent columns. |
show_header: bool | Whether the header row is drawn at all. |
Creates a table column definition.
header: Text drawn in the header row.constraint: How much width the column takes.alignment: How cells sit within the column.
Creates mutable widget state.
selected: Index of the selected row.offset: Index of the first visible row.
Creates a table widget.
columns: The schema, in display order.rows: Row data, each a list of cell texts.
Returns the selected item index.
Returns the first visible item index.
Moves the selection to a clamped index.
index: Index to move to, clamped into range.count: How many rows the table holds.
Adjusts the offset so the selection is visible.
height: How many rows are visible.count: How many rows the table holds.
Rendering only observes TableState. A row with fewer cells is padded; extra cells are ignored according to the column schema.
value: The table to paint.state: Selection and scroll position, read but not changed.window: Window to draw into.
moon_tui.widget_tabs
Creates a tabs widget.
titles: Tab labels, in display order.selected: Index of the active tab.
Renders the value into its target.
value: The tab bar to paint.window: Window to draw into.
moon_tui.width
Terminal-width policy. Ambiguous characters default to one column.
ambiguous_wide: bool | Whether East Asian ambiguous characters take two columns. |
|---|---|
emoji_wide: bool | Whether emoji presentation takes two columns. |
tab_width: int | Columns a tab advances to the next stop. |
One grapheme cluster and its displayed terminal-cell width.
text: string | The grapheme cluster itself. |
|---|---|
width: int | Columns it occupies under the policy that measured it. |
newline: bool | Whether the cluster is a line break. |
tab: bool | Whether the cluster is a tab. |
Returns the default terminal width policy.
use moon_tui.width
fn main() {
println(width.text_width("moon"))
println(width.text_width("็"))
println(width.clusters("๐ฉโ๐ป")[0].width)
println(width.is_printable_ascii("plain"))
let mut policy = width.default_policy()
policy.ambiguous_wide = true
policy.tab_width = 8
println(width.text_width("ยท", policy))
}True when every byte is a printable one-column ASCII character. Keeping this common terminal-text path allocation-free avoids paying the Unicode segmentation cost for labels, borders, counters, and status lines.
text: Text to classify.
Incremental-friendly extended-grapheme segmentation over one byte string. Invalid UTF-8 bytes become independent U+FFFD clusters.
text: Text to segment; invalid UTF-8 becomes U+FFFD clusters.policy: How grapheme display widths are measured.
Returns the displayed terminal-cell width of text.
text: Text to measure.policy: How grapheme display widths are measured.