Replies: 3 comments 2 replies
-
Sorry for dumping a lot of code here, I'm on a tablet. This is what I did for myself
So everything but files are handled normally, argument files use autocompletion callback which falls back to console, and only autocomplete paths with spaces if you open a quote at the start (not ideal). I think I also need quotes in the option arguments because I didn't bother listing the console quoted space version as a possibility and it looks better but I'm not sure (in a tablet as I write). If they aren't of a restricted set I expect, they're passed to the console and treated as a console file. I don't recall but I think I used different callbacks because they are subtly different in behavior in spite of the documentation saying they're the same. |
Beta Was this translation helpful? Give feedback.
-
I came up with the following work-around for the broken shell completion: def path_autocomplete(
file_okay: bool = True,
dir_okay: bool = True,
writable: bool = False,
readable: bool = True,
allow_dash: bool = False,
match_wildcard: Optional[str] = None,
) -> Callable[[str], list[str]]:
def wildcard_match(string: str, pattern: str) -> bool:
regex = re.escape(pattern).replace(r'\?', '.').replace(r'\*', '.*')
return re.fullmatch(regex, string) is not None
def completer(incomplete: str) -> list[str]:
items = os.listdir()
completions = []
for item in items:
if not file_okay and os.path.isfile(item):
continue
elif not dir_okay and os.path.isdir(item):
continue
if readable and not os.access(item, os.R_OK):
continue
if writable and not os.access(item, os.W_OK):
continue
completions.append(item)
if allow_dash:
completions.append('-')
if match_wildcard is not None:
completions = filter(lambda i: wildcard_match(i, match_wildcard), completions)
return [i for i in completions if i.startswith(incomplete)]
return completer It contains a subset to arguments normally provided to You can use it like this: @app.command()
def some_command(filename: Annotated[Path, typer.Argument(autocompletion=path_autocomplete(file_okay=True, dir_okay=False, readable=True, match_wildcard="foo*"))]):
# notice the file_okay and the rest of path-related arguments goes to path_autocomplete, to Argument
# this makes the code easy to cleanup when the bug is fixed
pass |
Beta Was this translation helpful? Give feedback.
-
Same problem with zsh and oh-my-zsh. How to represent. Example from official doc:from pathlib import Path
from typing import Optional
import typer
from typing_extensions import Annotated
def main(config: Annotated[Optional[Path], typer.Option()] = None):
if config is None:
print("No config file")
raise typer.Abort()
if config.is_file():
text = config.read_text()
print(f"Config file contents: {text}")
elif config.is_dir():
print("Config is a directory, will use all its config files")
elif not config.exists():
print("The config doesn't exist")
if __name__ == "__main__":
typer.run(main) Actual resulttyper ./main.py --config [TAB]
# No hints appear, only a single space is added to the end of the entered command
# If you continue to press [TAB], more spaces will be added Expected resulttyper ./main.py --config [TAB]
# Hints according to Path type |
Beta Was this translation helpful? Give feedback.
-
First Check
Commit to Help
Example Code
Description
The problem is with bash shell completions for files & directories in Typer (I've checked Click and it behaves as expected in that regard, that's what makes me confident it's an issue within Typer, not Click).
How to reproduce the issue
Actual result
Expected result
The expected result is in line with Click's behavior. I used the following Click code to check it:
The most simplistic way to install bash completions for the above script in current shell session is this:
I think this issue also impacted another user as described in this discussion.
Possible root cause - a lead to follow
I'm no shell expert, so the "lead" I will point here might be totally wrong.
I noticed the the shell completion scripts generated by Typer and Click differ a lot.
Typer:
Click:
There are two things that grab my attention, but I am not sure if they are relevant in this context:
complete -o nosort
, while Typer usescomplete -o default
Operating System
Linux
Operating System Details
No response
Typer Version
0.9.0
Python Version
Python 3.10.12
Additional Context
Click version: 8.1.7
Beta Was this translation helpful? Give feedback.
All reactions