Skip to main content

Automatically generate shell tab completion scripts for python CLI apps

Project description

  • What: Automatically generate shell tab completion scripts for python CLI apps

  • Why: Speed & correctness. Alternatives like argcomplete & pyzshcomplete are slow and have side-effects

  • How: shtab processes an argparse.ArgumentParser object to generate a tab completion script for your shell

Features

  • Outputs completion for bash and zsh

  • Supports argparse and docopt (via argopt)

  • Supports arguments, options and subparsers

  • Supports path completion

Usage

Installing shtab’s own tab completion scripts is possible via:

# Install locally (eager)
echo 'eval "$(shtab --shell=bash shtab.main.get_main_parser)"' \
  >> ~/.bash_completion

# Install locally (lazy load for bash-completion>=2.8)
echo 'eval "$(shtab --shell=bash shtab.main.get_main_parser)"' \
  > "${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/shtab"

# Install system-wide
echo 'eval "$(shtab --shell=bash shtab.main.get_main_parser)"' \
  | sudo tee "$(pkg-config --variable=completionsdir bash-completion)"/shtab

# Install system-wide (legacy)
echo 'eval "$(shtab --shell=bash shtab.main.get_main_parser)"' \
  | sudo tee "$BASH_COMPLETION_COMPAT_DIR"/shtab

# Install once (will have to re-run if the target's CLI API changes,
# but doesn't need target to always be in $PYTHONPATH)
shtab --shell=bash shtab.main.get_main_parser --error-unimportable \
  | sudo tee "$BASH_COMPLETION_COMPAT_DIR"/shtab

# zsh equivalent (alternatively place in $fpath/_shtab)
shtab --shell=zsh shtab.main.get_main_parser --error-unimportable \
  | sudo tee /usr/local/share/zsh/site-functions/_shtab

The same would work for most existing argparse-based scripts. For example, starting with this existing code:

import argparse

def get_main_parser():
    parser = argparse.ArgumentParser(prog="<MY_PROG>", ...)
    parser.add_argument(...)
    parser.add_subparsers(...)
    ...
    return parser

if __name__ == "__main__":
    parser = get_main_parser()
    args = parser.parse_args()
    ...

Assuming this code example is installed in MY_PROG.command.main, simply run:

# bash
echo 'eval "$(shtab --shell=bash MY_PROG.command.main.get_main_parser)"' \
  >> ~/.bash_completion

# zsh
shtab --shell=zsh -u MY_PROG.command.main.get_main_parser \
  | sudo tee /usr/local/share/zsh/site-functions/_MY_PROG

Configuration

Alternatively, add direct support to scripts for a little more configurability:

import argparse
import shtab, os  # for completion magic

def get_main_parser():
    parser = argparse.ArgumentParser(prog="<MY_PROG>", ...)
    parser.add_argument("--install-completion-shell", choices=["bash", "zsh"])
    parser.add_argument(
        "--file",
        choices=shtab.Optional.FILE,  # file tab completion
    )
    parser.add_argument(
        "--dir",
        choices=shtab.Required.DIRECTORY,  # directory tab completion
        default=os.getenv("BASH_COMPLETION_USER_DIR"),
    )
    ...
    return parser

if __name__ == "__main__":
    parser = get_main_parser()
    args = parser.parse_args()

    # completion magic
    shell = args.install_completion_shell
    if shell:
        completion_script = shtab.complete(parser, shell=shell)
        filename = args.file or "<MY_PROG>"
        print("Writing to system completion directory...")
        with open(os.path.join(args.dir, filename), "w") as fd:
            fd.write(completion_script)
        print("Please restart your terminal.")

    ...

More Examples

#!/usr/bin/env python
"""Greetings and partings.

Usage:
  greeter [options] [<you>] [<me>]

Options:
  -b, --bye  : Say "goodbye" (instead of "hello")
  -c, --print-bash-completion  : Output a tab-completion script

Arguments:
  <you>  : Your name [default: Anon]
  <me>  : My name [default: Casper]
"""
import sys, argopt, shtab
parser = argopt.argopt(__doc__)
if __name__ == "__main__":
    args = parser.parse_args()
    if args.print_bash_completion:
        print(shtab.complete(parser, shell="bash"))
        sys.exit(0)

    msg = "k thx bai!" if args.bye else "hai!"
    print("{} says '{}' to {}".format(args.me, msg, args.you))

Alternatives

  • argcomplete

    • executes the underlying script every time <TAB> is pressed (slow and has side-effects)

    • only provides bash completion

  • pyzshcomplete

    • executes the underlying script every time <TAB> is pressed (slow and has side-effects)

    • only provides zsh completion

  • click

    • different framework completely replacing argparse

    • solves multiple problems (rather than POSIX-style “do one thing well”)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shtab-0.0.4.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

shtab-0.0.4-py2.py3-none-any.whl (9.9 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file shtab-0.0.4.tar.gz.

File metadata

  • Download URL: shtab-0.0.4.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.7.7

File hashes

Hashes for shtab-0.0.4.tar.gz
Algorithm Hash digest
SHA256 4a46542c7ad87d3b3852956c7bc481cbf9fbd5c1dc6b539065bb28f7afd0a829
MD5 b373b9c389f7098617dc3affa6a849e0
BLAKE2b-256 32598b51324cc77eacf8e8ab5ed23082c582d3ef7d4f2232134751526cfb338e

See more details on using hashes here.

Provenance

File details

Details for the file shtab-0.0.4-py2.py3-none-any.whl.

File metadata

  • Download URL: shtab-0.0.4-py2.py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.7.7

File hashes

Hashes for shtab-0.0.4-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 56453fcf92326549a9af380991fbbda2520d93d990532f1a022cc6d8b3437edd
MD5 161b8996b9f500e63fe9db5ad107638d
BLAKE2b-256 030d5d481b462f66f5fb54d7fb1041faa8092467433d5c5b52c9aefabb553609

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page