-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Redesign completion system #1484
Comments
I'm interested in this refactor and I could probably help. 🤓 I recently started a PR for click-completion: click-contrib/click-completion#34, to fix user-provided completions. And I got to see how it ends up re-implementing a lot of the code from Click itself, it's not exactly the same, but it's quite similar, and newer features/additions to Click are not there (yet). I imagine at some point the two codebases started to diverge and it became every time more difficult to re-sync For example, adding basic PowerShell completion support for Click would probably be quite straightforward given there are scripts for Bash, Zsh, and Fish. I have been playing with it and it's fairly straightforward for PowerShell Core (6 and 7), and it can be installed/tested in Linux and others. Unfortunately, Windows comes with PowerShell 5 by default (although a newer version can be easily installed). For PowerShell 5 it seems the only way is with the (a bit more complex) approach done in One thing I've seen is that the current completion is relatively coupled with how Bash completion works, with the I think this might make the shell scripts/templates a bit more complex, and so, probably a bit more difficult to maintain. I think it could be easier if the shell scripts (in each shell language) to handle completion for each shell are as simple as possible, and most of the glue code is done in Python instead of in each shell language (inside of a Python string). The invocation with For example, if that's acceptable, adding basic PowerShell completion would be quite straightforward. But wrapping it around Just my 2 cents. Another independent idea, currently For example, click-completion is re-implementing the full Another example, I'm currently monkeypatching click-completion's That's in Typer CLI: https://github.com/tiangolo/typer-cli/blob/master/typer_cli/main.py#L149 |
This is basically the current situation which I think we should move away from. Right now we provide fairly simple shell scripts that call out to Click and expect a newline delimited list of completions back. For the way Bash completion works, this is sort of fine. But for ZSH, this completely breaks path handling, for example, because selecting a menu completion of partial paths always adds a space, even if you type Instead I'd like to be able to take advantages of the features of any given shell. For example, instead of returning a list of paths, we should be telling the ZSH script to use the Here's a design I've been thinking about that could accomplish this and would hopefully be reasonable to maintain in the future. Right now, parameters take an As you suggested, we should completely split the handlers for each shell, so there is a dedicated handler for each that can take shell-specific environment variables and produce shell-specific results. Instead of only returning a list of completions, the parameter completion methods should now be able to return something that indicates a different shell completion behavior. For example, the Here's a very rough outline of an API for this. What would be nice about splitting these up into classes is that we could provide a way for an extension to plug in support for a new shell, such as PowerShell. class ShellComplete:
def __init__(self, complete_var):
# get shell-specific environment variables
# set instance variables
def source(self):
# return bash completion script
def complete(self):
# get completion response from parameter/type
# handle special commands like "files" in shell-specific way
# bash doesn't quote special characters for custom responses, so do quoting here, etc.
# output command type (plain, files, etc.)
# output any other information for the command type, such as custom completions
class BashComplete(ShellComplete):
... The final piece of this is that the shell scripts would need to get more complicated, as they would now use the first line of the response to decide what to do. For example, ZSH decides to call We might also consider sending the "version" of the script back to Click, so that it can show a warning if we make more incompatible changes to the completion system in the future. "Completion definition outdated, consult {prog_name} docs to generate an updated completion script." |
Get it, yep, that looks great. 👍 |
Here's an outline of the current and proposed completion workflow. Setup (won't change):
Registering the completion script (current):
New implementation:
Triggering completion (won't change):
Calculating completions (current):
New implementation:
Bash is pretty simple, but zsh and fish can do a lot more. Things that we might return:
We don't have to do all that now, we mostly want to ensure we have an extensible system that could be extended to send that. Other bonus things we want to do later:
Unfortunately, bash and zsh documentation is detailed while also being impenetrable. That said, here are a bunch of docs links:
|
@kx-chen and I will be working on this! 😃 |
As a addition to the known issue with file/path completion I have one more areas to improve completion. |
The new system has been merged. The documentation can be found here for now: https://click.palletsprojects.com/en/master/shell-completion/. Pretty much everything @tiangolo and I discussed is implemented in some way. |
I've been trying to review #1403 (comment), which adds type-based completions, and it made me realize just how messy completion is, both within Click and with how the shells implement and document their systems.
Right now, a project would provide a much better user experience right now by providing their own handwritten completion script rather than using Click's. Due to its dynamic nature, Click probably won't be able to generate an equivalent script, but I think we can at least get closer.
Because Click only returns completion values, the shell has no metadata about what's actually being completed. This means we keep having to re-implement things that the shell should be doing, such as escaping special characters, adding spaces (except for directories), sorting, etc. And if the user wants to provide their own completions, they have to remember to do all that too.
There's no reason we just have to return completions. We already support returning descriptions, presumably we could extend that more. Wouldn't it be cool if Click could indicate to the completion script that it should use other functions that Bash or ZSH provide?
The text was updated successfully, but these errors were encountered: