A scrollable, keyboard-driven form; fields group into sections that drill in to any depth, with a contextual key-hint footer and a ? help overlay.
A dependency-light PHP engine for interactive, keyboard-driven terminal forms. Declare the questions with a fluent builder; the engine renders a scrollable, themeable TUI - or collects the answers headlessly from JSON and environment variables.
composer require drevops/tuiDescribe the questions with a fluent builder - text, choices, toggles and more - add a handler class where a question needs real behaviour, and call run(). Interactive on a terminal, non-interactive otherwise.
use DrevOps\Tui\Builder\Form;
use DrevOps\Tui\Builder\PanelBuilder;
use DrevOps\Tui\Tui;
$form = Form::create('New project')
->panel('setup', 'Setup', function (PanelBuilder $p): void {
$p->text('name', 'Project name')->required();
$p->select('type', 'Project type')->options([
'app' => 'Application',
'library' => 'Library',
]);
$p->select('services', 'Services')->multiple()->default(['redis'])->options([
'redis' => 'Redis',
'solr' => 'Solr',
'clamav' => 'ClamAV',
]);
$p->confirm('ci', 'Set up CI?')->default(TRUE);
});
$tui = new Tui($form, ['App\\Handler']);
// Interactive on a terminal, non-interactive otherwise.
$answers = $tui->run();On a terminal
A scrollable, keyboard-driven TUI; fields group into sections that drill in to any depth, with a contextual key-hint footer and a ? help overlay.
Everywhere else
Supply the answers up front as a JSON payload and environment variables so it runs without prompting. Emits a JSON schema for agents.
The engine stays generic. Your questions and handlers live in the consumer - it collects, you apply.
A scrollable, keyboard-driven form; fields group into sections that drill in to any depth, with a contextual key-hint footer and a ? help overlay.
A field's editor opens in place on the panel row, with its own view and keys; opt a field out to a full screen with ->standalone().
Text, numbers, dates, single and multiple choice, fuzzy search, file browsing, reordering and gates.
The form is declared in PHP with a fluent builder; the common cases need no extra code.
Answer by keyboard, or supply the answers up front as a JSON payload and environment variables so it runs without prompting. Emits a JSON schema for agents.
Compute one field from others with str2name transforms; chains settle to a fixpoint.
Show or hide fields with when rules; a fix-up pass reconciles dependent answers.
The whole visual representation - colours, glyphs, layout - is a theme class; ships dark and light.
Remap navigation, edit, accept and cancel keys per widget type; ships a vim-style preset.
A month calendar returning a normalized ISO YYYY-MM-DD; arrows move by day and week.
Yes/No toggle; arrows or Space switch, y/n set the choice directly, Enter accepts.
Browse the filesystem for a path, or several with ->multiple(); -> enters a directory, <- returns to its parent.
Integer entry accepted as an int, with optional min, max and step.
Text rendered as a mask everywhere; the accepted value stays plain for the consumer, and can be made revealable.
An acknowledgement gate; Enter or Space accepts. Unattended runs auto-acknowledge it.
Rank a list by moving items; Space picks an item up, arrows carry it, Enter accepts.
Single choice with a visible filter line; typing fuzzy-matches and ranks the labels.
Single choice from a list; arrows move, Enter accepts, long lists page around the cursor.
Free text with autocomplete over a fixed option set; suggestions fuzzy-matched and ranked.
Single-line input with a movable caret; type to insert, arrows move, Backspace deletes.
Multi-line input; Enter inserts a newline, Tab accepts, with an external-editor handoff.
An inline switch between two labelled values; arrows or Space flip, first letter sets it directly.