Bash tab completion for argparse
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Built-in completer classes that provide different completion strategies for various argument types. Completers can be assigned to specific arguments to customize their completion behavior.
Abstract base class that all argcomplete completers should inherit from.
class BaseCompleter:
def __call__(
self,
*,
prefix: str,
action: argparse.Action,
parser: argparse.ArgumentParser,
parsed_args: argparse.Namespace
) -> None:
"""
Generate completions for the given prefix.
Parameters:
- prefix: The partial string being completed
- action: The argparse action being completed
- parser: The argument parser instance
- parsed_args: Already parsed arguments
Returns:
- Iterator or list of completion strings
"""Completer for predefined choices, useful for arguments with a fixed set of valid values.
class ChoicesCompleter(BaseCompleter):
def __init__(self, choices):
"""
Create completer for predefined choices.
Parameters:
- choices: Iterable of valid choices
"""
def __call__(self, **kwargs):
"""Returns completions matching the choices."""Usage:
import argparse
import argcomplete
from argcomplete import ChoicesCompleter
parser = argparse.ArgumentParser()
parser.add_argument('--format', choices=['json', 'xml', 'yaml'])
# Use built-in choices completion (automatic)
# or explicitly assign:
parser.add_argument('--level').completer = ChoicesCompleter(['debug', 'info', 'warning', 'error'])
argcomplete.autocomplete(parser)Completer for file and directory paths with optional filtering by file extensions.
class FilesCompleter(BaseCompleter):
def __init__(self, allowednames=(), directories=True):
"""
Create file completer with optional filtering.
Parameters:
- allowednames: Tuple/list of allowed file extensions (without dots)
- directories: Whether to include directories in completion
"""
def __call__(self, prefix, **kwargs):
"""Returns file and directory completions matching the prefix."""Usage:
from argcomplete import FilesCompleter
# Complete any files and directories
parser.add_argument('--input').completer = FilesCompleter()
# Complete only Python files and directories
parser.add_argument('--script').completer = FilesCompleter(
allowednames=('py', 'pyw'),
directories=True
)
# Complete only files, no directories
parser.add_argument('--data').completer = FilesCompleter(directories=False)
# Complete multiple file types
parser.add_argument('--config').completer = FilesCompleter(
allowednames=('json', 'yaml', 'yml', 'toml')
)Specialized completer that only completes directories, not files.
class DirectoriesCompleter(BaseCompleter):
def __init__(self):
"""Create directory-only completer."""Usage:
from argcomplete import DirectoriesCompleter
parser.add_argument('--output-dir').completer = DirectoriesCompleter()
parser.add_argument('--workdir').completer = DirectoriesCompleter()Pre-configured completer for environment variable names.
EnvironCompleter: ChoicesCompleter # Pre-instantiated with os.environ keysUsage:
from argcomplete import EnvironCompleter
parser.add_argument('--env-var').completer = EnvironCompleterCompleter that suppresses completion for specific arguments.
class SuppressCompleter(BaseCompleter):
def __init__(self):
"""Create completer that suppresses completion."""
def suppress(self) -> bool:
"""Returns True to indicate completion should be suppressed."""Usage:
from argcomplete import SuppressCompleter
# Disable completion for sensitive arguments
parser.add_argument('--password').completer = SuppressCompleter()
parser.add_argument('--secret-key').completer = SuppressCompleter()You can create custom completers by inheriting from BaseCompleter:
import subprocess
from argcomplete import BaseCompleter
class GitBranchCompleter(BaseCompleter):
def __call__(self, prefix, **kwargs):
try:
output = subprocess.check_output(
['git', 'branch', '--format=%(refname:short)'],
universal_newlines=True
)
branches = output.strip().split('\n')
return [branch for branch in branches if branch.startswith(prefix)]
except subprocess.CalledProcessError:
return []
# Use the custom completer
parser.add_argument('--branch').completer = GitBranchCompleter()Completers can use parsed arguments to provide context-sensitive completion:
class ContextCompleter(BaseCompleter):
def __call__(self, prefix, action, parser, parsed_args, **kwargs):
if parsed_args.mode == 'development':
return ['debug', 'trace', 'verbose']
elif parsed_args.mode == 'production':
return ['error', 'warning', 'info']
return []
parser.add_argument('--mode', choices=['development', 'production'])
parser.add_argument('--log-level').completer = ContextCompleter()Completers can return dictionaries to provide descriptions for completions:
class DocumentedCompleter(BaseCompleter):
def __call__(self, prefix, **kwargs):
options = {
'fast': 'Quick processing with basic features',
'thorough': 'Complete processing with all features',
'balanced': 'Good balance of speed and features'
}
return {k: v for k, v in options.items() if k.startswith(prefix)}
parser.add_argument('--mode').completer = DocumentedCompleter()class CachedCompleter(BaseCompleter):
def __init__(self):
self._cache = None
self._cache_time = 0
def __call__(self, prefix, **kwargs):
import time
now = time.time()
if self._cache is None or now - self._cache_time > 60:
self._cache = self._fetch_completions()
self._cache_time = now
return [item for item in self._cache if item.startswith(prefix)]class RobustCompleter(BaseCompleter):
def __call__(self, prefix, **kwargs):
try:
return self._get_completions(prefix)
except Exception:
# Fall back to no completions rather than breaking completion
return []Install with Tessl CLI
npx tessl i tessl/pypi-argcomplete