Table
Streaming, auto-fitting terminal tables that redraw live or append in a pipe.
@ozaco/cli/table@ozaco/cli/table is the default implementation of the Table protocol. It renders columnar data that you feed row by row through a handle, so tables can grow while a job runs rather than being assembled all at once.
On an interactive terminal it keeps every row, auto-fits column widths, and re-renders the whole table in place — so any row stays editable via update/set until end(). When the table outgrows the viewport, only the last rows that fit are shown plus a +N more note; end() clears the live window and commits the full, fully-aligned table to the scrollback.
In a pipe or CI (non-interactive), output is fixed-width and append-only: a row is committed once the next one arrives (or on end()), so the most-recent row stays editable while earlier lines are already written. Updating an already-committed row can’t rewrite it, so its new state is re-appended as a fresh line. Column widths shrink to fit the terminal, cells are truncated with an ellipsis, and the border style (full, header, or none), gutter, header visibility and live window are all configurable. Requires Terminal and Palette.
Implementation
DefaultTable
The table implementation providing the `table` action.
const DefaultTable: TableDefInstall it alongside Terminal and Palette, then open a table with Table.actions.table(options) and drive it through the returned handle.
import { install } from '@ozaco/std/plugin'
import { Table } from '@ozaco/cli/core'
import { DefaultTable } from '@ozaco/cli/table'
yield* install(DefaultTable)
const t = yield* Table.actions.table({
columns: [
{ header: 'Name', key: 'name' },
{ header: 'Size', key: 'size', align: 'right' },
],
})
yield* t.rows(files.map(f => ({ name: f.name, size: f.size })))
yield* t.end()Action
Available on the `Table` protocol once `DefaultTable` is installed.
table
Open a streaming table; returns a `Handle` to feed rows and close it.
table(options: TableDef.Options): Future<TableDef.Handle>options.columns defines the shape; border (default full), gutter (default 2), head (default true) and window tune rendering. Each Column may set header, key, fixed width or min/max bounds, align, a color style, and a format function. The table is bound to the current scope: it commits on end() or on teardown.
Handle
The interface returned by the `table` action.
Handle
Feed rows into an open table and commit it (`TableDef.Handle`).
interface Handle {
row(row: TableDef.Row): Future<number>
rows(rows: TableDef.Row[]): Future<number[]>
update(index: number, row: TableDef.Row): Future<void>
set(index: number, column: string | number, value: TableDef.Cell): Future<void>
end(): Future<void>
}row appends one row and returns its index; rows appends many and returns their indices. update replaces a whole row by index; set replaces one cell by column key (object rows) or index (array rows). end commits the full, aligned table to the scrollback. A Row is a tuple of cells or a keyed record.
const i = yield* t.row({ name: 'build', size: 0 })
// … work happens …
yield* t.set(i, 'size', 2048)
yield* t.end()