Skip to content

Symfony Console

Edit this page

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.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version