Skip to content

Feature: Add completion script for powershell #9025

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

Merged
merged 4 commits into from
Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/html/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,10 @@ To setup for fish::

python -m pip completion --fish > ~/.config/fish/completions/pip.fish

To setup for powershell::

python -m pip completion --powershell | Out-File -Encoding default -Append $PROFILE

Alternatively, you can use the result of the ``completion`` command directly
with the eval function of your shell, e.g. by adding the following to your
startup file::
Expand Down
1 change: 1 addition & 0 deletions news/9024.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for Powershell autocompletion.
30 changes: 30 additions & 0 deletions src/pip/_internal/commands/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@
end
complete -fa "(__fish_complete_pip)" -c {prog}
""",
"powershell": """
if ((Test-Path Function:\\TabExpansion) -and -not `
(Test-Path Function:\\_pip_completeBackup)) {{
Rename-Item Function:\\TabExpansion _pip_completeBackup
}}
function TabExpansion($line, $lastWord) {{
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
if ($lastBlock.StartsWith("{prog} ")) {{
$Env:COMP_WORDS=$lastBlock
$Env:COMP_CWORD=$lastBlock.Split().Length - 1
$Env:PIP_AUTO_COMPLETE=1
(& {prog}).Split()
Remove-Item Env:COMP_WORDS
Remove-Item Env:COMP_CWORD
Remove-Item Env:PIP_AUTO_COMPLETE
}}
elseif (Test-Path Function:\\_pip_completeBackup) {{
# Fall back on existing tab expansion
_pip_completeBackup $line $lastWord
}}
}}
""",
}


Expand Down Expand Up @@ -76,6 +98,14 @@ def add_options(self) -> None:
dest="shell",
help="Emit completion code for fish",
)
self.cmd_opts.add_option(
"--powershell",
"-p",
action="store_const",
const="powershell",
dest="shell",
help="Emit completion code for powershell",
)

self.parser.insert_option_group(0, self.cmd_opts)

Expand Down
33 changes: 29 additions & 4 deletions tests/functional/test_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@
}
compctl -K _pip_completion pip""",
),
(
"powershell",
"""\
if ((Test-Path Function:\\TabExpansion) -and -not `
(Test-Path Function:\\_pip_completeBackup)) {
Rename-Item Function:\\TabExpansion _pip_completeBackup
}
function TabExpansion($line, $lastWord) {
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
if ($lastBlock.StartsWith("pip ")) {
$Env:COMP_WORDS=$lastBlock
$Env:COMP_CWORD=$lastBlock.Split().Length - 1
$Env:PIP_AUTO_COMPLETE=1
(& pip).Split()
Remove-Item Env:COMP_WORDS
Remove-Item Env:COMP_CWORD
Remove-Item Env:PIP_AUTO_COMPLETE
}
elseif (Test-Path Function:\\_pip_completeBackup) {
# Fall back on existing tab expansion
_pip_completeBackup $line $lastWord
}
}""",
),
)


Expand Down Expand Up @@ -110,9 +134,10 @@ def test_completion_alone(autocomplete_script):
Test getting completion for none shell, just pip completion
"""
result = autocomplete_script.pip("completion", allow_stderr_error=True)
assert "ERROR: You must pass --bash or --fish or --zsh" in result.stderr, (
"completion alone failed -- " + result.stderr
)
assert (
"ERROR: You must pass --bash or --fish or --powershell or --zsh"
in result.stderr
), ("completion alone failed -- " + result.stderr)


def test_completion_for_un_snippet(autocomplete):
Expand Down Expand Up @@ -301,7 +326,7 @@ def test_completion_path_after_option(autocomplete, data):
)


@pytest.mark.parametrize("flag", ["--bash", "--zsh", "--fish"])
@pytest.mark.parametrize("flag", ["--bash", "--zsh", "--fish", "--powershell"])
def test_completion_uses_same_executable_name(
autocomplete_script, flag, deprecated_python
):
Expand Down