Repository: pallets/click (python)

Issue:
Shell completion fails with for arguments starting with "/"
After enabling shell completion support, arguments which start with a leading forward slash "/" fail to complete.

After a bit of debugging, it appears that if the argument starts with a "/", the completions are generated for the command itself instead of for the argument. For example, `my_app open /fold⇥` would generate completions for `open` instead of `/fold` whereas `my_app open fold⇥` correctly generates completions for `fold`.

Edit: To clarify the above, in both cases either "/fold" or "fold" is correctly picked up as the incomplete string. But in the first case, `obj.shell_complete(ctx, "/fold")` is called with the "open" command as the `obj`.

Environment:

- Python version: 3.9
- Click version: 8.0.1
- Shell: zsh, bash


Pull request description:
Fix shell completion for arguments with non-alphanumeric characters
This PR fixes shell completion for arguments with non-alphanumeric characters by implementing a less stringent test in `shell_completion._start_of_option()`.

- fixes #1929

Checklist:

- [x] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
- [x] Add or update relevant docs, in the docs folder and in code.
- [x] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [x] Add `.. versionchanged::` entries in any relevant code docs.
- [x] Run `pre-commit` hooks and fix any issues.
- [x] Run `pytest` and `tox`, no tests failed.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 8f978ff..e5876af 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,8 @@ Unreleased
 -   Bash version detection is locale independent. :issue:`1940`
 -   Empty ``default`` value is not shown for ``multiple=True``.
     :issue:`1969`
+-   Fix shell completion for arguments that start with a forward slash
+    such as absolute file paths. :issue:`1929`
 
 
 Version 8.0.1
diff --git a/src/click/shell_completion.py b/src/click/shell_completion.py
index b444bae..cad080d 100644
--- a/src/click/shell_completion.py
+++ b/src/click/shell_completion.py
@@ -450,7 +450,12 @@ def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool:
 
 def _start_of_option(value: str) -> bool:
     """Check if the value looks like the start of an option."""
-    return not value[0].isalnum() if value else False
+    if not value:
+        return False
+
+    c = value[0]
+    # Allow "/" since that starts a path.
+    return not c.isalnum() and c != "/"
 
 
 def _is_incomplete_option(args: t.List[str], param: Parameter) -> bool:


Test patch:
diff --git a/tests/test_shell_completion.py b/tests/test_shell_completion.py
index ac34ef9..46143c0 100644
--- a/tests/test_shell_completion.py
+++ b/tests/test_shell_completion.py
@@ -125,6 +125,14 @@ def test_path_types(type, expect):
     assert c.type == expect
 
 
+def test_absolute_path():
+    cli = Command("cli", params=[Option(["-f"], type=Path())])
+    out = _get_completions(cli, ["-f"], "/ab")
+    assert len(out) == 1
+    c = out[0]
+    assert c.value == "/ab"
+
+
 def test_option_flag():
     cli = Command(
         "cli",