TUI API
Terminal UI helpers are available under ptool.tui and p.tui.
The first version focuses on small interactive terminal screens driven by a Lua event loop.
ptool.tui.run
Unreleased- Introduced.
ptool.tui.run(options) starts a TUI session, runs the Lua lifecycle
callbacks, and returns the value passed to app:quit(value). If app:quit()
is called without a value, the function returns nil.
options fields:
tick_ms(integer, optional): Tick interval in milliseconds. Defaults to100.init(function, optional): Called once before the first frame is drawn. Its return value becomes the initialstate.update(function, required): Called asupdate(state, event, app)after each input event or tick. If it returns a non-nilvalue, that value becomes the nextstate. Returningnilkeeps the currentstate.view(function, required): Called asview(state, app)to build the root node for the next frame.
Behavior:
- Requires an interactive TTY.
- Runs inside the terminal alternate screen with raw mode enabled.
- Restores the terminal when the session exits, including error paths.
Events:
{ type = "tick" }{ type = "resize", width = <integer>, height = <integer> }{ type = "key", key = <string>, ctrl = <boolean>, alt = <boolean>, shift = <boolean> }
Common key names include up, down, left, right, enter, esc,
tab, backspace, delete, home, end, pageup, and pagedown.
Character keys use the character itself, such as "q" or "j".
Example:
local result = p.tui.run({
tick_ms = 200,
init = function()
return {
items = {"alpha", "beta", "gamma"},
selected = 1,
}
end,
update = function(state, event, app)
if event.type == "key" then
if event.key == "q" then
app:quit(state.items[state.selected])
elseif event.key == "down" then
state.selected = math.min(#state.items, state.selected + 1)
elseif event.key == "up" then
state.selected = math.max(1, state.selected - 1)
end
end
end,
view = function(state)
return p.tui.column({
title = "Demo",
border = true,
padding = 1,
children = {
p.tui.text("Press q to quit", {
align = "center",
}),
p.tui.list(state.items, {
selected = state.selected,
highlight_style = {
reversed = true,
},
}),
},
})
end,
})
print("selected:", result)
App
Unreleased- Introduced.
app is passed to update(...) and view(...).
quit
Canonical API name: ptool.tui.App:quit.
app:quit(value?) requests that the TUI session stop after the current
callback completes.
value(Lua value, optional): The value returned byptool.tui.run(...).
Node Constructors
Unreleased- Introduced.
The constructor helpers below return plain node tables. view(...) must return
one of these nodes as the root widget tree.
Common node fields:
title(string, optional): Draws a block title around the node.border(boolean, optional): Draws a border around the node. Defaults tofalse.padding(integer, optional): Uniform inner padding. Defaults to0.grow(integer, optional): Relative size when the node is inside a row or column. Defaults to1.style(table, optional): Shared style fields:fg/bg: One ofblack,red,green,yellow,blue,magenta,cyan,white,gray, ordark_gray.bold,dim,italic,underlined,reversed: Boolean style toggles.
ptool.tui.text
Unreleased- Introduced.
ptool.tui.text(text[, options]) creates a text node.
text(string, required): The text to render.options.align(string, optional):left,center, orright. Defaults toleft.
ptool.tui.list
Unreleased- Introduced.
ptool.tui.list(items[, options]) creates a vertical list node.
items(table, required): A dense list table. Item values may be strings, numbers, or booleans.options.selected(integer, optional): The selected row using Lua's 1-based indexing. Values beyond the item count are ignored.options.highlight_style(table, optional): Style applied to the selected row. Uses the same keys asstyle.
Notes:
- Selection is only visually distinct when
highlight_stylechanges the rendered style.
ptool.tui.row
Unreleased- Introduced.
ptool.tui.row(options) creates a horizontal container.
options.children(table, required): A dense list table of child nodes.
ptool.tui.column
Unreleased- Introduced.
ptool.tui.column(options) creates a vertical container.
options.children(table, required): A dense list table of child nodes.
Current Limits
ptool.tui currently supports:
tick,resize, and keyboard events.- Text, list, row, and column nodes.
- Basic block decoration and style options.
It does not yet provide text inputs, popups, tables, mouse-driven widgets, or arbitrary ratatui widget bindings.