Skip to main content

zcompy

zcompy (zsh completion using Python) is a Python library that makes it easy to generate sophisticated zsh completion scripts for your command-line tools.

Instead of writing complex zsh completion scripts by hand, you can define your commands and options in Python and let zcompy generate the completion for you.

Features

  • 🐍 Pure Python: Define completions using familiar Python syntax
  • 🎯 Type-safe: Built-in support for common argument types (files, directories, strings)
  • 🔄 Sub-commands: Full support for nested sub-commands
  • 🎨 Custom completions: Define your own completion functions with python functions
  • 🔗 Dependencies: Completion could depend on other option values

Installation

From PyPI

pip install zcompy

From Source

git clone https://github.com/FateScript/zcompy.git
cd zcompy
pip install -e .

Development Installation

git clone https://github.com/FateScript/zcompy.git
cd zcompy
pip install -e ".[dev]"

Quick Start

Here's a simple example to get you started:

from zcompy import Command, Option, Files, Completion

# Create your command
mytool = Command("mytool", "My awesome command-line tool")

# Add global options for mytool
mytool.add_options([
    Option(("--verbose", "-v"), "Enable verbose output"),
    Option(("--config", "-c"), "Config file path", complete_func=Files())
])

# Create sub-commands
build_cmd = Command("build", "Build the project")
build_cmd.add_options([
    Option(
        ("--output", "-o"), "Output directory",
        complete_func=Files(dir_only=True)
    ),
    Option(
        ("--optimize", "-O"), "Optimization level",
        complete_func=Completion(func=("o1", "o2", "o3"))
    )
])

# Add sub-command to main command
mytool.add_sub_commands(build_cmd)

# print completion source
print(mytool.complete_source())
# Also, you might generate zsh completion code in output dir
# mytool.completion_entry(output_dir="~/.zsh/completion")

Then add to your ~/.zshrc or run in your terminal sesssion:

fpath=(~/.zsh/completions $fpath)
autoload -U compinit && compinit
compdef _mytool mytool

👉 Please type mytool in cli and press <TAB> to feel the magic 🪄

Usage

Basic Command Structure

from zcompy import Command, Option, Completion, Files

# Create a command
cmd = Command("mycmd", "Description of your command")

# Add options
cmd.add_options([
    Option(("--flag", "-f"), "Turn on to enable something"),
    Option(("--file",), "Input file", complete_func=Files()),
    Option(("--dir",), "Output directory", complete_func=Files(dir_only=True))
])

Sub-commands

# Create main command
main = Command("git", "Git version control")

# Create sub-commands
status = Command("status", "Show working tree status")
commit = Command("commit", "Record changes to repository")
commit.add_options([
    Option(("--message", "-m"), "Commit message", type="STRING"),
    Option(("--amend",), "Amend previous commit")
])

# Add sub-commands to main
main.add_sub_commands([status, commit])

Custom Completions

Define your own completion functions

NOTE:

  1. To make your completions work, simply print each completion string to stdout.
  2. If you want to show descriptions for completions, print them after a space, like: completion description.
def list_things():
    for item in ["thing1", "thing2", "thing3"]:
        print(f"my_{item}")

branch_option = Option(
    ("--things", "-t"), 
    "things to describe",
    type="THINGS", 
    complete_func=Completion(list_things)
)

Advanced Usage

Automatic CLI Framework Support

zcompy provides built-in support for generating completions from popular Python CLI frameworks:

ArgumentParser support
from argparse import ArgumentParser
from zcompy.parser_command import ParserCommand

# Create your argparse parser
parser = ArgumentParser(prog="mytool", description="My awesome CLI tool")
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output")
parser.add_argument("--config", "-c", type=str, help="Config file path")
parser.add_argument("--mode", choices=["auto", "manual", "disabled"], help="Operation mode")

# Add sub-commands
subparsers = parser.add_subparsers(dest="command")
build_parser = subparsers.add_parser("build", help="Build the project")
build_parser.add_argument("--output", "-o", type=str, help="Output directory")

# Generate completion using zcompy
parser_command = ParserCommand(parser)
command = parser_command.to_command()
print(command.complete_source())

# Add custom completion for file paths
from zcompy.action import Files
parser_command.add_action_for_options("--config", "--output", action=Files())
Abseil (absl-py) Support
from absl import flags
from zcompy.absl_command import AbslFlagsCommand

# Define your absl flags
FLAGS = flags.FLAGS
flags.DEFINE_string('name', 'World', 'The name to greet')
flags.DEFINE_integer('count', 1, 'The number of greetings')
flags.DEFINE_bool('verbose', False, 'Whether to display verbose output')
flags.DEFINE_enum('color', 'blue', ['red', 'blue', 'green'], 'Choose a color')

# Generate completion using zcompy
cmd = AbslFlagsCommand(name="mytool").to_command()
print(cmd.complete_source())
Fire Support

Users could use FireCommand like fire-guide.

python class
import fire
from zcompy.fire_command import FireCommand

class MyCLI:
    """My awesome CLI tool."""

    def add(self, x, y):
        """Addition command"""
        return x + y

    def mul(self, a, b):
        """Multiplication command"""
        return a * b

    def build(self, output_dir="./build", optimize=True):
        """Build the project"""
        return f"Building to {output_dir}"

# Generate completion using zcompy
fire_cmd = FireCommand(name="mytool", obj=MyCLI)
command = fire_cmd.to_command()
print(command.complete_source())
python function
def add_func(x, y):
    """Addition command"""
    return x + y

fire_cmd = FireCommand(name="calc", obj=add_func)
command = fire_cmd.to_command()
print(command.complete_source())
python dict
func_dict = {"add": lambda x, y: x + y, "mul": lambda a, b: a * b}
fire_cmd = FireCommand(name="math", obj=func_dict)
command = fire_cmd.to_command()
print(command.complete_source())

Dependent Completions

Completions could depend on other options' value/existence:

from zcompy import DependentCompletion, Option

def complete_based_on_config(config_path):
    """Complete based on config_path value."""
    if config_path and os.path.exists(config_path):
        # Read config and provide completions
        with open(config_path) as f:
            configs = f.read().splitlines()
        for line, config in enumerate(configs):
            print(f"{config} line {line + 1}")

config_dependent = Option(
    ("--target",), 
    "Target based on config",
    type="TARGET",
    complete_func=DependentCompletion(
        func=complete_based_on_config,
        depends_on="--config"
    )
)

Positional Arguments

from zcompy.action import GitBranches, GitCommits

# Add positional arguments
cmd.add_positional_args([
    Files("*.py"),
    GitBranches(),
    GitCommits(),
])

# Use repeat_pos_args if you want to repeat positional arguments.
# for example, `cmd file1 file2 file3`
cmd.repeat_pos_args = Files()

Development

Setup Development Environment

git clone https://github.com/FateScript/zcompy.git
cd zcompy
python -m venv zcompy
source zcompy/bin/activate
pip install -e ".[dev]"

Running Tests

pytest tests

Acknowledgments

Metadata

Release files for zcompy 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zcompy 0.0.1
File Size Uploaded
zcompy-0.0.1.tar.gz 27.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zcompy 0.0.1
File Interpreter ABI Platform
zcompy-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 54.0 kB

Release files / zcompy-0.0.1.tar.gz

Download URL zcompy-0.0.1.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0a9f14ed177667be3ae264c130544d6cde8427415bb9d73e9b83aac3c8d14da8
BLAKE2b-256 checksum
How to use checksums
8ae4f9425da74ec67f335b6d8f4e228244303b062e31f759fb97dfe2877df00b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.10

Release files / zcompy-0.0.1-py3-none-any.whl

Download URL zcompy-0.0.1-py3-none-any.whl
Size 26.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b0f7500dbc237e4fa75e1c12ef32a634df2fd5f1d6ae25f2345ef96fb6eaff1e
BLAKE2b-256 checksum
How to use checksums
78574fdb2c3f1cb2b2617a2852830d14f1f6f2cf7c9d84a7ebf1f1289cb1e6be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page