diff options
| author | Danilo M. <danix@danix.xyz> | 2026-06-30 15:09:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-06-30 15:09:34 +0200 |
| commit | 9c15e172eb5b50796eb050cc5704471bce09e024 (patch) | |
| tree | 01433901ddd2bb8db3f2498a225c49faae26d295 /scripts | |
| parent | 93dbbe18e934d87ebf6ae6c614bb26f0e9e5afa5 (diff) | |
| download | firefly-cli-0.2.1.tar.gz firefly-cli-0.2.1.zip | |
help, completion: descriptive help text and bash completionv0.2.1
Add group/leaf descriptions to argparse help and richer command help
strings. Add generated bash completion (completions/firefly.bash) plus
its generator (scripts/gen_completion.py), wired into the command
checklist in CLAUDE.md and documented in the README. Bump to 0.2.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/gen_completion.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/scripts/gen_completion.py b/scripts/gen_completion.py new file mode 100644 index 0000000..a97f26b --- /dev/null +++ b/scripts/gen_completion.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> GPL-2.0-only +"""Generate completions/firefly.bash from the live command registry. + + python scripts/gen_completion.py > completions/firefly.bash + +No drift: groups, leaves, and per-leaf flags are read straight off the +argparse subparsers the registry builds. +""" +import argparse +from collections import defaultdict + +from firefly_cli import registry +import firefly_cli.commands # noqa: F401 triggers registration + +GROUP_ORDER = ["auth", "account", "category", "tag", "tx"] + + +def collect(): + groups = defaultdict(dict) # group -> {leaf: [--flag, ...]} + for c in registry.all_commands(): + g, _, leaf = c.name.partition(" ") + p = argparse.ArgumentParser() + if c.args: + c.args(p) + opts = [] + for a in p._actions: + opts += [s for s in a.option_strings + if s.startswith("--") and s != "--help"] + groups[g][leaf] = sorted(opts) + return groups + + +def render(groups): + order = [g for g in GROUP_ORDER if g in groups] + order += [g for g in sorted(groups) if g not in GROUP_ORDER] + + leaf_cases, group_cases = [], [] + for g in order: + leaves = " ".join(sorted(groups[g])) + group_cases.append(f' {g}) leaves="{leaves}";;') + for leaf in sorted(groups[g]): + flags = " ".join(groups[g][leaf]) + if flags: + leaf_cases.append( + f' "{g} {leaf}")'.ljust(28) + f'leaf_opts="{flags}";;') + + return TEMPLATE.format( + groups=" ".join(order), + leaf_cases="\n".join(leaf_cases), + group_cases="\n".join(group_cases), + ) + + +TEMPLATE = '''# bash completion for firefly (firefly-cli) +# Install: source this file, or drop it in /etc/bash_completion.d/ or +# /usr/share/bash-completion/completions/firefly +# +# Generated by scripts/gen_completion.py -- do not edit by hand. +# Regenerate when commands change (see CLAUDE.md): +# python scripts/gen_completion.py > completions/firefly.bash + +_firefly() {{ + local cur prev words cword + _init_completion 2>/dev/null || {{ + cur="${{COMP_WORDS[COMP_CWORD]}}" + prev="${{COMP_WORDS[COMP_CWORD-1]}}" + words=("${{COMP_WORDS[@]}}") + cword=$COMP_CWORD + }} + + local global_opts="--human --url --token -h --help" + local groups="{groups}" + + # Find the group and leaf among the words (skip the program name at 0). + local group="" leaf="" i + for ((i=1; i < cword; i++)); do + local w="${{words[i]}}" + case "$w" in + -*) ;; # an option, skip + --url|--token) ((i++));; # option that takes a value + *) + if [[ -z $group ]]; then group="$w" + elif [[ -z $leaf ]]; then leaf="$w" + fi + ;; + esac + done + + # Leaf-specific options. + local leaf_opts="" + case "$group $leaf" in +{leaf_cases} + esac + + # Leaves per group. + local leaves="" + case "$group" in +{group_cases} + esac + + if [[ -z $group ]]; then + COMPREPLY=($(compgen -W "$groups $global_opts" -- "$cur")) + elif [[ -z $leaf ]]; then + COMPREPLY=($(compgen -W "$leaves" -- "$cur")) + else + COMPREPLY=($(compgen -W "$leaf_opts --help" -- "$cur")) + fi +}} +complete -F _firefly firefly +''' + + +if __name__ == "__main__": + print(render(collect()), end="") |
