-
-
Notifications
You must be signed in to change notification settings - Fork 682
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
Autocompletion for Path
#951
Comments
I've been looking into this for a bit (these are quite technical internals 🤓) So one route we could consider is something that's already marked in the code in
Once we have access to the type, we can do something like Click does, e.g. their Bash script:
which has specific support for different types. For @tiangolo: is this the direction we want to go in? Or did you have a different type of solution in mind? |
This comment was marked as off-topic.
This comment was marked as off-topic.
I was checking these internals for a bit, now I remember, yep, these are very technical details. 😅 I have been writing this reply below for the past few hours, so it's super long. 😅 I'm adding a lot of context and info here, maybe too much. And I might be wrong in some of my assumptions. But better to state the obvious than to hide the unknown. Also, I should probably clean up a bit of this text and put it in the docs somewhere. 😅 I think there's no central place on the internet explaining how to make these shell completion systems, at least not at this level of abstraction (only much lighter or much more low-level). So, sorry in advance for so much text. ☕ How shell completion worksI think this is an important detail that I have never documented anywhere, and I don't think it is documented anywhere in general, it's just discovered by anyone who dares to try to build or work on these things. 😅 The way these shell completion systems work, at least from what I have seen, is this, and it applies to all, Bash, Fish, Zsh, PowerShell (and I suspect any other):
The important points are:
How completion works in Click and TyperIn both Click and Typer, when you install completion, what it will do is add a script in the language of the specific shell to the startup config file for that shell. This script is a function/script, it takes the input of the current arguments passed to the program, and then it calls the same CLI program with some extra env vars that tell Click or Typer that completion is being requested and the current arguments. Then the CLI program is run with those extra env vars, Click or Typer detect them, and generate the completion for the existing commands or arguments. If there's a Python function to handle And here's a funny detail, all that stuff that is "printed", doesn't show up in the terminal, that output is parsed by the shell asking for completion (or in PowerShell, by the function calling the program to then call the PowerShell-specific thing to set completion options). And then those parsed options are shown in the completion in the shell. All this happens in an instant, when the user hits This shows some interesting details:
A couple of interesting conclusions:
Click 7, click-completion, TyperOn Click 7, it only had integrated support for simple Bash completions. There was a package click-completion that extended it by modifying stuff to support other shells: Fish, Zsh, and PowerShell. If I remember correctly, some of those completions were not working correctly, I think PowerShell was not working at all. I copied the shell scripts from there into Typer and tweaked them (e.g. fixing PowerShell). I think there were some issues with the others too (Zsh, Fish) but I don't remember exactly. Click 8Click 8 re-built the shell completion system. It added support for Fish and Zsh (but no PowerShell). One important but non-obvious difference from Click 7 to Click 8 is: the keyword to trigger completion passed in an env var from the shell (e.g. Bash) to Python was reversed from Click - Typer - completion at runtimeThere's another important and non-obvious difference between how Click expects things to happen vs Typer. ClickClick has docs to install the completion that assume that the program is available at shell startup time (or however that is called). So, the program has to be installed globally before the shell completion config is run. So, before the This means that if a Click program is installed in a venv, then shell completion is installed, the next time a new shell is started, it will show an error saying that the program was not found. And loading the venv would not solve the problem, it's too late by that point. So, Click programs don't support completion if they are installed in a venv, and installing completion for Click programs in venvs would break (at least a bit) part of the shell startup. TyperTyper's completion stuff only runs the CLI program once some completion is requested, not at shell startup time. This means that, it's possible to install some CLI app inside of a venv, install its completion, and it will work after the venv is activated. And it won't explode at shell startup time if the venv is not activated and the CLI program is not yet in the Click - Typer - completion sourceClickAnother difference is that, Click has two completion installation modes, one is to The other mode is to generate the completion shell script and save it to a file, and then TyperThe way Typer works, taken from how click-completion used to work, is that the completion shell script that is installed is very minimal, and it doesn't call the CLI program on shell startup. Instead, it declares a plain tiny function that will be in charge of handling completion, and configures the shell to use this function as the completion thing for the CLI program. When the shell needs completion and calls the function, that function will then (and only then) call the CLI program with the extra env vars. And the CLI program is the one in charge of printing things in the right format... except for PowerShell that needs to call a PowerShell function with the completion options. So, if a CLI program is installed in a venv, and completion is installed, it won't explode at shell startup time, and once the venv is loaded, it will work as normally. In fact, if two venvs have different versions of the same program, as the completion script is so minimal, it will work for both, and both could have different completions depending on the venv activated. This is an exotic case, but it's possible. Click 8 shell scriptsIn Click 8, there's support for setting a completion type, between The completion systems for the shells have a way to say "hey, do whatever completions apply to file paths", or the same for dirs. This is the new feature feature in Click, supporting setting those configs. But the way it is done in Click handles a lot of the logic in the shell-specific script. So, there's a fair amount of logic in each shell scripting language inside of strings in a Python file. I would prefer to avoid that or reduce it to the minimum in Typer. My reasons to avoid script shell syntax in Python strings:
I would prefer to handle the logic that is currently in those shell scripts in Click's source code in pure Python, and pass the information back to the shell script as ready as possible, to minimize the amount of shell-specific code. For example, I think the shell function that calls the CLI program can keep calling ...there's still the amount of logic in the current PowerShell script, which is similar to the new flavor of Click, with a fair amount of logic in the shell scripting side. But I couldn't find a way to make it just eval some string or have a plain function without so much logic. It would be great to be able to simplify this one, but that's harder, because PowerShell is quite weird. So maybe for later. So, yes, I would like us to be able to handle types and have completion specific for files and dirs as well, but I wouldn't like to just copy Click's code, I would want to do as much of the logic as possible in Python. |
Privileged issue
Issue Content
It seems autocompletion for
Path
types is not working correctly.Running that, for example with Typer CLI:
$ typer demo.py run <TAB>
that should show the available files in the current directory. In Zsh it doesn't show the files, in Bash it shows the files.
Then, let's say it's run from the same Typer directory, where the
LICENSE
file is located:$ typer demo.py run L<TAB>
That should autocomplete
LICENSE
, but it only addsTAB
/spaces characters.The text was updated successfully, but these errors were encountered: