-
Notifications
You must be signed in to change notification settings - Fork 169
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
Dynamic CLI completion #2285
Merged
r4victor
merged 20 commits into
dstackai:master
from
solovyevt:issue_2284_cli_completion
Feb 18, 2025
Merged
Dynamic CLI completion #2285
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
1f3640f
feature(cli): Initial completion
tsolovev bc4a6d6
feature(cli): stats run_name completion
tsolovev cfab3d3
feature(cli): Add completion script generation
tsolovev ae74805
docs(cli): Expand comment for BaseProjectCompleter
tsolovev 3eb23c2
style(cli): debug → argcomplete.debug
tsolovev 7bfa414
refactor(cli): Move completion.py to cli/services
tsolovev 59b2f17
fix(cli): Restore unknown args
tsolovev 370f4b1
fix(cli): Attach more completions
tsolovev fc12d56
style(cli): Fix typos in help strings
tsolovev ffad645
fix(cli): Change base class for BaseProjectCompletion
tsolovev da9595d
build(cli): Update deps argcomplete==3.5.3 → >=3.5.0
tsolovev 0756bf1
fix(cli): Temporary fix for repeated empty completions
tsolovev 72ee8e3
feature(cli): Replace remote project completion with local
tsolovev 6ca0fc2
refactor(cli): DRY completers, uniform exception handling
tsolovev d14466a
Merge branch 'master' into issue_2284_cli_completion
r4victor 931cc23
Fix typing
r4victor 6f7d6cd
docs(cli): Add autocompletion docs
tsolovev e671090
docs(cli): Minimalist completion docs
tsolovev 66bb816
Revert "docs(cli): Minimalist completion docs"
r4victor fcb5130
Recommend sourcing external script for completions
r4victor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import argcomplete | ||
|
||
from dstack._internal.cli.commands import BaseCommand | ||
|
||
|
||
class CompletionCommand(BaseCommand): | ||
NAME = "completion" | ||
DESCRIPTION = "Generate shell completion scripts" | ||
|
||
def _register(self): | ||
super()._register() | ||
self._parser.add_argument( | ||
"shell", | ||
help="The shell to generate the completion script for", | ||
choices=["bash", "zsh"], | ||
) | ||
|
||
def _command(self, args): | ||
super()._command(args) | ||
print(argcomplete.shellcode(["dstack"], shell=args.shell)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import argparse | ||
import os | ||
from abc import ABC, abstractmethod | ||
from typing import Iterable, List, Optional | ||
|
||
import argcomplete | ||
from argcomplete.completers import BaseCompleter | ||
|
||
from dstack._internal.core.errors import ConfigurationError | ||
from dstack._internal.core.services.configs import ConfigManager | ||
from dstack.api import Client | ||
|
||
|
||
class BaseAPINameCompleter(BaseCompleter, ABC): | ||
""" | ||
Base class for name completers that fetch resource names via the API. | ||
""" | ||
|
||
def __init__(self): | ||
super().__init__() | ||
|
||
def get_api(self, parsed_args: argparse.Namespace) -> Optional[Client]: | ||
argcomplete.debug(f"{self.__class__.__name__}: Retrieving API client") | ||
project = getattr(parsed_args, "project", os.getenv("DSTACK_PROJECT")) | ||
try: | ||
return Client.from_config(project_name=project) | ||
except ConfigurationError as e: | ||
argcomplete.debug(f"{self.__class__.__name__}: Error initializing API client: {e}") | ||
return None | ||
|
||
def __call__(self, prefix: str, parsed_args: argparse.Namespace, **kwargs) -> List[str]: | ||
api = self.get_api(parsed_args) | ||
if api is None: | ||
return [] | ||
|
||
argcomplete.debug(f"{self.__class__.__name__}: Fetching completions") | ||
try: | ||
resource_names = self.fetch_resource_names(api) | ||
return [name for name in resource_names if name.startswith(prefix)] | ||
except Exception as e: | ||
argcomplete.debug( | ||
f"{self.__class__.__name__}: Error fetching resource completions: {e}" | ||
) | ||
return [] | ||
|
||
@abstractmethod | ||
def fetch_resource_names(self, api: Client) -> Iterable[str]: | ||
""" | ||
Returns an iterable of resource names. | ||
""" | ||
pass | ||
|
||
|
||
class RunNameCompleter(BaseAPINameCompleter): | ||
def __init__(self, all: bool = False): | ||
super().__init__() | ||
self.all = all | ||
|
||
def fetch_resource_names(self, api: Client) -> Iterable[str]: | ||
return [r.name for r in api.runs.list(self.all)] | ||
|
||
|
||
class FleetNameCompleter(BaseAPINameCompleter): | ||
def fetch_resource_names(self, api: Client) -> Iterable[str]: | ||
return [r.name for r in api.client.fleets.list(api.project)] | ||
|
||
|
||
class VolumeNameCompleter(BaseAPINameCompleter): | ||
def fetch_resource_names(self, api: Client) -> Iterable[str]: | ||
return [r.name for r in api.client.volumes.list(api.project)] | ||
|
||
|
||
class GatewayNameCompleter(BaseAPINameCompleter): | ||
def fetch_resource_names(self, api: Client) -> Iterable[str]: | ||
return [r.name for r in api.client.gateways.list(api.project)] | ||
|
||
|
||
class ProjectNameCompleter(BaseCompleter): | ||
""" | ||
Completer for local project names. | ||
""" | ||
|
||
def __call__(self, prefix: str, parsed_args: argparse.Namespace, **kwargs) -> List[str]: | ||
argcomplete.debug(f"{self.__class__.__name__}: Listing projects from ConfigManager") | ||
projects = ConfigManager().list_projects() | ||
return [p for p in projects if p.startswith(prefix)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's a good idea to write directly to ~/.bashrc or ~/.zshrc. Let me fix it.