Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Console] Document console completion #16723

Merged
merged 1 commit into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 php 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 built 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
87 changes: 87 additions & 0 deletions console/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,91 @@ 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 shell is able to handle huge amounts of suggestions and 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);
Copy link
Member

@GromNaN GromNaN Apr 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users will think they need to filter the values themself, while this is done by the completion tool.
I think getCompletionValue usage is rare and reserved to cases when the list of values is too long (like the list of all packages on packagist composer/composer#10320 (comment))

}
}

.. _`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