Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

App

App.zig manages the frame lifecycle — the entry point for any TUI application.

Usage

const std = @import("std");
const tui = @import("tui");
 
pub fn main(init: std.process.Init) !void {
    var app = try tui.App.init(init.gpa, init.io);
    defer app.deinit(); // restores terminal to cooked mode
 
    while (true) {
        app.beginFrame();
 
        // ... render to app.buf ...
 
        if (app.pollKey()) |key| {
            switch (key) {
                .char => |c| if (c == 'q') break,
                else => {},
            }
        }
 
        app.endFrame(); // flushes buffer diff to terminal
    }
}

API

App.init(allocator, io) -> !App

Initializes the terminal in raw mode and allocates the double buffer. Pass the process io from std.process.Init.

app.deinit()

Restores terminal to cooked mode. Always call this (use defer).

app.beginFrame()

Starts a new frame. Clears dirty state from previous frame.

app.endFrame()

Flushes the buffer diff to the terminal. Only changed cells are written.

app.pollKey() -> ?Key

Non-blocking key read. Returns null if no key is pressed.

Uses VTIME=0 VMIN=0 for truly non-blocking reads — no blocking, no busy-wait.

app.width() / app.height() / app.fullRect()

Helpers for current terminal dimensions and the full-screen drawing region.

app.buf

The current frame buffer. Write to this during your render phase.