Skip to main content

Generate zsh completions with Python.

Project description

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

Project details


Download files

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

Source Distribution

zcompy-0.0.1.tar.gz (27.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zcompy-0.0.1-py3-none-any.whl (26.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: zcompy-0.0.1.tar.gz
  • Upload date:
  • Size: 27.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for zcompy-0.0.1.tar.gz
Algorithm Hash digest
SHA256 0a9f14ed177667be3ae264c130544d6cde8427415bb9d73e9b83aac3c8d14da8
MD5 3fddcc2c21296d74bb7b84fbedecfc17
BLAKE2b-256 8ae4f9425da74ec67f335b6d8f4e228244303b062e31f759fb97dfe2877df00b

See more details on using hashes here.

File details

Details for the file zcompy-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: zcompy-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 26.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for zcompy-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b0f7500dbc237e4fa75e1c12ef32a634df2fd5f1d6ae25f2345ef96fb6eaff1e
MD5 872c7bb8962121512bc9315e14a465e7
BLAKE2b-256 78574fdb2c3f1cb2b2617a2852830d14f1f6f2cf7c9d84a7ebf1f1289cb1e6be

See more details on using hashes here.

Supported by

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