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
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.1.tar.gz (11.2 kB view details)

Uploaded Source

Built Distribution

shtab-0.0.1-py2.py3-none-any.whl (8.5 kB view details)

Uploaded Python 2 Python 3

File details

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

File metadata

  • Download URL: shtab-0.0.1.tar.gz
  • Upload date:
  • Size: 11.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.4.2 requests/2.23.0 setuptools/41.4.0 requests-toolbelt/0.8.0 tqdm/4.46.0 CPython/2.7.15

File hashes

Hashes for shtab-0.0.1.tar.gz
Algorithm Hash digest
SHA256 85ea262f0f37ce81ac88a1b0f9a13f01de880a4d3418cf60ea656391e0b56bbc
MD5 b5c1d8b5ca333c806d83b676209de2cd
BLAKE2b-256 de7c835675096d82b14593a3ae9d131bcc82cf5a206f7e50874d096210721057

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: shtab-0.0.1-py2.py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.4.2 requests/2.23.0 setuptools/41.4.0 requests-toolbelt/0.8.0 tqdm/4.46.0 CPython/2.7.15

File hashes

Hashes for shtab-0.0.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 80af50edc7675b742adda730ffce46e791ce0f6cbe9ea72d042fb4ac938009ae
MD5 8271f3455af94e899241ca436c15fefe
BLAKE2b-256 76dc27114bb06832ba629e496cfaf4ab852c69be19e1b3397e62b51081a1a2a5

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