Repository: iterative/shtab

Issue:
Inconsistencies with expected completions behavior
Shtab has some interesting quirks in the completions it generates that deviate from what I am used to seeing, and I am having trouble figuring out if they are intentional or just bugs.

First, if there is only one possible option for completion of a command when I press tab, I expect completions to finish writing the command for me and then add a space, indicating that the command is complete and allowing me to immediately start writing the next command, or an argument to that command, etc.  Instead, the command gets completed, but no space is added, despite the fact that nothing helpful could be added to the command at that point (except a space).

Second, the file completion support through the shtab.FILE option has a similar issue.  When I am attempting to complete a file path using this option, if I try to navigate into a new directory and the text I have provided so far is sufficient to determine that directory, pressing tab does not autocomplete to take me into that directory.  Instead, two options are given:  One for the directory path without the forward slash, and one with the forward slash.  For example, if I type "/us" and hit tab, the path is expanded to "/usr" and two options are given: "/usr" and "/usr/".  All other completions I have used would see these as the same option and autocomplete to "/usr/" so that I can continue typing the file path until I reach the destination file.  Interestingly enough, using the shtab.DIRECTORY option produces the desired behavior, except that a file cannot be selected at the end of the file path.

Lastly, In addition to the above point, shtab.FILE and shtab.DIRECTORY don't handle completions for larger file paths as expected.  If a path across several directories is given, completions for any additional directories include every other directory up to that point instead of just the relevant directory.  As an example, if the text "/green/eggs/and/ham" is provided and tab is pressed twice, the options "/green/eggs/and/ham/" and "green/eggs/and/hamburgers/" are given instead of just "ham/" and "hamburgers/".  This method of displaying completion options can get VERY cluttered for large file paths.

These aspects of the shtab generated completions are very strange to me since they seem to go against every other set of completions that I have worked with in the Ubuntu bash terminal.  If these are intended features, what is the rationale behind them, and could it be possible to allow for completions in a more "native" form?

Discussion:

Patch:
diff --git a/shtab/__init__.py b/shtab/__init__.py
index fd8d7a7..9fda301 100644
--- a/shtab/__init__.py
+++ b/shtab/__init__.py
@@ -268,12 +268,11 @@ def complete_bash(
 # $1=COMP_WORDS[1]
 _shtab_compgen_files() {
   compgen -f -- $1  # files
-  compgen -d -S '/' -- $1  # recurse into subdirs
 }
 
 # $1=COMP_WORDS[1]
 _shtab_compgen_dirs() {
-  compgen -d -S '/' -- $1  # recurse into subdirs
+  compgen -d -- $1  # recurse into subdirs
 }
 
 # $1=COMP_WORDS[1]
@@ -344,7 +343,7 @@ _shtab_replace_nonword() {
   return 0
 }
 
-complete -o nospace -F {root_prefix} {prog}""",
+complete -o filenames -F {root_prefix} {prog}""",
         commands=" ".join(commands),
         options=" ".join(options),
         preamble=(


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6f4f8cb..8fae992 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -54,27 +54,18 @@ jobs:
     - id: dist
       uses: casperdcl/deploy-pypi@v2
       with:
-        build: true
+        pip: true
         password: ${{ secrets.PYPI_TOKEN }}
         upload: ${{ github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') }}
     - name: Changelog
       run: git log --pretty='format:%d%n- %s%n%b---' $(git tag --sort=v:refname | tail -n2 | head -n1)..HEAD > _CHANGES.md
     - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
-      id: create_release
-      uses: actions/create-release@v1
+      uses: softprops/action-gh-release@v1
       env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
       with:
-        tag_name: ${{ github.ref }}
-        release_name: shtab ${{ github.ref }} beta
+        release_name: shtab ${{ github.ref }} stable
         body_path: _CHANGES.md
         draft: true
-    - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ steps.create_release.outputs.upload_url }}
-        asset_path: dist/${{ steps.dist.outputs.whl }}
-        asset_name: ${{ steps.dist.outputs.whl }}
-        asset_content_type: application/zip
+        files: |
+          dist/${{ steps.dist.outputs.whl }}
diff --git a/tests/test_shtab.py b/tests/test_shtab.py
index 9e431fb..e8f1e75 100644
--- a/tests/test_shtab.py
+++ b/tests/test_shtab.py
@@ -81,7 +81,7 @@ def test_prog_override(shell, caplog, capsys):
     captured = capsys.readouterr()
     assert not captured.err
     if shell == "bash":
-        assert "complete -o nospace -F _shtab_shtab foo" in captured.out
+        assert "complete -o filenames -F _shtab_shtab foo" in captured.out
 
     assert not caplog.record_tuples
 
@@ -95,7 +95,7 @@ def test_prog_scripts(shell, caplog, capsys):
     assert not captured.err
     script_py = [i.strip() for i in captured.out.splitlines() if "script.py" in i]
     if shell == "bash":
-        assert script_py == ["complete -o nospace -F _shtab_shtab script.py"]
+        assert script_py == ["complete -o filenames -F _shtab_shtab script.py"]
     elif shell == "zsh":
         assert script_py == [
             "#compdef script.py",