diff --git a/_images/components/console/completion.gif b/_images/components/console/completion.gif new file mode 100644 index 00000000000..011ae0b935e Binary files /dev/null and b/_images/components/console/completion.gif differ diff --git a/console.rst b/console.rst index 9de02a4b882..243ab6bc1e8 100644 --- a/console.rst +++ b/console.rst @@ -9,15 +9,90 @@ The Symfony framework provides lots of commands through the ``bin/console`` scri created with the :doc:`Console component `. 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 ` 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 ------------------ @@ -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 @@ -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 `:: +:doc:`input options and arguments ` 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 @@ -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:: @@ -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.', @@ -176,8 +252,8 @@ If you can't use PHP attributes, register the command as a service and :ref:`default services.yaml configuration `, this is already done for you, thanks to :ref:`autoconfiguration `. -Executing the Command ---------------------- +Running the Command +~~~~~~~~~~~~~~~~~~~ After configuring and registering the command, you can run it in the terminal: @@ -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:: diff --git a/console/input.rst b/console/input.rst index 3bbba7e5fce..2257e153bd8 100644 --- a/console/input.rst +++ b/console/input.rst @@ -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 `, +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/ diff --git a/page_creation.rst b/page_creation.rst index a8d97aac618..9819764c81e 100644 --- a/page_creation.rst +++ b/page_creation.rst @@ -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 ` for more + information on how to set-up completion. + .. _web-debug-toolbar: The Web Debug Toolbar: Debugging Dream