Terminal
Terminal.zig handles raw mode, terminal size detection, and input.
Raw Mode
Entering raw mode disables:
- Line buffering (characters available immediately, not after Enter)
- Echo (typed characters aren't displayed)
- Signal handling for Ctrl+C (you handle it yourself)
const std = @import("std");
const tui = @import("tui");
pub fn main(init: std.process.Init) !void {
var term = try tui.Terminal.init(init.io); // enters raw mode
defer term.deinit(); // restores cooked mode
}Always pair init with deinit via defer. If your program crashes without restoring cooked mode, the terminal will be unusable (run reset to fix).
Terminal Size
term.refreshSize();
// term.width, term.heightInput
The terminal uses a ring buffer for input and VTIME=0 VMIN=0 for non-blocking reads. This means:
pollKey()returns immediately withnullif no input- No busy-wait, no blocking
- Escape sequences (arrow keys, function keys) are parsed into single key events
Raw Mode Details
On POSIX systems, raw mode sets:
ICANONoff — no line bufferingECHOoff — no character echoISIGoff — no signal generation from Ctrl+C etcVTIME=0, VMIN=0— non-blocking reads
Important
- Always emit
\r\nnot just\nin raw mode (the terminal won't do CR for you) - Use hex literals for escape sequences:
"\x1b[2J"not literal escape chars - Don't use
SO_RCVTIMEOwith TLS on macOS — it corrupts state