devlaunch 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,176 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
161
+
162
+ .vscode/active_file.cfg
163
+
164
+ #COLCON
165
+ install/**
166
+ log/**
167
+ # pixi environments
168
+ .pixi
169
+ *.egg-info
170
+
171
+ managed_context/metadata.json
172
+ test_suite_analysis/metadata.json
173
+
174
+ .devpod/
175
+ .devpod-internal/
176
+ .*.swp
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Austin Gregg-Smith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: devlaunch
3
+ Version: 0.0.1
4
+ Summary: DevLaunch - A streamlined CLI for devpod workspaces
5
+ Project-URL: Source, https://github.com/blooop/devlaunch
6
+ Project-URL: Home, https://github.com/blooop/devlaunch
7
+ Author-email: Austin Gregg-Smith <blooop@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Dist: iterfzf>=1.0.0
11
+ Provides-Extra: test
12
+ Requires-Dist: coverage<=7.13.1,>=7.5.4; extra == 'test'
13
+ Requires-Dist: hypothesis<=6.150.2,>=6.104.2; extra == 'test'
14
+ Requires-Dist: prek<0.3.0,>=0.2.28; extra == 'test'
15
+ Requires-Dist: pylint<=4.0.4,>=3.2.5; extra == 'test'
16
+ Requires-Dist: pytest-cov<=7.0.0,>=4.1; extra == 'test'
17
+ Requires-Dist: pytest<=9.0.2,>=7.4; extra == 'test'
18
+ Requires-Dist: ruff<=0.14.13,>=0.5.0; extra == 'test'
19
+ Requires-Dist: ty<=0.0.12,>=0.0.12; extra == 'test'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # devlaunch
23
+
24
+ A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete and fzf fuzzy selection.
25
+
26
+ ## Continuous Integration Status
27
+
28
+ [![Ci](https://github.com/blooop/devlaunch/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/blooop/devlaunch/actions/workflows/ci.yml?query=branch%3Amain)
29
+ [![Codecov](https://codecov.io/gh/blooop/devlaunch/branch/main/graph/badge.svg?token=Y212GW1PG6)](https://codecov.io/gh/blooop/devlaunch)
30
+ [![GitHub issues](https://img.shields.io/github/issues/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/issues/)
31
+ [![GitHub pull-requests merged](https://badgen.net/github/merged-prs/blooop/devlaunch)](https://github.com/blooop/devlaunch/pulls?q=is%3Amerged)
32
+ [![GitHub release](https://img.shields.io/github/release/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/releases/)
33
+ [![License](https://img.shields.io/github/license/blooop/devlaunch)](https://opensource.org/license/mit/)
34
+ [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/)
35
+ [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ # Using pixi (recommended)
41
+ pixi global install devlaunch
42
+
43
+ # Using pip
44
+ pip install devlaunch
45
+ ```
46
+
47
+ After installation, set up shell completions:
48
+
49
+ ```bash
50
+ dl --install
51
+ source ~/.bashrc # or restart your terminal
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ```bash
57
+ dl # Interactive workspace selector (fzf)
58
+ dl <workspace> # Start workspace and attach shell
59
+ dl <workspace> <command> # Run command in workspace
60
+ dl owner/repo # Create workspace from GitHub repo
61
+ dl owner/repo@branch # Create workspace from specific branch
62
+ dl ./path # Create workspace from local path
63
+ ```
64
+
65
+ ## Commands
66
+
67
+ | Command | Description |
68
+ |---------|-------------|
69
+ | `dl --ls` | List all workspaces |
70
+ | `dl --stop <workspace>` | Stop a workspace |
71
+ | `dl --rm <workspace>` | Delete a workspace |
72
+ | `dl --code <workspace>` | Open workspace in VS Code |
73
+ | `dl --status <workspace>` | Show workspace status |
74
+ | `dl --recreate <workspace>` | Recreate workspace container |
75
+ | `dl --reset <workspace>` | Reset workspace (clean slate) |
76
+ | `dl --install` | Install shell completions |
77
+ | `dl --help` | Show help |
78
+
79
+ ## Examples
80
+
81
+ ```bash
82
+ # Select workspace interactively with fzf
83
+ dl
84
+
85
+ # Open an existing workspace
86
+ dl myproject
87
+
88
+ # Create workspace from GitHub repository
89
+ dl loft-sh/devpod
90
+
91
+ # Create workspace from specific branch
92
+ dl blooop/devlaunch@main
93
+
94
+ # Create workspace from local folder
95
+ dl ./my-project
96
+
97
+ # Open workspace in VS Code
98
+ dl --code myproject
99
+
100
+ # Run a command in workspace
101
+ dl myproject 'make test'
102
+ ```
103
+
104
+ ## Features
105
+
106
+ - **Fuzzy Selection**: When called without arguments, uses fzf for interactive workspace selection
107
+ - **Smart Completion**: Tab completion for workspaces, GitHub repos (owner/repo format), and paths
108
+ - **GitHub Shorthand**: Use `owner/repo` instead of full URLs - automatically expands to `github.com/owner/repo`
109
+ - **Branch Support**: Specify branches with `owner/repo@branch` syntax
110
+ - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
111
+
112
+ ## Shell Completion
113
+
114
+ After running `dl --install`, you get intelligent tab completion:
115
+
116
+ - Workspace names from your devpod list
117
+ - Known GitHub owners and repositories from your workspaces
118
+ - File/directory paths when starting with `./`, `/`, or `~`
119
+ - All command flags (`--ls`, `--stop`, etc.)
120
+
121
+ ## Development
122
+
123
+ This project uses [pixi](https://pixi.sh) for environment management.
124
+
125
+ ```bash
126
+ # Run tests
127
+ pixi run test
128
+
129
+ # Run full CI suite
130
+ pixi run ci
131
+
132
+ # Format and lint
133
+ pixi run style
134
+ ```
@@ -0,0 +1,113 @@
1
+ # devlaunch
2
+
3
+ A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete and fzf fuzzy selection.
4
+
5
+ ## Continuous Integration Status
6
+
7
+ [![Ci](https://github.com/blooop/devlaunch/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/blooop/devlaunch/actions/workflows/ci.yml?query=branch%3Amain)
8
+ [![Codecov](https://codecov.io/gh/blooop/devlaunch/branch/main/graph/badge.svg?token=Y212GW1PG6)](https://codecov.io/gh/blooop/devlaunch)
9
+ [![GitHub issues](https://img.shields.io/github/issues/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/issues/)
10
+ [![GitHub pull-requests merged](https://badgen.net/github/merged-prs/blooop/devlaunch)](https://github.com/blooop/devlaunch/pulls?q=is%3Amerged)
11
+ [![GitHub release](https://img.shields.io/github/release/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/releases/)
12
+ [![License](https://img.shields.io/github/license/blooop/devlaunch)](https://opensource.org/license/mit/)
13
+ [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/)
14
+ [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ # Using pixi (recommended)
20
+ pixi global install devlaunch
21
+
22
+ # Using pip
23
+ pip install devlaunch
24
+ ```
25
+
26
+ After installation, set up shell completions:
27
+
28
+ ```bash
29
+ dl --install
30
+ source ~/.bashrc # or restart your terminal
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```bash
36
+ dl # Interactive workspace selector (fzf)
37
+ dl <workspace> # Start workspace and attach shell
38
+ dl <workspace> <command> # Run command in workspace
39
+ dl owner/repo # Create workspace from GitHub repo
40
+ dl owner/repo@branch # Create workspace from specific branch
41
+ dl ./path # Create workspace from local path
42
+ ```
43
+
44
+ ## Commands
45
+
46
+ | Command | Description |
47
+ |---------|-------------|
48
+ | `dl --ls` | List all workspaces |
49
+ | `dl --stop <workspace>` | Stop a workspace |
50
+ | `dl --rm <workspace>` | Delete a workspace |
51
+ | `dl --code <workspace>` | Open workspace in VS Code |
52
+ | `dl --status <workspace>` | Show workspace status |
53
+ | `dl --recreate <workspace>` | Recreate workspace container |
54
+ | `dl --reset <workspace>` | Reset workspace (clean slate) |
55
+ | `dl --install` | Install shell completions |
56
+ | `dl --help` | Show help |
57
+
58
+ ## Examples
59
+
60
+ ```bash
61
+ # Select workspace interactively with fzf
62
+ dl
63
+
64
+ # Open an existing workspace
65
+ dl myproject
66
+
67
+ # Create workspace from GitHub repository
68
+ dl loft-sh/devpod
69
+
70
+ # Create workspace from specific branch
71
+ dl blooop/devlaunch@main
72
+
73
+ # Create workspace from local folder
74
+ dl ./my-project
75
+
76
+ # Open workspace in VS Code
77
+ dl --code myproject
78
+
79
+ # Run a command in workspace
80
+ dl myproject 'make test'
81
+ ```
82
+
83
+ ## Features
84
+
85
+ - **Fuzzy Selection**: When called without arguments, uses fzf for interactive workspace selection
86
+ - **Smart Completion**: Tab completion for workspaces, GitHub repos (owner/repo format), and paths
87
+ - **GitHub Shorthand**: Use `owner/repo` instead of full URLs - automatically expands to `github.com/owner/repo`
88
+ - **Branch Support**: Specify branches with `owner/repo@branch` syntax
89
+ - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
90
+
91
+ ## Shell Completion
92
+
93
+ After running `dl --install`, you get intelligent tab completion:
94
+
95
+ - Workspace names from your devpod list
96
+ - Known GitHub owners and repositories from your workspaces
97
+ - File/directory paths when starting with `./`, `/`, or `~`
98
+ - All command flags (`--ls`, `--stop`, etc.)
99
+
100
+ ## Development
101
+
102
+ This project uses [pixi](https://pixi.sh) for environment management.
103
+
104
+ ```bash
105
+ # Run tests
106
+ pixi run test
107
+
108
+ # Run full CI suite
109
+ pixi run ci
110
+
111
+ # Format and lint
112
+ pixi run style
113
+ ```
File without changes
@@ -0,0 +1,100 @@
1
+ """Utilities for installing shell autocompletion scripts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ import pathlib
8
+ from typing import Optional
9
+
10
+ from .completion_loader import load_completion_script
11
+
12
+ _RC_BLOCK_START = "# >>> devlaunch completions >>>"
13
+ _RC_BLOCK_END = "# <<< devlaunch completions <<<"
14
+
15
+ # Legacy blocks to clean up from previous installations
16
+ _LEGACY_BLOCKS = {
17
+ "# dl completion": "# end dl completion",
18
+ "# dp completion": "# end dp completion",
19
+ _RC_BLOCK_START: _RC_BLOCK_END,
20
+ }
21
+
22
+ _LEGACY_SINGLE_LINES = {
23
+ "complete -F _dl_completion dl",
24
+ "complete -F _dp_completion dp",
25
+ }
26
+
27
+
28
+ def _completion_file_path() -> pathlib.Path:
29
+ """Return the path where the completion script should be stored."""
30
+ override = os.environ.get("DEVLAUNCH_COMPLETION_FILE")
31
+ if override:
32
+ return pathlib.Path(override).expanduser()
33
+ return pathlib.Path.home() / ".config" / "devlaunch" / "completions.sh"
34
+
35
+
36
+ def install_completions(rc_path: Optional[pathlib.Path] = None) -> int:
37
+ """Install or refresh completion scripts for dl."""
38
+ completion_path = _completion_file_path().expanduser()
39
+ rc_target = (rc_path if rc_path is not None else pathlib.Path.home() / ".bashrc").expanduser()
40
+
41
+ try:
42
+ completion_path.parent.mkdir(parents=True, exist_ok=True)
43
+
44
+ # Write the dl completion script
45
+ completion_script = load_completion_script("dl").rstrip() + "\n"
46
+ completion_path.write_text(completion_script, encoding="utf-8")
47
+ logging.info("Wrote completion script to %s", completion_path)
48
+
49
+ rc_target.parent.mkdir(parents=True, exist_ok=True)
50
+ existing_content = ""
51
+ if rc_target.exists():
52
+ existing_content = rc_target.read_text(encoding="utf-8")
53
+
54
+ # Remove any existing completion block and legacy blocks before appending
55
+ def remove_block(text: str, start: str, end: str) -> str:
56
+ lines = text.splitlines()
57
+ out = []
58
+ skip = False
59
+ for line in lines:
60
+ if line.strip() == start:
61
+ skip = True
62
+ continue
63
+ if skip and line.strip() == end:
64
+ skip = False
65
+ continue
66
+ if not skip:
67
+ out.append(line)
68
+ return "\n".join(out)
69
+
70
+ # Remove main block
71
+ cleaned_content = remove_block(existing_content, _RC_BLOCK_START, _RC_BLOCK_END)
72
+ # Remove legacy blocks
73
+ for block_start, block_end in _LEGACY_BLOCKS.items():
74
+ cleaned_content = remove_block(cleaned_content, block_start, block_end)
75
+ # Remove legacy single lines
76
+ cleaned_lines = []
77
+ for line in cleaned_content.splitlines():
78
+ if not any(line.strip().startswith(single) for single in _LEGACY_SINGLE_LINES):
79
+ cleaned_lines.append(line)
80
+ cleaned_content = "\n".join(cleaned_lines).strip()
81
+ escaped_path = str(completion_path).replace('"', r"\"")
82
+ source_line = f'source "{escaped_path}"'
83
+ block = "\n".join([_RC_BLOCK_START, source_line, _RC_BLOCK_END])
84
+
85
+ if cleaned_content:
86
+ new_content = f"{cleaned_content}\n\n{block}\n"
87
+ else:
88
+ new_content = f"{block}\n"
89
+
90
+ rc_target.write_text(new_content, encoding="utf-8")
91
+ logging.info("Added completion source block to %s", rc_target)
92
+ logging.info("Run 'source %s' or restart your terminal to enable completion", rc_target)
93
+ print(
94
+ "[devlaunch] Autocomplete has been updated. Run 'source %s' or restart your terminal to enable completion."
95
+ % rc_target
96
+ )
97
+ return 0
98
+ except OSError as error:
99
+ logging.error("Failed to install completions: %s", error)
100
+ return 1
@@ -0,0 +1,12 @@
1
+ """Helpers for loading embedded completion scripts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib import resources
6
+
7
+
8
+ def load_completion_script(name: str) -> str:
9
+ """Return the text of the embedded completion script."""
10
+ package = "devlaunch.completions"
11
+ resource = resources.files(package).joinpath(f"{name}.bash")
12
+ return resource.read_text(encoding="utf-8")
File without changes
@@ -0,0 +1,78 @@
1
+ # dl completion
2
+ _dl_completion() {
3
+ local cur prev opts
4
+ COMPREPLY=()
5
+ cur="${COMP_WORDS[COMP_CWORD]}"
6
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
7
+
8
+ # Command options
9
+ opts="--ls --repos --stop --rm --code --status --recreate --reset --install --help"
10
+
11
+ # Flag completion
12
+ if [[ ${cur} == -* ]]; then
13
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
14
+ return 0
15
+ fi
16
+
17
+ # Cache file location (honors XDG_CACHE_HOME)
18
+ local cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/dl"
19
+ local cache_file="$cache_dir/completions.bash"
20
+
21
+ # Initialize completion variables
22
+ local DL_WORKSPACES=""
23
+ local DL_REPOS=""
24
+ local DL_OWNERS=""
25
+
26
+ # Source the bash cache file (fast, no jq needed)
27
+ if [[ -f "$cache_file" ]]; then
28
+ source "$cache_file"
29
+ fi
30
+
31
+ # Commands that need workspace completion
32
+ if [[ "$prev" == "--stop" || "$prev" == "--rm" || "$prev" == "--code" || "$prev" == "--status" || "$prev" == "--recreate" || "$prev" == "--reset" ]]; then
33
+ if [[ -n "$DL_WORKSPACES" ]]; then
34
+ COMPREPLY=( $(compgen -W "${DL_WORKSPACES}" -- ${cur}) )
35
+ fi
36
+ return 0
37
+ fi
38
+
39
+ # First positional argument: workspace, owner/repo, or path
40
+ if [[ ${COMP_CWORD} -eq 1 ]]; then
41
+ # Don't add space after completion to allow @branch suffix
42
+ compopt -o nospace
43
+
44
+ # If typing a path, complete files/directories
45
+ if [[ "$cur" == ./* || "$cur" == /* || "$cur" == ~/* ]]; then
46
+ compopt +o nospace
47
+ COMPREPLY=( $(compgen -d -- ${cur}) )
48
+ return 0
49
+ fi
50
+
51
+ # Check if completing owner/repo format (contains /)
52
+ if [[ "$cur" == */* ]]; then
53
+ # Complete from known repos
54
+ if [[ -n "$DL_REPOS" ]]; then
55
+ COMPREPLY=( $(compgen -W "${DL_REPOS}" -- ${cur}) )
56
+ fi
57
+ return 0
58
+ fi
59
+
60
+ # Default: complete workspace names and offer owner/ completion
61
+ local completions="$DL_WORKSPACES"
62
+
63
+ # Add owners with trailing slash
64
+ for owner in $DL_OWNERS; do
65
+ completions="$completions ${owner}/"
66
+ done
67
+
68
+ if [[ -n "$completions" ]]; then
69
+ COMPREPLY=( $(compgen -W "${completions}" -- ${cur}) )
70
+ fi
71
+ return 0
72
+ fi
73
+
74
+ return 0
75
+ }
76
+
77
+ complete -F _dl_completion dl
78
+ # end dl completion