Skip to content

drevops/tui

Repository files navigation

TUI logo

Terminal user interfaces for PHP

GitHub Issues GitHub Pull Requests Test PHP codecov GitHub release (latest by date) LICENSE Renovate


Terminal form with a rounded border

drevops/tui is a PHP engine for panel-based terminal forms: keyboard-driven questionnaires that collect a set of answers and hand them back to the caller as typed values.

  • Declarative form model. A form is declared with a fluent builder (Form / PanelBuilder / FieldBuilder): panels of typed fields, each field a widget with its own options, conditions, derivation rules and behaviour.
  • Two collection modes, one declaration. The same form runs as a full-screen interactive TUI on a terminal, or resolves non-interactively from a JSON payload, per-field environment variables, discovery rules and defaults.
  • Application-agnostic. The engine knows nothing about the application it serves; questions and handlers live in the consumer, and applying the collected answers is the consumer's job. It collects; you apply.
  • Dependency-light. The runtime dependency surface is a single string-transform package.

The border above is a display option. The same form at the default borderless look, normal spacing:

Terminal form without a border

πŸ“– Documentation

Full documentation lives at phptui.dev. The in-development build, rebuilt from main ahead of each release, is previewed at tui-docs.netlify.app.

Features

Every feature has a reference page and a runnable, self-contained example in playground/:

Feature Summary Docs Example
🧭 Full-screen TUI Scrollable panel browser: hubs drill into sub-panels to any depth, contextual key-hint footer, ? help overlay panels 03-panels
πŸͺŸ Modal panels A panel marked ->modal() opens as a centered dialog over its dimmed parent, with its own submit/cancel buttons panels 03-panels
⚑ Inline editing A field's editor opens in place on the panel row; ->standalone() opts a field out to full-screen panels 04-inline-editing
🧩 Widgets 13 field types: text, number, calendar, textarea, password, select, reorder, suggest, search, file picker, confirm, toggle, pause widgets 02-widgets
πŸ—οΈ Builder-driven The form is declared in PHP with a fluent builder; the common cases need no code configuration 01-quickstart
πŸŽ›οΈ Interactive or unattended run() picks the mode: keyboard on a terminal, otherwise JSON payload + TUI_<ID> environment variables headless collection 05-headless
πŸ”— Derived values Fields computed from other answers via {{field}} templates and str2name transforms, settling to a fixpoint configuration 06-form-logic
πŸ”€ Conditional fields ->when() conditions (eq/ne/in/contains, composable with all/any/not) drive visibility; form-level fix-ups reconcile answers configuration 06-form-logic
βš™οΈ Declared behaviour Dynamic defaults, validation and transforms as field closures, or as per-field handler classes resolved by naming convention field behaviour 07-field-behaviour
πŸ” Discovery Update mode detects defaults from an existing directory: dotenv keys, JSON dot-paths, path checks, directory scans discovery 08-discovery
πŸ“¦ Self-describing answers Answers carry provenance; toSummary() renders a badged, panel-grouped report and toJson() the machine result; schema(), validate() and agentHelp() describe the form itself self-describing answers 05-headless
🎨 Themes Six built-ins selected by name; a custom theme is a DefaultTheme subclass overriding palette atoms and render methods themes 09-themes
⌨️ Key bindings Presets (default, vim, or a class) plus per-binding overrides scoped to navigation or a widget type; conflicts throw at setup key bindings 10-key-bindings
✨ Display modes Dark/light follows the terminal background, glyphs follow the locale, colour honours NO_COLOR; all three can be forced display modes 11-display-modes
πŸ§ͺ Test harness TuiTester drives the real panel loop from scripted keystrokes, no TTY; assert on answers, output and rendered frames testing 12-testing
🌍 Translations A Translator with per-language catalog files localizes chrome and questions, falling back to English translations 13-translations

Installation

composer require drevops/tui

Quick start

Declare a form with the Form builder, then drive it through the Tui facade - the one class that wires the engine, resolver, schema tools and TUI:

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

$form = Form::create('My form')
  ->panel('general', 'General', fn(PanelBuilder $p) => $p->text('name', 'Your name')->required());

$tui = new Tui($form, handler_namespaces: ['App\\Handler']);

$answers = $tui->run();

The facade's surface:

Call Purpose
run($prompts, $version, $directory, $interactive) Collect answers; interactive on a TTY, headless otherwise (or forced via $interactive)
collect($prompts, $directory, $update, $version) Headless collection from JSON + environment; $update enables discovery
interact() The interactive panel TUI, explicitly
schema() / validate($answers) / agentHelp() Describe the form as a JSON schema, validate a payload against it, emit agent-facing instructions
theme($name, $options) / keys($preset, $overrides) Select the theme and key bindings
color($bool) / unicode($bool) / footer($bool) / clearOnExit($bool) / translator($t) Display and runtime switches
form() / engine() / registry() The internals, for finer control

Read the full guide at phptui.dev, and browse playground/ for complete, runnable examples - one directory per feature in the table above.

Widgets

There's a widget for most things you'd want to ask: text entry, numbers and dates, single and multiple choice, fuzzy search, filesystem browsing, and simple gates. Each one links to its full reference on phptui.dev, and every card below plays back the real interaction in whichever colour scheme - light or dark - your reader is using.

Calendar widget Calendar
A month calendar returning a normalized ISO YYYY-MM-DD; arrows move by day and week.
Confirm widget Confirm
Yes/No toggle; arrows or Space switch, y/n set the choice directly, Enter accepts.
File picker widget File picker
Browse the filesystem for a path; arrows move, β†’ enters a directory and ← returns to its parent. Add ->multiple() for several paths.
Number widget Number
Integer entry (digits with an optional leading minus) accepted as an int, with optional min, max and step.
Password widget Password
Text rendered as a mask in the editor, the field row and the summary; the accepted value stays plain for the consumer, and can be made revealable.
Pause widget Pause
An acknowledgement gate; Enter or Space accepts. Unattended runs auto-acknowledge it, so it never blocks automation.
Reorder widget Reorder
Rank a list by moving items into the order you want; Space picks an item up, arrows carry it through the list, Enter accepts.
Search widget Search
Single choice with a visible filter line; typing fuzzy-matches and ranks the labels, exact and prefix matches leading.
Select widget Select
Single choice from a list; arrows move, Enter accepts the highlighted option, long lists page around the cursor.
Suggest widget Suggest
Free text with autocomplete over a fixed option set: as you type, suggestions are fuzzy-matched and ranked by relevance.
Text widget Text
Single-line input with a movable caret; type to insert, arrows move, Backspace deletes, Enter accepts.
Textarea widget Textarea
Multi-line input; Enter inserts a newline, arrows move between lines, Tab accepts, with an external-editor handoff.
Toggle widget Toggle
An inline switch between two labelled values; arrows or Space flip, the first letter of each label sets it directly.

Themes

Six themes ship built-in, selected by name on the Tui facade. Dark or light is a separate mode display option auto-detected from the terminal background, so every adaptive theme serves both:

$tui = (new Tui($form))->theme('midnight');
Name Palette
default Cyan accents on an auto-detected dark or light base - the out-of-the-box look.
midnight Violet accents, green values, pink highlights.
frost Arctic frost-blue accents, sage values, sand highlights.
ember Burnt-orange accents, olive values, gold highlights.
mono Hue-free - bold weight, grey levels and reverse video for maximum compatibility.
dos Retro MS-DOS: the bright white/cyan/yellow CGA palette in a double-line window, made for a blue terminal background.

Each renders across every widget and degrades to plain text without ANSI. Here the dark palette (left) and the light palette (right); the themes docs also show every theme inside the rounded border frame:

midnight

midnight theme, dark mode midnight theme, light mode

frost

frost theme, dark mode frost theme, light mode

ember

ember theme, dark mode ember theme, light mode

mono

mono theme, dark mode mono theme, light mode

dos - the CGA blue screen, painted regardless of the terminal background

dos theme, dark terminal dos theme, light terminal

Write your own by subclassing DefaultTheme and overriding just its palette - see the theming guide and the playground's OceanTheme.

Maintenance

composer install
composer lint
composer test

Contributing

See the Contributing guide for the development workflow, quality gates and how the documentation and SVG assets are built.


This repository was created using the Scaffold project template

About

WIP! DO NOT USE! Terminal user interfaces for PHP

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Sponsor this project

  •  

Contributors

Languages