Skip to main content

Output

A form is rarely the whole program. A market-stall order opens with a welcome box, says what it is doing between steps, and closes with a summary and its next steps. The output() primitives draw that chrome with the same theme the panel uses, so the text around the form belongs to the same program as the form itself.

output() returns a DrevOps\PhpTui\Primitive\Output carrying the pieces: a box and a card, an aligned table, five status lines, a definition list, wrapped text, a rule and a banner. Like progress(), it is a primitive: it collects no answer and never runs inside the interactive panel. Hold onto the object and call it as often as you need - every call returns it, so the calls chain.

$out = $tui->output();

$out->box('Welcome', 'Everything below is picked the morning it ships.');

$answers = $tui->run();

$out->success('Preserves are ready')
->definitions(['Jars' => '12', 'Fruit' => 'Apricot'])
->note('Anything short is refunded, never substituted');

Box

box() frames a body under an optional title, sized to its widest line and capped at the terminal. Pass a string, or a list of lines when you want to control the spacing - an empty entry stays a blank line.

Output boxOutput box

$out->box('Welcome to the produce box', [
'Everything below is picked the morning it ships.',
'',
'Nothing is charged until the box leaves the packing shed.',
]);

Long lines wrap inside the border rather than being clipped by it, so you can hand box() a paragraph and let it fit itself to the terminal.

Runnable in playground/18-output-box.php.

In all four display modes - Unicode or ASCII, color on or off:

ANSINo ANSI
UnicodeBox: Unicode + ANSIBox: Unicode + ANSIBox: Unicode + No ANSIBox: Unicode + No ANSI
ASCIIBox: ASCII + ANSIBox: ASCII + ANSIBox: ASCII + No ANSIBox: ASCII + No ANSI

Table

table() lays headers and rows into a bordered grid, sizing each column to its widest cell and capping the whole thing at the terminal. It is the same renderer a markup block's grid uses, so a standalone table matches the ones inside the panel.

Output tableOutput table

$out->table(['Item', 'Crates', 'Picked'], [
['Apricot', '4', 'Tuesday'],
['Peach', '2', 'Tuesday'],
['Carrot', '6', 'Wednesday'],
]);

Pass an empty header list to draw the rows with no header row. When the natural width exceeds the terminal, the widest columns shrink and over-long cells are cut short with an ellipsis, so the borders always stay whole.

Runnable in playground/18-output-table.php.

ANSINo ANSI
UnicodeTable: Unicode + ANSITable: Unicode + ANSITable: Unicode + No ANSITable: Unicode + No ANSI
ASCIITable: ASCII + ANSITable: ASCII + ANSITable: ASCII + No ANSITable: ASCII + No ANSI

Card

card() is the full form of box(): a title, a body and a grid, boxed together when the three belong to one another. It is the same renderer behind a markup block's card, so a standalone card and an in-form card are the same object drawn twice.

Output cardOutput card

$out->card('Loaded for delivery', 'Everything below leaves the shed at seven.', ['Item', 'Crates'], [
['Apricot', '4'],
['Peach', '2'],
]);

The grid is sized to fit inside the card's own border, so the two frames never collide. Pass bordered: false for the indented card - the shape a markup block draws when it carries a grid without asking for a border.

Status lines

Five kinds, each with its own glyph and its own color: note(), info(), success(), warning() and error().

Status linesStatus lines

$out->info('Checking the morning harvest')
->success('Apricots picked and weighed')
->warning('Only two crates of pears left')
->error('The cherry shelf is empty')
->note('Anything short is refunded, never substituted');

The glyph carries the meaning on its own, so the five stay distinguishable with color off and in ASCII alike. Every glyph is one column wide in any terminal, so a run of status lines always aligns.

To choose the kind at runtime, pass a Status case to status():

use DrevOps\PhpTui\Primitive\Status;

$out->status($ok ? Status::Success : Status::Error, 'Packed the box');

Runnable in playground/18-output-status.php.

ANSINo ANSI
UnicodeStatus: Unicode + ANSIStatus: Unicode + ANSIStatus: Unicode + No ANSIStatus: Unicode + No ANSI
ASCIIStatus: ASCII + ANSIStatus: ASCII + ANSIStatus: ASCII + No ANSIStatus: ASCII + No ANSI

Definition list

definitions() lays label/value pairs into two columns - the labels sized to the widest of them, a long value wrapped under its own column. It is the natural way to read a collected form back to the person who filled it in.

Definition listDefinition list

$out->definitions([
'Order' => 'Summer Box',
'Fruit' => 'Apricot, Peach, Plum',
'Vegetables' => 'Carrot, Spinach, Tomato',
'Quantity' => '6 baskets',
'Note' => 'Everything is picked the morning it ships, packed in the shed, and loaded onto the van before seven.',
]);

Runnable in playground/18-output-definitions.php.

ANSINo ANSI
UnicodeDefinitions: Unicode + ANSIDefinitions: Unicode + ANSIDefinitions: Unicode + No ANSIDefinitions: Unicode + No ANSI
ASCIIDefinitions: ASCII + ANSIDefinitions: ASCII + ANSIDefinitions: ASCII + No ANSIDefinitions: ASCII + No ANSI

Text, rules and a banner

Three smaller pieces round out the set. text() wraps a paragraph to the terminal and renders the same markdown subset a field description carries, so prose outside the form reads like prose inside it. rule() draws a themed separator between sections, and banner() opens the program with a logo above an optional version line.

Banner, rule and wrapped textBanner, rule and wrapped text

$out->banner('Produce Box', '1.2.3');
$out->rule();
$out->text('Every box is picked the morning it ships. Nothing is charged until the crates leave the packing shed.');

The markdown subset is off by default, exactly as it is for field descriptions - turn it on with $tui->markdown() before reaching for output():

$out = $tui->markdown()->output();

$out->text("**Before you order:**\n\n- Pick a *delivery day* between Monday and Saturday\n- Leave a note if the gate code is not `1234`");

Runnable in playground/18-output-text.php.

Theme-drawn

The colors and glyphs come from the active theme, the same way every field does, and the pieces reuse the voices the panel already speaks in: a box takes the frame's border and heading, a success line the value color, an info line the theme's accent. So ->theme('ember') prints info lines in ember's orange and ->theme('frost') in frost's blue, with no extra configuration and nothing a custom theme has to override to inherit its own palette.

To go further and restyle one piece outright, override its render*() method on your theme - renderCard(), renderTable(), renderStatus(), renderDefinitions(), renderText(), renderRule() or renderBanner().

renderCard() is the single renderer behind both the standalone card and the one a markup block draws in a panel - grid included, since a markup grid is a card with a grid in it - so overriding it restyles the two together. renderTable() draws the standalone grid. None of them takes a field, a panel or an answer set: they take plain strings and arrays, which is what makes them usable outside a form at all.

Degrading off a TTY

Output is chrome, not data, so it is written to standard error and leaves standard output for your program's own results. Piped, redirected or captured, the escape codes would land in the text rather than on a terminal, so the color is dropped and the plain lines remain:

php playground/18-output-status.php 2>&1 | cat
# › Checking the morning harvest
# ✓ Apricots picked and weighed
# ! Only two crates of pears left

The frames, glyphs and alignment survive, because they are text. Forcing wins over the detection either way, and both switches are set on the facade before you reach for output(): $tui->color(true)->output() keeps the color in a captured log, and $tui->unicode(false)->output() draws the ASCII glyphs on a capable terminal. See display modes for the full set of switches.

To write somewhere other than standard error - standard output, or a stream you control - pass your own terminal:

use DrevOps\PhpTui\Terminal\Terminal;

$out = $tui->output(new Terminal(STDOUT));