1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
.. currentmodule:: click.shell_completion
Shell Completion
================
Click provides tab completion support for Bash (version 4.4 and up),
Zsh, and Fish. It is possible to add support for other shells too, and
suggestions can be customized at multiple levels.
Shell completion suggests command names, option names, and values for
choice, file, and path parameter types. Options are only listed if at
least a dash has been entered. Hidden commands and options are not
shown.
.. code-block:: text
$ repo <TAB><TAB>
clone commit copy delete setuser
$ repo clone -<TAB><TAB>
--deep --help --rev --shallow -r
Enabling Completion
-------------------
Completion is only available if a script is installed and invoked
through an entry point, not through the ``python`` command. See
:doc:`/setuptools`. Once the executable is installed, calling it with
a special environment variable will put Click in completion mode.
To enable shell completion, the user needs to register a special
function with their shell. The exact script varies depending on the
shell you are using. Click will output it when called with
``_{FOO_BAR}_COMPLETE`` set to ``{shell}_source``. ``{FOO_BAR}`` is
the executable name in uppercase with dashes replaced by underscores.
It is conventional but not strictly required for environment variable
names to be in upper case. This convention helps distinguish environment
variables from regular shell variables and commands, making scripts
and configuration files more readable and easier to maintain. The
built-in shells are ``bash``, ``zsh``, and ``fish``.
Provide your users with the following instructions customized to your
program name. This uses ``foo-bar`` as an example.
.. tabs::
.. group-tab:: Bash
Add this to ``~/.bashrc``:
.. code-block:: bash
eval "$(_FOO_BAR_COMPLETE=bash_source foo-bar)"
.. group-tab:: Zsh
Add this to ``~/.zshrc``:
.. code-block:: zsh
eval "$(_FOO_BAR_COMPLETE=zsh_source foo-bar)"
.. group-tab:: Fish
Add this to ``~/.config/fish/completions/foo-bar.fish``:
.. code-block:: fish
_FOO_BAR_COMPLETE=fish_source foo-bar | source
This is the same file used for the activation script method
below. For Fish it's probably always easier to use that method.
Using ``eval`` means that the command is invoked and evaluated every
time a shell is started, which can delay shell responsiveness. To speed
it up, write the generated script to a file, then source that. You can
generate the files ahead of time and distribute them with your program
to save your users a step.
.. tabs::
.. group-tab:: Bash
Save the script somewhere.
.. code-block:: bash
_FOO_BAR_COMPLETE=bash_source foo-bar > ~/.foo-bar-complete.bash
Source the file in ``~/.bashrc``.
.. code-block:: bash
. ~/.foo-bar-complete.bash
.. group-tab:: Zsh
Save the script somewhere.
.. code-block:: bash
_FOO_BAR_COMPLETE=zsh_source foo-bar > ~/.foo-bar-complete.zsh
Source the file in ``~/.zshrc``.
.. code-block:: bash
. ~/.foo-bar-complete.zsh
.. group-tab:: Fish
Save the script to ``~/.config/fish/completions/foo-bar.fish``:
.. code-block:: fish
_FOO_BAR_COMPLETE=fish_source foo-bar > ~/.config/fish/completions/foo-bar.fish
After modifying the shell config, you need to start a new shell in order
for the changes to be loaded.
Custom Type Completion
----------------------
When creating a custom :class:`~click.ParamType`, override its
:meth:`~click.ParamType.shell_complete` method to provide shell
completion for parameters with the type. The method must return a list
of :class:`~CompletionItem` objects. Besides the value, these objects
hold metadata that shell support might use. The built-in implementations
use ``type`` to indicate special handling for paths, and ``help`` for
shells that support showing a help string next to a suggestion.
In this example, the type will suggest environment variables that start
with the incomplete value.
.. code-block:: python
class EnvVarType(ParamType):
name = "envvar"
def shell_complete(self, ctx, param, incomplete):
return [
CompletionItem(name)
for name in os.environ if name.startswith(incomplete)
]
@click.command()
@click.option("--ev", type=EnvVarType())
def cli(ev):
click.echo(os.environ[ev])
Overriding Value Completion
---------------------------
Value completions for a parameter can be customized without a custom
type by providing a ``shell_complete`` function. The function is used
instead of any completion provided by the type. It is passed 3 keyword
arguments:
- ``ctx`` - The current command context.
- ``param`` - The current parameter requesting completion.
- ``incomplete`` - The partial word that is being completed. May
be an empty string if no characters have been entered yet.
It must return a list of :class:`CompletionItem` objects, or as a
shortcut it can return a list of strings.
In this example, the command will suggest environment variables that
start with the incomplete value.
.. code-block:: python
def complete_env_vars(ctx, param, incomplete):
return [k for k in os.environ if k.startswith(incomplete)]
@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def cli(name):
click.echo(f"Name: {name}")
click.echo(f"Value: {os.environ[name]}")
Adding Support for a Shell
--------------------------
Support can be added for shells that do not come built in. Be sure to
check PyPI to see if there's already a package that adds support for
your shell. This topic is very technical, you'll want to look at Click's
source to study the built-in implementations.
Shell support is provided by subclasses of :class:`ShellComplete`
registered with :func:`add_completion_class`. When Click is invoked in
completion mode, it calls :meth:`~ShellComplete.source` to output the
completion script, or :meth:`~ShellComplete.complete` to output
completions. The base class provides default implementations that
require implementing some smaller parts.
First, you'll need to figure out how your shell's completion system
works and write a script to integrate it with Click. It must invoke your
program with the environment variable ``_{FOO_BAR}_COMPLETE`` set to
``{shell}_complete`` and pass the complete args and incomplete value.
How it passes those values, and the format of the completion response
from Click is up to you.
In your subclass, set :attr:`~ShellComplete.source_template` to the
completion script. The default implementation will perform ``%``
formatting with the following variables:
- ``complete_func`` - A safe name for the completion function defined
in the script.
- ``complete_var`` - The environment variable name for passing the
``{shell}_complete`` instruction.
- ``foo_bar`` - The name of the executable being completed.
The example code is for a made up shell "My Shell" or "mysh" for short.
.. code-block:: python
from asyncclick.shell_completion import add_completion_class
from asyncclick.shell_completion import ShellComplete
_mysh_source = """\
%(complete_func)s {
response=$(%(complete_var)s=mysh_complete %(foo_bar)s)
# parse response and set completions somehow
}
call-on-complete %(foo_bar)s %(complete_func)s
"""
@add_completion_class
class MyshComplete(ShellComplete):
name = "mysh"
source_template = _mysh_source
Next, implement :meth:`~ShellComplete.get_completion_args`. This must
get, parse, and return the complete args and incomplete value from the
completion script. For example, for the Bash implementation the
``COMP_WORDS`` env var contains the command line args as a string, and
the ``COMP_CWORD`` env var contains the index of the incomplete arg. The
method must return a ``(args, incomplete)`` tuple.
.. code-block:: python
import os
from asyncclick.parser import split_arg_string
class MyshComplete(ShellComplete):
...
def get_completion_args(self):
args = split_arg_string(os.environ["COMP_WORDS"])
if os.environ["COMP_PARTIAL"] == "1":
incomplete = args.pop()
return args, incomplete
return args, ""
Finally, implement :meth:`~ShellComplete.format_completion`. This is
called to format each :class:`CompletionItem` into a string. For
example, the Bash implementation returns ``f"{item.type},{item.value}``
(it doesn't support help strings), and the Zsh implementation returns
each part separated by a newline, replacing empty help with a ``_``
placeholder. This format is entirely up to what you parse with your
completion script.
The ``type`` value is usually ``plain``, but it can be another value
that the completion script can switch on. For example, ``file`` or
``dir`` can tell the shell to handle path completion, since the shell is
better at that than Click.
.. code-block:: python
class MyshComplete(ShellComplete):
...
def format_completion(self, item):
return f"{item.type}\t{item.value}"
With those three things implemented, the new shell support is ready. In
case those weren't sufficient, there are more parts that can be
overridden, but that probably isn't necessary.
The activation instructions will again depend on how your shell works.
Use the following to generate the completion script, then load it into
the shell somehow.
.. code-block:: text
_FOO_BAR_COMPLETE=mysh_source foo-bar
|