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] Fix various completion edge cases #47432

Open
wants to merge 1 commit into
base: 5.4
Choose a base branch
from

Conversation

Seldaek
Copy link
Member

@Seldaek Seldaek commented Aug 30, 2022

Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #...
License MIT
Doc PR symfony/symfony-docs#...

Refs composer/composer#11029

There are two things I am trying to fix here:

  • composer require yiisoft/yii-[TAB] works, but composer req yiisoft/yii-[TAB] does not work
  • composer up suggets upgrade update but both are aliases to the same command, so I fixed it to make it always just suggest one name, which lets the shell complete to composer update and then I can tab again to get more relevant completions.

The fixes work almost.. I have one problem for which I need help from someone (maybe @wouterj?).

See the changes in CompleteCommand. The current code is doing smth like:

  • try to find a command
  • if none found, autocomplete command names
  • if a command is found and the completion does not match the command name/aliases, suggest command name
  • otherwise bind the command and forward completion to the command

This is problematic because it breaks the 1st case I mentioned above, and it also is just fairly dodgy if you are trying to complete an arg with the command's name as input (e.g. composer require require) it will kinda stay stuck on suggesting the command's name even tho you are completing another arg here.

So I am trying to change it to a flow like:

  • try to find a command
  • if a command is found check where the completion input/caret is.
  • if the caret is at the end of the command name, complete that
  • otherwise bind the command and then check what can be completed

But it seems like CompletionInput does not work correctly there.. see these few examples from the completion debug output after I added some extra logging:

            $command = $this->findCommand($completionInput, $output);
            $this->log('  START, completing command name ("'.$completionInput->getCompletionName().'/'.$completionInput->getCompletionType().'")');
            if (null !== $command && !$completionInput->mustSuggestArgumentValuesFor('command')) {
                $command->mergeApplicationDefinition();
                $completionInput->bind($command->getDefinition());
                $this->log('  BOUND, completing command name ("'.$completionInput->getCompletionName().'/'.$completionInput->getCompletionType().'")');
            }
Input: ("|" indicates the cursor position)
  c req|
Command:
  /var/www/composer/bin/composer _complete -sbash -c1 -S2.4.999-dev+source -ic -ireq
Messages:
  START, completing command name ("command/argument_value")

Input: ("|" indicates the cursor position)
  c require |
Command:
  /var/www/composer/bin/composer _complete -sbash -c2 -S2.4.999-dev+source -ic -irequire
Messages:
  START, completing command name ("/none")
  BOUND, completing command name ("packages/argument_value")

Input: ("|" indicates the cursor position)
  c require foo|
Command:
  /var/www/composer/bin/composer _complete -sbash -c2 -S2.4.999-dev+source -ic -irequire -ifoo
Messages:
  START, completing command name ("command/argument_value")

As you can see when the input is c req| it completes the command argument as it should, then with c require | it also works as it should, detecting the space and moving to none completion. But then as soon as you have some more text it goes back to think it is completing the command argument and that makes no sense.

I am too dumb or tired to figure out what's going on in the CompletionInput class or its tests, so I'd appreciate input there :)

@Seldaek Seldaek requested a review from chalasr as a code owner August 30, 2022 14:54
@carsonbot carsonbot added this to the 5.4 milestone Aug 30, 2022
@carsonbot carsonbot changed the title Fix various completion edge cases [Console] Fix various completion edge cases Aug 31, 2022
@carsonbot
Copy link

Hey!

I think @technojit has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@wouterj
Copy link
Member

wouterj commented Sep 29, 2022

I am too dumb or tired to figure out what's going on in the CompletionInput class or its tests, so I'd appreciate input there :)

The CompletionInput is a monster, so you sure shouldn't feel dumb if you cannot follow it (it also took me an hour to relearn enough of the logic to find the issue).

In fact, you've found a bug that also exists on 5.4, I've submitted a fix: #47726 When that one is merged up, this one should work correctly.

I've played a lot with this PR locally in order to find this bug. The behavior looks very promising to me! Thanks for working on these edge-cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants