import os import re import typing as t from gettext import gettext as _
from .core import Argument from .core import BaseCommand from .core import Context from .core import MultiCommand from .core import Option from .core import Parameter from .core import ParameterSource from .parser import split_arg_string from .utils import echo
def shell_complete(
cli: BaseCommand,
ctx_args: t.MutableMapping[str, t.Any],
prog_name: str,
complete_var: str,
instruction: str,
) -> int: """Perform shell completion for the given CLI program.
:param cli: Command being called.
:param ctx_args: Extra arguments to pass to
``cli.make_context``.
:param prog_name: Name of the executable in the shell.
:param complete_var: Name of the environment variable that holds
the completion instruction.
:param instruction: Value of ``complete_var`` with the completion
instruction and shell, in the form ``instruction_shell``.
:return: Status code to exit with. """
shell, _, instruction = instruction.partition("_")
comp_cls = get_completion_class(shell)
if instruction == "source":
echo(comp.source()) return 0
if instruction == "complete":
echo(comp.complete()) return 0
return 1
class CompletionItem: """Represents a completion value and metadata about the value. The
default metadata is ``type`` to indicate special shell handling, and ``help`` if a shell supports showing a help string next to the
value.
Arbitrary parameters can be passed when creating the object, and
accessed using ``item.attr``. If an attribute wasn't passed,
accessing it returns ``None``.
:param value: The completion suggestion.
:param type: Tells the shell script to provide special completion
support for the type. Click uses ``"dir"`` and ``"file"``.
:param help: String shown next to the value if supported.
:param kwargs: Arbitrary metadata. The built-in implementations
don't use this, but custom type completions paired with custom
shell support could use it. """
for type key descr in ${response}; do if [[ "$type" == "plain" ]]; then if [[ "$descr" == "_" ]]; then
completions+=("$key") else
completions_with_descriptions+=("$key":"$descr")
fi elif [[ "$type" == "dir" ]]; then
_path_files -/ elif [[ "$type" == "file" ]]; then
_path_files -f
fi
done
if [ -n "$completions_with_descriptions" ]; then
_describe -V unsorted completions_with_descriptions -U
fi
if [ -n "$completions" ]; then
compadd -U -V unsorted -a completions
fi
}
if [[ $zsh_eval_context[-1] == loadautofunc ]]; then # autoload from fpath, call function directly
%(complete_func)s "$@" else # eval/source/. command, register function for later
compdef %(complete_func)s %(prog_name)s
fi """
_SOURCE_FISH = """\
function %(complete_func)s;
set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \
COMP_CWORD=(commandline -t) %(prog_name)s);
for completion in $response;
set -l metadata (string split "," $completion);
if test $metadata[1] = "dir";
__fish_complete_directories $metadata[2]; elseif test $metadata[1] = "file";
__fish_complete_path $metadata[2]; elseif test $metadata[1] = "plain";
echo $metadata[2];
end;
end;
end;
class ShellComplete: """Base class for providing shell completion support. A subclass for
a given shell will override attributes and methods to implement the
completion instructions (``source`` and ``complete``).
:param cli: Command being called.
:param prog_name: Name of the executable in the shell.
:param complete_var: Name of the environment variable that holds
the completion instruction.
.. versionadded:: 8.0 """
name: t.ClassVar[str] """Name to register the shell as with :func:`add_completion_class`.
This is used in completion instructions (``{name}_source`` and
``{name}_complete``). """
source_template: t.ClassVar[str] """Completion script template formatted by :meth:`source`. This must
be provided by subclasses. """
@property def func_name(self) -> str: """The name of the shell function defined by the completion
script. """
safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) return f"_{safe_name}_completion"
def source_vars(self) -> t.Dict[str, t.Any]: """Vars for formatting :attr:`source_template`.
By default this provides ``complete_func``, ``complete_var``, and ``prog_name``. """ return { "complete_func": self.func_name, "complete_var": self.complete_var, "prog_name": self.prog_name,
}
def source(self) -> str: """Produce the shell script that defines the completion
function. By default this ``%``-style formats
:attr:`source_template` with the dict returned by
:meth:`source_vars`. """ return self.source_template % self.source_vars()
def get_completion_args(self) -> t.Tuple[t.List[str], str]: """Use the env vars defined by the shell script to return a
tuple of ``args, incomplete``. This must be implemented by
subclasses. """ raise NotImplementedError
def get_completions(
self, args: t.List[str], incomplete: str
) -> t.List[CompletionItem]: """Determine the context and last complete command or parameter from the complete args. Call that object's ``shell_complete``
method to get the completions for the incomplete value.
:param args: List of complete args before the incomplete value.
:param incomplete: Value being completed. May be empty. """
ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args)
obj, incomplete = _resolve_incomplete(ctx, args, incomplete) return obj.shell_complete(ctx, incomplete)
def format_completion(self, item: CompletionItem) -> str: """Format a completion item into the form recognized by the
shell script. This must be implemented by subclasses.
:param item: Completion item to format. """ raise NotImplementedError
def complete(self) -> str: """Produce the completion data to send back to the shell.
By default this calls :meth:`get_completion_args`, gets the
completions, then calls :meth:`format_completion` for each
completion. """
args, incomplete = self.get_completion_args()
completions = self.get_completions(args, incomplete)
out = [self.format_completion(item) for item in completions] return"\n".join(out)
class BashComplete(ShellComplete): """Shell completion for Bash."""
if major < "4"or major == "4"and minor < "4":
echo(
_( "Shell completion is not supported for Bash" " versions older than 4.4."
),
err=True,
) else:
echo(
_("Couldn't detect Bash version, shell completion is not supported."),
err=True,
)
# Fish stores the partial word in both COMP_WORDS and # COMP_CWORD, remove it from complete args. if incomplete and args and args[-1] == incomplete:
args.pop()
return args, incomplete
def format_completion(self, item: CompletionItem) -> str: if item.help: return f"{item.type},{item.value}\t{item.help}"
def add_completion_class(
cls: ShellCompleteType, name: t.Optional[str] = None
) -> ShellCompleteType: """Register a :class:`ShellComplete` subclass under the given name.
The name will be provided by the completion instruction environment
variable during completion.
:param cls: The completion class that will handle completion for the
shell.
:param name: Name to register the class under. Defaults to the class's ``name`` attribute. """ if name isNone:
name = cls.name
_available_shells[name] = cls
return cls
def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: """Look up a registered :class:`ShellComplete` subclass by the name
provided by the completion instruction environment variable. If the
name isn't registered, returns ``None``.
:param shell: Name the classis registered under. """ return _available_shells.get(shell)
def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: """Determine if the given parameter is an argument that can still
accept values.
:param ctx: Invocation context for the command represented by the
parsed complete args.
:param param: Argument object being checked. """ ifnot isinstance(param, Argument): returnFalse
assert param.name isnotNone # Will be None if expose_value is False.
value = ctx.params.get(param.name) return (
param.nargs == -1 or ctx.get_parameter_source(param.name) isnot ParameterSource.COMMANDLINE or (
param.nargs > 1 and isinstance(value, (tuple, list)) and len(value) < param.nargs
)
)
def _start_of_option(ctx: Context, value: str) -> bool: """Check if the value looks like the start of an option.""" ifnot value: returnFalse
c = value[0] return c in ctx._opt_prefixes
def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: """Determine if the given parameter is an option that needs a value.
:param args: List of complete args before the incomplete value.
:param param: Option object being checked. """ ifnot isinstance(param, Option): returnFalse
if param.is_flag or param.count: returnFalse
last_option = None
for index, arg in enumerate(reversed(args)): if index + 1 > param.nargs: break
if _start_of_option(ctx, arg):
last_option = arg
return last_option isnotNoneand last_option in param.opts
def _resolve_context(
cli: BaseCommand,
ctx_args: t.MutableMapping[str, t.Any],
prog_name: str,
args: t.List[str],
) -> Context: """Produce the context hierarchy starting with the command and
traversing the complete arguments. This only follows the commands,
it doesn't trigger input prompts or callbacks.
:param cli: Command being called.
:param prog_name: Name of the executable in the shell.
:param args: List of complete args before the incomplete value. """
ctx_args["resilient_parsing"] = True
ctx = cli.make_context(prog_name, args.copy(), **ctx_args)
args = ctx.protected_args + ctx.args
def _resolve_incomplete(
ctx: Context, args: t.List[str], incomplete: str
) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: """Find the Click object that will handle the completion of the
incomplete value. Return the object and the incomplete value.
:param ctx: Invocation context for the command represented by
the parsed complete args.
:param args: List of complete args before the incomplete value.
:param incomplete: Value being completed. May be empty. """ # Different shells treat an "=" between a long option name and # value differently. Might keep the value joined, return the "=" # as a separate item, or return the split name and value. Always # split and discard the "=" to make completion easier. if incomplete == "=":
incomplete = "" elif"="in incomplete and _start_of_option(ctx, incomplete):
name, _, incomplete = incomplete.partition("=")
args.append(name)
# The "--" marker tells Click to stop treating values as options # even if they start with the option character. If it hasn't been # given and the incomplete arg looks like an option, the current # command will provide option name completions. if"--"notin args and _start_of_option(ctx, incomplete): return ctx.command, incomplete
params = ctx.command.get_params(ctx)
# If the last complete arg is an option name with an incomplete # value, the option will provide value completions. for param in params: if _is_incomplete_option(ctx, args, param): return param, incomplete
# It's not an option name or value. The first argument without a # parsed value will provide value completions. for param in params: if _is_incomplete_argument(ctx, param): return param, incomplete
# There were no unparsed arguments, the command may be a group that # will provide command name completions. return ctx.command, incomplete
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.