phpbashsymfonyubuntusymfony-console

Autocomplete doesn't work for a Symfony Console script


I have a Symfony Console app and I want to use it with autocomplete but autocoplite doesn't work. When I click tab nothing happens.

My app works successfully from the command line if I type like this:

./myapp generate-constants nomenclature

Then it prints

Hello World!, nomenclature

This is my script named myapp

#!/usr/bin/env php
<?php
require 'bootstrap.php';

use MyApp\Core\Console\GenerateConstantsCommand;
use Symfony\Component\Console\Application;

$app = new Application();
$app->add(new GenerateConstantsCommand());
$app->run();

And this is GenerateConstantsCommand.php

<?php
namespace MyApp\Core\Console;
use LogicException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;

class GenerateConstantsCommand extends Command
{
    protected function configure()
    {
        $this->setName('generate-constants')
            ->setDescription('Generate constsants')
            ->setHelp('Demonstration of custom commands created by Symfony Console component.')
            ->addArgument('nomenclature', InputArgument::REQUIRED, 'Pass the nomenclature');
    }


    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln(sprintf('Hello World!, %s', $input->getArgument('nomenclature')));
        return 0;
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('nomenclature')) {
            $suggestions->suggestValues(['json', 'xml']);
        }
    }
}

What I am doing wrong? Why autocomplete doesn't work?

Also I have tried with stecman/symfony-console-completion but when I run eval $(./myapp _completion --generate-hook) the cursor goes to new line and stays there forever.

I use Bash 5.0.17(1)-release, Ubuntu 20.04.4 LTS, Symfony Console 5.4.7, and PHP 7.3.26.


Solution

  • As per the documentation:

    Make sure to install the bash-completion package: sudo apt-get install -y bash-completion.

    Then run the following command ONCE (installing Symfony's bash completion script): php bin/console completion bash | sudo tee /etc/bash_completion.d/console-events-terminate.

    Restart your terminal and it should work.

    This is the example command that I used for testing and shell auto-completion works as expected:

    <?php declare(strict_types = 1);
    
    namespace App\Command;
    
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Completion\CompletionInput;
    use Symfony\Component\Console\Completion\CompletionSuggestions;
    use Symfony\Component\Console\Input\InputArgument;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    use function is_string;
    use function sprintf;
    
    class TestCommand extends Command
    {
        protected function configure(): void
        {
            $this->setName('app:test')
                ->setDescription('Test command')
                ->setHidden(false)
                ->addArgument('format', InputArgument::REQUIRED, 'The format');
        }
    
        public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
        {
            if (true === $input->mustSuggestArgumentValuesFor('format')) {
                $suggestions->suggestValues(['json', 'xml']);
            }
        }
    
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            $format = $input->getArgument('format');
            if (false === is_string($format)) {
                $output->writeln('Given format is not a string');
                return Command::FAILURE;
            }
            $output->writeln(sprintf('Format: %s', $format));
            return Command::SUCCESS;
        }
    }
    

    enter image description here