Repository: pypa/pip

Issue:
Add support for Powershell autocompletion
**What's the problem this feature will solve?**
Improve the user experience on Powershell command line.

**Describe the solution you'd like**
<!-- Clear and concise description of what you want to happen. -->
I am inspired by the script of [click-completion](https://github.com/click-contrib/click-completion/blob/master/click_completion/powershell.j2), that you define a function named `TabExpansion` to implement completion, and backup possible existing functions so that Powershell can fallback one by one to find the correct definition.

I can work on this if there is no objection from maintainers.

<!-- Provide examples of real world use cases that this would enable and how it solves the problem described above. -->

**Alternative Solutions**
<!-- Have you tried to workaround the problem using pip or other tools? Or a different approach to solving this issue? Please elaborate here. -->

**Additional context**
<!-- Add any other context, links, etc. about the feature here. -->



Discussion:
PRs welcome. :)
I'd be in favour of this

Resolving patch:
diff --git a/src/pip/_internal/commands/completion.py b/src/pip/_internal/commands/completion.py
--- a/src/pip/_internal/commands/completion.py
+++ b/src/pip/_internal/commands/completion.py
@@ -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
+            }}
+        }}
+    """,
 }
 
 
@@ -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)
 


Test patch:
diff --git a/tests/functional/test_completion.py b/tests/functional/test_completion.py
--- a/tests/functional/test_completion.py
+++ b/tests/functional/test_completion.py
@@ -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
+    }
+}""",
+    ),
 )
 
 
@@ -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):
@@ -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
 ):