Skip to content

Commit

Permalink
Document console completion
Browse files Browse the repository at this point in the history
  • Loading branch information
wouterj committed Apr 16, 2022
1 parent 0718196 commit be5a15d
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 33 deletions.
Binary file added _images/components/console/completion.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
142 changes: 109 additions & 33 deletions console.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,90 @@ The Symfony framework provides lots of commands through the ``bin/console`` scri
created with the :doc:`Console component </components/console>`. You can also
use it to create your own commands.

The Console: APP_ENV & APP_DEBUG
---------------------------------
Running Commands
----------------

Each Symfony application comes with a large set of commands. You can use
the ``list`` command to view all available commands in the application:

.. code-block:: terminal
$ php bin/console list
...
Available commands:
about Display information about the current project
completion Dump the shell completion script
help Display help for a command
list List commands
assets
assets:install Install bundle's web assets under a public directory
cache
cache:clear Clear the cache
...
If you find the command you need, you can run it with the ``--help`` option
to view the command's documentation:

.. code-block:: terminal
$ php bin/console assets:install --help
APP_ENV & APP_DEBUG
~~~~~~~~~~~~~~~~~~~

Console commands run in the :ref:`environment <config-dot-env>` defined in the ``APP_ENV``
variable of the ``.env`` file, which is ``dev`` by default. It also reads the ``APP_DEBUG``
value to turn "debug" mode on or off (it defaults to ``1``, which is on).

To run the command in another environment or debug mode, edit the value of ``APP_ENV``
and ``APP_DEBUG``.
and ``APP_DEBUG``. You can also define this env vars when running the
command, for instance:

.. code-block:: terminal
# clears the cache for the prod environment
$ APP_ENV=prod bin/console cache:clear
.. _console-completion-setup:

Console Completion
~~~~~~~~~~~~~~~~~~

.. versionadded:: 5.4

Console completion for Bash was introduced in Symfony 5.4.

If you are using the Bash shell, you can install Symfony's completion
script to get auto completion when typing commands in the terminal. All
commands support name and option completion, and some can even complete
values.

.. image:: /_images/components/console/completion.gif

First, make sure you installed and setup the "bash completion" package for
your OS (typically named ``bash-completion``). Then, install the Symfony
completion bash script *once* by running the ``completion`` command in a
Symfony app installed on your computer:

.. code-block:: terminal
$ php bin/console completion bash | sudo tee /etc/bash_completion.d/console-events-terminate
# after the installation, restart the shell
Now you are all set to use the auto completion for all Symfony Console
applications on your computer. By default, you can get a list of complete
options by pressing the Tab key.

.. tip::

Many PHP tools are build using the Symfony Console component (e.g.
Composer, PHPstan and Behat). If they are using version 5.4 or higher,
you can also install their completion script to enable console completion:

.. code-block:: terminal
$ php vendor/bin/phpstan completion bash | sudo tee /etc/bash_completion.d/phpstan
Creating a Command
------------------
Expand All @@ -38,11 +113,6 @@ want a command to create a user::
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:create-user';

protected function configure(): void
{
// ...
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
// ... put here the code to create the user
Expand Down Expand Up @@ -74,37 +144,41 @@ want a command to create a user::
The ``Command::INVALID`` constant was introduced in Symfony 5.3

Configuring the Command
-----------------------
~~~~~~~~~~~~~~~~~~~~~~~

You can optionally define a description, help message and the
:doc:`input options and arguments </console/input>`::
:doc:`input options and arguments </console/input>` by overriding the
``configure()`` method::

// ...
// the command description shown when running "php bin/console list"
protected static $defaultDescription = 'Creates a new user.';
// src/Command/CreateUserCommand.php

// ...
protected function configure(): void
class CreateUserCommand extends Command
{
$this
// If you don't like using the $defaultDescription static property,
// you can also define the short description using this method:
// ->setDescription('...')
// the command description shown when running "php bin/console list"
protected static $defaultDescription = 'Creates a new user.';

// the command help shown when running the command with the "--help" option
->setHelp('This command allows you to create a user...')
;
// ...
protected function configure(): void
{
$this
// the command help shown when running the command with the "--help" option
->setHelp('This command allows you to create a user...')
;
}
}

Defining the ``$defaultDescription`` static property instead of using the
``setDescription()`` method allows to get the command description without
instantiating its class. This makes the ``php bin/console list`` command run
much faster.
.. tip::

Defining the ``$defaultDescription`` static property instead of using the
``setDescription()`` method allows to get the command description without
instantiating its class. This makes the ``php bin/console list`` command run
much faster.

If you want to always run the ``list`` command fast, add the ``--short`` option
to it (``php bin/console list --short``). This will avoid instantiating command
classes, but it won't show any description for commands that use the
``setDescription()`` method instead of the static property.
If you want to always run the ``list`` command fast, add the ``--short`` option
to it (``php bin/console list --short``). This will avoid instantiating command
classes, but it won't show any description for commands that use the
``setDescription()`` method instead of the static property.

.. versionadded:: 5.3

Expand Down Expand Up @@ -144,7 +218,7 @@ available in the ``configure()`` method::
}

Registering the Command
-----------------------
~~~~~~~~~~~~~~~~~~~~~~~

In PHP 8 and newer versions, you can register the command by adding the
``AsCommand`` attribute to it::
Expand All @@ -155,6 +229,8 @@ In PHP 8 and newer versions, you can register the command by adding the
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;

// the "name" and "description" arguments of AsCommand replace the
// static $defaultName and $defaultDescription properties
#[AsCommand(
name: 'app:create-user',
description: 'Creates a new user.',
Expand All @@ -176,8 +252,8 @@ If you can't use PHP attributes, register the command as a service and
:ref:`default services.yaml configuration <service-container-services-load-example>`,
this is already done for you, thanks to :ref:`autoconfiguration <services-autoconfigure>`.

Executing the Command
---------------------
Running the Command
~~~~~~~~~~~~~~~~~~~

After configuring and registering the command, you can run it in the terminal:

Expand Down Expand Up @@ -468,7 +544,7 @@ call ``setAutoExit(false)`` on it to get the command result in ``CommandTester``

$application = new Application();
$application->setAutoExit(false);

$tester = new ApplicationTester($application);

.. note::
Expand Down
86 changes: 86 additions & 0 deletions console/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,90 @@ The above code can be simplified as follows because ``false !== null``::
$yell = ($optionValue !== false);
$yellLouder = ($optionValue === 'louder');

Adding Argument/Option Value Completion
---------------------------------------

.. versionadded:: 5.4

Console completion was introduced in Symfony 5.4.

If :ref:`Console completion is installed <console-completion-setup>`,
command and option names will be auto completed by the shell. However, you
can also implement value completion for the input in your commands. For
instance, you may want to complete all usernames from the database in the
``name`` argument of your greet command.

To achieve this, override the ``complete()`` method in the command::

// ...
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;

class GreetCommand extends Command
{
// ...

public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('names')) {
// the user asks for completion input for the "names" option

// the value the user already typed, e.g. when typing "app:greet Fa" before
// pressing Tab, this will contain "Fa"
$currentValue = $input->getCompletionValue();

// get the list of username names from somewhere (e.g. the database)
// you may use $currentValue to filter down the names
$availableUsernames = ...;

// then add the retrieved names as suggested values
$suggestions->suggestValues($availableUsernames);
}
}
}

That's all you need! Assuming users "Fabien" and "Fabrice" exist, pressing
tab after typing ``app:greet Fa`` will give you these names as a suggestion.

.. tip::

The bash script will automatically filter the suggested values based on
the existing input from the user. You do not have to implement any
filter logic in the command.

You may use ``CompletionInput::getCompletionValue()`` to get the
current input if that helps improving performance (e.g. by reducing the
number of rows fetched from the database).

Testing the Completion script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Console component comes with a special
:class:`Symfony\\Component\\Console\\Test\\CommandCompletionTester`` class
to help you unit test the completion logic::

// ...
use Symfony\Component\Console\Application;

class GreetCommandTest extends TestCase
{
public function testComplete()
{
$application = new Application();
$application->add(new GreetCommand());

// create a new tester with the greet command
$tester = new CommandCompletionTester($application->get('app:greet'));

// complete the input without any existing input (the empty string represents
// the position of the cursor)
$suggestions = $tester->complete(['']);
$this->assertSame(['Fabien', 'Fabrice', 'Wouter'], $suggestions);

// complete the input with "Fa" as input
$suggestions = $tester->complete(['Fa']);
$this->assertSame(['Fabien', 'Fabrice'], $suggestions);
}
}

.. _`docopt standard`: http://docopt.org/
7 changes: 7 additions & 0 deletions page_creation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ the debugging routes in the next section.

You'll learn about many more commands as you continue!

.. tip::

If you are using the Bash shell, you can set-up completion support.
This autocompletes commands and other input when using ``bin/console``.
See :ref:`the Console document <console-completion-setup>` for more
information on how to set-up completion.

.. _web-debug-toolbar:

The Web Debug Toolbar: Debugging Dream
Expand Down

0 comments on commit be5a15d

Please sign in to comment.