Skip to content

Commit

Permalink
🐛 Allow colon in zsh autocomplete values and descriptions (#988)
Browse files Browse the repository at this point in the history
Co-authored-by: Matt Crane <matt.crane@airbnb.com>
Co-authored-by: svlandeg <svlandeg@github.com>
  • Loading branch information
3 people authored Nov 7, 2024
1 parent 438ae44 commit ebb968e
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
25 changes: 25 additions & 0 deletions tests/test_completion/colon_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typer

image_desc = [
("alpine:latest", "latest alpine image"),
("alpine:hello", "fake image: for testing"),
("nvidia/cuda:10.0-devel-ubuntu18.04", ""),
]


def _complete(incomplete: str) -> str:
for image, desc in image_desc:
if image.startswith(incomplete):
yield image, desc


app = typer.Typer()


@app.command()
def image(name: str = typer.Option(autocompletion=_complete)):
typer.echo(name)


if __name__ == "__main__":
app()
219 changes: 219 additions & 0 deletions tests/test_completion/test_completion_option_colon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import os
import subprocess
import sys

from . import colon_example as mod


def test_script():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, "--name", "DeadPool"],
capture_output=True,
encoding="utf-8",
)
assert result.returncode == 0
assert "DeadPool" in result.stdout


def test_completion_colon_bash_all():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_bash",
"COMP_WORDS": "colon_example.py --name ",
"COMP_CWORD": "2",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" in result.stdout


def test_completion_colon_bash_partial():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_bash",
"COMP_WORDS": "colon_example.py --name alpine ",
"COMP_CWORD": "2",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_bash_single():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_bash",
"COMP_WORDS": "colon_example.py --name alpine:hell ",
"COMP_CWORD": "2",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" not in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_zsh_all():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_zsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name ",
},
)
assert "alpine\\\\:hello" in result.stdout
assert "alpine\\\\:latest" in result.stdout
assert "nvidia/cuda\\\\:10.0-devel-ubuntu18.04" in result.stdout


def test_completion_colon_zsh_partial():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_zsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine",
},
)
assert "alpine\\\\:hello" in result.stdout
assert "alpine\\\\:latest" in result.stdout
assert "nvidia/cuda\\\\:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_zsh_single():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_zsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine:hell",
},
)
assert "alpine\\\\:hello" in result.stdout
assert "alpine\\\\:latest" not in result.stdout
assert "nvidia/cuda\\\\:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_powershell_all():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_powershell",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name ",
"_TYPER_COMPLETE_WORD_TO_COMPLETE": "",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" in result.stdout


def test_completion_colon_powershell_partial():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_powershell",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine",
"_TYPER_COMPLETE_WORD_TO_COMPLETE": "alpine",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_powershell_single():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_powershell",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine:hell",
"_TYPER_COMPLETE_WORD_TO_COMPLETE": "alpine:hell",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" not in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_pwsh_all():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_pwsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name",
},
)

assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" in result.stdout


def test_completion_colon_pwsh_partial():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_pwsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine",
"_TYPER_COMPLETE_WORD_TO_COMPLETE": "alpine",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


def test_completion_colon_pwsh_single():
result = subprocess.run(
[sys.executable, "-m", "coverage", "run", mod.__file__, " "],
capture_output=True,
encoding="utf-8",
env={
**os.environ,
"_COLON_EXAMPLE.PY_COMPLETE": "complete_pwsh",
"_TYPER_COMPLETE_ARGS": "colon_example.py --name alpine:hell",
"_TYPER_COMPLETE_WORD_TO_COMPLETE": "alpine:hell",
},
)
assert "alpine:hello" in result.stdout
assert "alpine:latest" not in result.stdout
assert "nvidia/cuda:10.0-devel-ubuntu18.04" not in result.stdout


# TODO: tests for complete_fish
1 change: 1 addition & 0 deletions typer/_completion_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def escape(s: str) -> str:
.replace("'", "''")
.replace("$", "\\$")
.replace("`", "\\`")
.replace(":", r"\\:")
)

# TODO: Explore replicating the new behavior from Click, pay attention to
Expand Down

0 comments on commit ebb968e

Please sign in to comment.