summaryrefslogtreecommitdiff
path: root/docs/shell-completion.rst
diff options
context:
space:
mode:
authorAmy <leiamy12@gmail.com>2020-08-04 15:55:12 -0700
committerDavid Lord <davidism@gmail.com>2020-10-03 12:08:02 -0700
commitde75b40b5f986b4f843a487b2eb6272773b3f304 (patch)
tree59acdb0cc9b6b4a2d66914552435a8f306e71d37 /docs/shell-completion.rst
parent7029307f9ce2ee6757e8d49e3f76ebeec944779e (diff)
downloadclick-de75b40b5f986b4f843a487b2eb6272773b3f304.tar.gz
documentation for new shell completion system
Co-authored-by: Kai Chen <kaichen120@gmail.com> Co-authored-by: David Lord <davidism@gmail.com>
Diffstat (limited to 'docs/shell-completion.rst')
-rw-r--r--docs/shell-completion.rst286
1 files changed, 286 insertions, 0 deletions
diff --git a/docs/shell-completion.rst b/docs/shell-completion.rst
new file mode 100644
index 0000000..1e45bcd
--- /dev/null
+++ b/docs/shell-completion.rst
@@ -0,0 +1,286 @@
+.. 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.
+
+In order for completion to be used, the user needs to register a special
+function with their shell. The script is different for every shell, and
+Click will output it when called with ``_{PROG_NAME}_COMPLETE`` set to
+``source_{shell}``. ``{PROG_NAME}`` is the executable name in uppercase
+with dashes replaced by underscores. 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=source_bash foo-bar)"
+
+ .. group-tab:: Zsh
+
+ Add this to ``~/.zshrc``:
+
+ .. code-block:: zsh
+
+ eval "$(_FOO_BAR_COMPLETE=source_zsh foo-bar)"
+
+ .. group-tab:: Fish
+
+ Add this to ``~/.config/fish/completions/foo-bar.fish``:
+
+ .. code-block:: fish
+
+ eval (env _FOO_BAR_COMPLETE=source_fish foo-bar)
+
+ 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=source_bash 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=source_zsh 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=source_fish 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 ``(type, value, help)`` tuples. ``type`` will usually be ``"plain"``
+unless you've implemented a custom shell script. Some shells know how to
+display a ``help`` string next to each suggestion.
+
+In this example, the type will suggest environment variables that start
+with the incomplete value.
+
+.. code-block:: python
+
+ class EnvVarType(ParamType):
+ def shell_complete(self, ctx, args, incomplete):
+ return [
+ ("plain", k, None)
+ for k in os.environ
+ if k.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 an ``autocompletion`` function. The function is used
+instead of any completion provided by the type. It is passed 3 keyword
+arguments, and returns a list of strings to be shown.
+
+- ``ctx`` - The current command context.
+- ``args`` - The list of complete args before the incomplete value.
+- ``incomplete`` - The partial word that is being completed. May
+ be an empty string if no characters have been entered yet.
+
+In this example, the command will suggest environment variables that
+start with the incomplete value.
+
+.. code-block:: python
+
+ def complete_env_vars(ctx, args, incomplete):
+ return [k for k in os.environ if k.startswith(incomplete)]
+
+ @click.command()
+ @click.argument("name", autocompletion=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 ``_{PROG_NAME}_COMPLETE`` set to
+``complete_{shell}`` 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
+ ``complete_{shell}`` value.
+- ``prog_name`` - 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 click.shell_completion import add_completion_class
+ from click.shell_completion import ShellComplete
+
+ _mysh_source = """\
+ %(complete_func)s {
+ response=$(%(complete_var)s=complete_mysh %(prog_name)s)
+ # parse response and set completions somehow
+ }
+ call-on-complete %(prog_name)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 click.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 ``(type, value, help)`` tuples returned by Click
+into a string. For example, the Bash implementation returns
+``f"{type},{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
+
+ import os
+ from click.parser import split_arg_string
+
+ class MyshComplete(ShellComplete):
+ ...
+
+ def format_completion(self, item):
+ type, value, _ = item
+ return f"{type}\t{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=source_mysh foo-bar