TTY
Terminal UI module for raw input events, styled output, and layout utilities.
Loading
Section titled “Loading”local tty = require("tty")Input Loop
Section titled “Input Loop”Start the raw input reader, subscribe to events, and process them in a loop:
local tty = require("tty")local io = require("io")
local function handler() tty.start() local events = tty.events()
while true do local ev = events:receive() if not ev then break end
if ev.type == "key" then if ev.key == "q" or (ev.ctrl and ev.key == "c") then break end io.print("Key: " .. ev.key)
elseif ev.type == "resize" then io.print("Size: " .. ev.width .. "x" .. ev.height) end end
tty.stop()endInput Control
Section titled “Input Control”tty.start()
Section titled “tty.start()”Enable raw terminal input mode. The terminal switches to raw mode and begins emitting events.
local ok, err = tty.start()Returns: boolean, error
tty.stop()
Section titled “tty.stop()”Disable raw input and restore the terminal to normal mode.
local ok, err = tty.stop()Returns: boolean, error
tty.events()
Section titled “tty.events()”Subscribe to terminal events and return a channel. Events are delivered as tables with a type field.
local events = tty.events()Returns: EventChannel, error
tty.screen_size()
Section titled “tty.screen_size()”Query current terminal dimensions.
local width, height, err = tty.screen_size()Returns: number, number, error
tty.mouse(enable)
Section titled “tty.mouse(enable)”Enable or disable mouse event tracking.
local ok, err = tty.mouse(true)| Parameter | Type | Description |
|---|---|---|
enable | boolean | true to enable, false to disable |
Returns: boolean, error
Event Types
Section titled “Event Types”Events are tables with a type field that determines which other fields are present.
Key Event
Section titled “Key Event”{ type = "key", key = "a", -- printable character or key name key_type = "runes", -- "runes" for printable, or special key name action = "press", -- "press" or "release" alt = false, ctrl = false, shift = false}Mouse Event
Section titled “Mouse Event”Requires tty.mouse(true).
{ type = "mouse", action = "press", -- "press", "release", "motion", "wheel" button = "left", -- button name x = 10, y = 5, alt = false, ctrl = false, shift = false}Resize Event
Section titled “Resize Event”{type = "resize", width = 120, height = 40}Start Event
Section titled “Start Event”Emitted once after tty.start() with initial dimensions.
{type = "start", width = 120, height = 40}Focus Event
Section titled “Focus Event”{type = "focus", focused = true}Paste Event
Section titled “Paste Event”{type = "paste", text = "pasted content"}Key Bindings
Section titled “Key Bindings”Create reusable key bindings that match against key events:
local quit = tty.bind({ keys = {"q", "ctrl+c"}, help = {key = "q/ctrl+c", desc = "quit"}})
-- In event loopif quit:matches(ev) then breakendtty.bind(config)
Section titled “tty.bind(config)”| Field | Type | Description |
|---|---|---|
keys | string[] | Key patterns to match (e.g. "a", "ctrl+c", "enter") |
help | table | Optional. {key = "...", desc = "..."} for help text |
Returns: KeyBinding
KeyBinding Methods
Section titled “KeyBinding Methods”| Method | Returns | Description |
|---|---|---|
matches(event) | boolean | Test if a key event matches this binding |
set_enabled(bool) | self | Enable or disable the binding |
is_enabled() | boolean | Check if the binding is enabled |
help() | table | Returns {key, desc} help info |
Styles
Section titled “Styles”Create styled text output using lipgloss-based styling. All style methods return a new style (immutable).
local tty = require("tty")local io = require("io")
local title = tty.style() :bold() :foreground("#FF0000") :padding(0, 1)
local box = tty.style() :border(tty.borders.ROUNDED) :border_foreground("#00FF00") :width(40) :padding(1, 2)
io.print(box:render(title:render("Hello"), "World"))tty.style()
Section titled “tty.style()”Create a new empty style.
Returns: Style
Style Methods
Section titled “Style Methods”All methods return a new Style and can be chained.
Text Decoration
Section titled “Text Decoration”| Method | Parameter | Description |
|---|---|---|
foreground(color) | string | Text color (hex "#FF0000", ANSI "9", or name) |
background(color) | string | Background color |
bold(enable?) | boolean | Bold text (default: true) |
italic(enable?) | boolean | Italic text |
underline(enable?) | boolean | Underline text |
strikethrough(enable?) | boolean | Strikethrough text |
faint(enable?) | boolean | Dimmed text |
blink(enable?) | boolean | Blinking text |
reverse(enable?) | boolean | Swap foreground/background |
Layout
Section titled “Layout”| Method | Parameter | Description |
|---|---|---|
width(n) | number | Fixed width |
height(n) | number | Fixed height |
max_width(n) | number | Maximum width |
max_height(n) | number | Maximum height |
padding(...) | numbers | Padding (CSS-style: top, right, bottom, left) |
margin(...) | numbers | Margin (CSS-style) |
align(pos) | number | Horizontal alignment |
align_vertical(pos) | number | Vertical alignment |
inline(enable?) | boolean | Inline rendering mode |
Borders
Section titled “Borders”| Method | Parameter | Description |
|---|---|---|
border(name, ...) | string, booleans | Border style, optional per-side toggles |
border_foreground(...) | strings | Border color(s) |
border_background(...) | strings | Border background color(s) |
| Method | Description |
|---|---|
render(...) | Render strings with this style applied |
copy() | Create a copy of this style |
Border Constants
Section titled “Border Constants”tty.borders.NORMALtty.borders.ROUNDEDtty.borders.THICKtty.borders.DOUBLEtty.borders.HIDDENAlignment Constants
Section titled “Alignment Constants”tty.align.LEFT -- 0tty.align.CENTER -- 0.5tty.align.RIGHT -- 1Text Utilities
Section titled “Text Utilities”Layout and measurement functions for styled text. Available under tty.text.
Measurement
Section titled “Measurement”local w = tty.text.width("hello") -- printable width (ANSI-aware)local h = tty.text.height("a\nb\nc") -- line countlocal w, h = tty.text.size("hello\nworld") -- bothJoining
Section titled “Joining”-- Join side by side, aligned at toplocal row = tty.text.join_horizontal(tty.text.position.TOP, left, right)
-- Stack vertically, centeredlocal col = tty.text.join_vertical(tty.text.position.CENTER, top, bottom)Max Dimensions
Section titled “Max Dimensions”local w = tty.text.max_width({"short", "a longer string"}) -- widestlocal h = tty.text.max_height({"one\ntwo", "single"}) -- tallestPlacement
Section titled “Placement”Place a string within a box of given dimensions:
-- Center in a 80x24 boxlocal out = tty.text.place(80, 24, tty.text.position.CENTER, tty.text.position.CENTER, content)
-- Horizontal onlylocal out = tty.text.place_horizontal(80, tty.text.position.RIGHT, content)
-- Vertical onlylocal out = tty.text.place_vertical(24, tty.text.position.BOTTOM, content)Position Constants
Section titled “Position Constants”tty.text.position.TOP -- 0tty.text.position.LEFT -- 0tty.text.position.CENTER -- 0.5tty.text.position.BOTTOM -- 1tty.text.position.RIGHT -- 1See Also
Section titled “See Also”- Terminal I/O — stdin/stdout/stderr operations
- Terminal Host — Terminal host configuration