Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Console] Bash completion integration#42251
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
47efd2b to0623991CompareNyholm commentedJul 25, 2021
Thank you. This looks super cool. =) |
0623991 to5986f27Comparewouterj commentedJul 25, 2021
Thanks :) I've updated this PR to complete most of the important TODO items (and also updated the usage in the PR description). It still needs more unit tests (I used a local shell script to test things, I need to convert it to unit tests) and I need to add a line to the CHANGELOG. Other than that, I think this in a final state, so ready for reviews :) |
5986f27 to8873ba0CompareUh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
8873ba0 tocff89a6Comparecff89a6 toca0b1dbCompareOskarStark commentedAug 1, 2021
Should we target |
Nyholm commentedAug 1, 2021
My general opinion is that we mark too many classes experimental. But I let@wouterj decide in this specific case. |
wouterj commentedAug 2, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
The public API side of this feature is quite minimal (one method in Adding support for ZSH might break things, but a community member already stepped up to provide a PR for this if this is merged, so this can be caught before the 5.4 release. Other than that, all complexity of this feature is in the I guess the lack of reviewers in this PR indicates that it's probably a bit difficult to review. Some hints:
|
dkarlovi commentedAug 3, 2021
@wouterj I'm looking for a simple way to test this in my actual app, IMO it would be most beneficial to figure it all out. I'll provide my findings if I find a way to do that. Other than that, a cool sample might be to make a fork of Composer with this enabled. It might make it simple to visualize once you can test it for yourself easily. |
dkarlovi commentedAug 3, 2021
Also, this is an absurdly valuable feature, thank you a lot for working on this! 😍 |
wouterj commentedAug 3, 2021
@dkarlovi if you have an app running Symfony 5.3, you can try to clone my fork locally and use the And then use the |
This comment has been minimized.
This comment has been minimized.
dkarlovi commentedAug 5, 2021
@wouterj which Bash did you use to test this? For me, if I test with To get it to work, I needed to change it like this: Also, the |
src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
dkarlovi commentedAug 5, 2021
One thing which might be neat to have is to provide a flag for the dumper, something like or similar, where it would create additional code in there to help you debug it if you're working on it. Might be too niche, maybe wait for use cases, but as I was testing this, I needed to edit the completion function to add them myself. |
theofidry left a comment• edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
A few minor comments/nitpicks. A big 👍 for this feature
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
| $option =$this->getOptionFromToken($optionToken); | ||
| if (null ===$option && !$this->isCursorFree()) { | ||
| $this->completionType =self::TYPE_OPTION_NAME; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I tend to find this sort of API a bit brittle: it's easy to miss that all properties need to be set together. I am also not sure if this class is supposed to be extendable or not (it is not final at least, didn't check how hard/easy it would be to extend).
WDYT of adding a private accessorsetCompletionValues(string $type, string $anme, string $value)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I do agree with you that this a bit brittle, but this is indeed not meant to be extended (I've made the class final now - thanks to your comment). The same comment as#42251 (comment) applies here imho.
Besides, we don't always set all 3 properties at the same time, sometimes only 1 or 2.
Uh oh!
There was an error while loading.Please reload this page.
| $relevantToken =$this->getRelevantToken(); | ||
| if ('-' ===$relevantToken[0]) { | ||
| // the current token is an input option: complete either option name or option value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
what about moving the different blocks into dedicated methods? e.g.addCompletionForInputOption()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
As with all parsing, it's really horrible code (lots of nested if statements) but not so easy to clean-up.
In this case,$relevantToken[0] === '-' can have multiple meanings: Either it's just- or--, indicating the next tokens are all argument values. Or it's the start of an option (short or long). And things get even more messy with things like-eprod,-vvv and-ev (indicating respectively an option with its value, an option without value, and 2 options).
I also don't think it's worth cleaning this code up. All "messiness" is contained in a single method, which will not be touched regularly (how we parse options, arguments and values is pretty static).
f071e5f to7810d19Comparewouterj commentedOct 18, 2021
Thanks for the review@theofidry! PR updated and rebased. We have a new failure (7.2) but I can't find any error logs whatsoever about this failure. |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
7810d19 toe0a174fComparewouterj commentedOct 19, 2021
Thanks, PR updated. |
fabpot commentedOct 19, 2021
Thank you@wouterj. |
This PR was squashed before being merged into the 5.4 branch.Discussion----------[Console] Bash completion integration| Q | A| ------------- | ---| Branch? | 5.4| Bug fix? | no| New feature? | yes| Deprecations? | no| Tickets | Fix #38275| License | MIT| Doc PR | -This is a first shot at implementing interactive bash completion support in the Console component. Besides completing option and command names, commands can override `Command::complete()` to implement completing values.I've added an example code to the `secrets:remove` command, which now supports autocompletion quite nicely: And support for other applications using `symfony/console` is automatically included (if the autocompletion script is installed for that specific application):This PR only implements Bash completion. Zsh and Fish have much more sophisticated completion systems, but I propose to keep those for a future PR if there is a need for this.### How it works1. A bash completion function (`_console`) is defined by `bin/console completion bash` for the `console` command (name of the "binary" file)2. This completion function calls the local `bin/console _complete` command to come up with suggestions3. Bash parses these suggestions and shows them to the user.This has one drawback: the `_console` function is defined globally only once. This means we cannot easily change it, as it would break if you run different Symfony versions. We should probably add versioning (e.g. `bin/console _complete --version=1.0`) and don't suggest anything if the version doesn't match.<s> **Maybe it would be safer to mark this feature as experimental and target 6.0, to allow us to fine tune the shell related sides over the lifespan of 6.x?** </s>symfony/symfony#42251 (comment)### Steps to test yourselfLoad this PR in your project, open a bash shell and run this command to "install" completion for this project:```bin/console completion bash > /etc/bash_completion.d/console````Then reload the bash shell and enjoy autocompletion.### TODO* [x] Autocompleting in the middle of the input doesn't work yet (i.e. `bin/console --en<TAB> cache:clear`)* [x] Better error handling* [x] Add a `bin/console completion` command to dump the `_console` file, so users can install this locally* [x] Add some versioning, to allow us to change the `_console` file in the future* [x] <s>See how we can better support standalone usage (e.g. Composer)</s> Tested on Laravel's artisan, works flawlesslyCommits-------e0a174f877 [FrameworkBundle] Add CLI completion to secrets:remove82ef399de3 [Console] Bash completion integration
| if (!file_exists($debugFile)) { | ||
| touch($debugFile); | ||
| } | ||
| $process =newProcess(['tail','-f',$debugFile],null,null,null,0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
what happens on windows (and yes, bash can be used on windows, which does not imply thattail is available in the PATH AFAICT) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This needs some more special casing. For example, you might not havesymfony/process installed.
| return$parseOptions; | ||
| } | ||
| privatefunctiongetOptionValueFromToken(string$optionToken):string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Is this function actually used?
| private$tokens; | ||
| private$currentIndex; | ||
| private$indexToArgumentIndex = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This property is not used.
Uh oh!
There was an error while loading.Please reload this page.
This is a first shot at implementing interactive bash completion support in the Console component. Besides completing option and command names, commands can override
Command::complete()to implement completing values.I've added an example code to the
secrets:removecommand, which now supports autocompletion quite nicely:And support for other applications using

symfony/consoleis automatically included (if the autocompletion script is installed for that specific application):This PR only implements Bash completion. Zsh and Fish have much more sophisticated completion systems, but I propose to keep those for a future PR if there is a need for this.
How it works
_console) is defined bybin/console completion bashfor theconsolecommand (name of the "binary" file)bin/console _completecommand to come up with suggestionsThis has one drawback: the
_consolefunction is defined globally only once. This means we cannot easily change it, as it would break if you run different Symfony versions. We should probably add versioning (e.g.bin/console _complete --version=1.0) and don't suggest anything if the version doesn't match.Maybe it would be safer to mark this feature as experimental and target 6.0, to allow us to fine tune the shell related sides over the lifespan of 6.x?#42251 (comment)Steps to test yourself
Load this PR in your project, open a bash shell and run this command to "install" completion for this project:
Then reload the bash shell and enjoy autocompletion.
TODO
bin/console --en<TAB> cache:clear)bin/console completioncommand to dump the_consolefile, so users can install this locally_consolefile in the futureSee how we can better support standalone usage (e.g. Composer)Tested on Laravel's artisan, works flawlessly