Symfony Console
Tui integrates naturally with Symfony Console. Create a Tui inside
a command's execute() method, run it and return the exit code.
Basic Command
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Tui\Event\InputEvent;
use Symfony\Component\Tui\Input\Keybindings;
use Symfony\Component\Tui\Tui;
use Symfony\Component\Tui\Widget\EditorWidget;
use Symfony\Component\Tui\Widget\TextWidget;
#[AsCommand(name: 'app:editor')]
final class EditorCommand extends Command
{
protected function execute(
InputInterface $input,
OutputInterface $output,
): int {
$tui = new Tui();
$keys = new Keybindings(['quit' => ['ctrl+c']]);
$tui->addListener(
static function (InputEvent $event) use ($tui, $keys): void {
if ($keys->matches($event->getData(), 'quit')) {
$tui->stop();
}
}
);
$editor = new EditorWidget();
$editor->onSubmit(fn () => $tui->stop());
$tui->add(new TextWidget('Type your message:'));
$tui->add($editor);
$tui->setFocus($editor);
$tui->run();
if ($editor->wasSubmitted()) {
$output->writeln('You wrote:');
$output->writeln($editor->getText());
}
return Command::SUCCESS;
}
}
The Tui takes full control of the terminal while it runs. When
run() returns, the terminal is restored and you can use the
Console $output object normally.
Output After the Tui Stops
Query widget state after run() returns to produce Console
output:
1 2 3 4 5 6 7 8
$tui->run();
$selected = $list->getSelectedItem();
if (null !== $selected) {
$output->writeln('Selected: '.$selected['label']);
}
return Command::SUCCESS;
Using Console Input
Read Console arguments and options before starting the Tui to configure widgets:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
protected function execute(
InputInterface $input,
OutputInterface $output,
): int {
$name = $input->getArgument('name');
$tui = new Tui();
$keys = new Keybindings(['quit' => ['ctrl+c']]);
$tui->addListener(
static function (InputEvent $event) use ($tui, $keys): void {
if ($keys->matches($event->getData(), 'quit')) {
$tui->stop();
}
}
);
$editor = new EditorWidget();
$editor->setText($name);
// ...
}
Stylesheets
Pass a stylesheet to the Tui constructor to theme your command:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\Tui\Style\Style;
use Symfony\Component\Tui\Style\StyleSheet;
use Symfony\Component\Tui\Style\VerticalAlign;
$stylesheet = new StyleSheet([
':root' => new Style(
gap: 1,
verticalAlign: VerticalAlign::Bottom,
),
]);
$tui = new Tui($stylesheet);
See Styling for the full styling documentation.
Handling Signals
Symfony Console registers signal handlers for SIGINT and
SIGTERM. The Tui uses its own terminal handling, so signal
delivery works as expected. Intercepting Ctrl+C via an InputEvent
listener catches the key press at the input level, before it becomes
a signal.