Skip to main content

Installation

Install the package with Composer:

composer require drevops/tui

The package is a library you consume programmatically - it has no CLI entry point of its own. You'll work with two classes:

  • DrevOps\Tui\Tui - the facade: collects a form's answers, headlessly or through the interactive panel TUI.
  • DrevOps\Tui\Builder\Form - the fluent builder for declaring a form's panels and fields.

Usage

Declare a form with the fluent Form builder, then hand it to the Tui facade - one class that wires up the engine, resolver, schema tools and TUI so you don't have to:

use DrevOps\Tui\Builder\Form;
use DrevOps\Tui\Builder\PanelBuilder;
use DrevOps\Tui\Tui;

$form = Form::create('Quick start')
->panel('order', 'New order', function (PanelBuilder $p): void {
// A required single-line text field.
$p->text('name', 'Order name')->required();

// A single choice, starting on "Banana".
$p->select('fruit', 'Fruit')->default('banana')->options([
'apple' => 'Apple',
'banana' => 'Banana',
'cherry' => 'Cherry',
]);

// A multi-select, with one option pre-checked.
$p->select('veg', 'Vegetables')->multiple()->default(['carrot'])->options([
'carrot' => 'Carrot',
'tomato' => 'Tomato',
'spinach' => 'Spinach',
]);

// An integer bounded to a sensible quantity.
$p->number('quantity', 'Quantity')->min(1)->max(99)->default(6);

// A yes/no gate.
$p->confirm('organic', 'Organic only?')->default(FALSE);
});

$tui = new Tui($form);

// Interactive panel TUI on a terminal, headless otherwise.
$answers = $tui->run();

// Or drive a mode directly:
echo $tui->collect('{"name":"Weekly Box"}')->toJson(); // headless: JSON + environment
$answers = $tui->interact(); // interactive panel TUI

run() picks the mode for you: on a terminal it drives the interactive panel TUI, and anywhere else - or whenever prompts are supplied - it collects headlessly. The facade also exposes schema(), agentHelp() and validate(), and - when you want finer control - the internals via form(), engine() and registry().

Aborting with Ctrl-C or Cancel

Pressing Ctrl-C part-way through an interactive session aborts it: the panel TUI restores the terminal, clears the screen, and the facade raises a DrevOps\Tui\InterruptException instead of returning the partial answers - so an abort can never be mistaken for a completed submission. The Cancel button aborts the same way, raising DrevOps\Tui\CancelException. That's a subclass of InterruptException, so one catch covers both:

use DrevOps\Tui\InterruptException;

try {
$answers = $tui->run();
}
catch (InterruptException) {
// The user pressed Ctrl-C or cancelled: leave without printing a result.
exit(130);
}

echo $answers->toSummary();

Catch CancelException first when an explicit cancel should react differently from a Ctrl-C. Only the interactive session raises these: headless collection - collect(), or run() when prompts are supplied or the input is piped - never interacts, so it never aborts this way.

Next steps