Refactor CLI implementation: add help callback and improve help handling; update setup.py dependencies

This commit is contained in:
Chipperfluff 2026-04-03 14:31:06 +02:00
parent c9176dbbce
commit 37eaee3dbe
3 changed files with 60 additions and 26 deletions

View File

@ -1,7 +1,12 @@
from cli import CLI
from .cli import CLI
def help_text():
return [
"%bold%%cyan%nut CLI ... you expected a help menu? cute :3%reset%"
]
def main():
cli = CLI("nut")
cli = CLI(help_callback=help_text)
cli.command("run") \
.flag("debug", "d") \
@ -12,17 +17,13 @@ def main():
return cli.run()
def cmd_run(subcommands, flags):
print("RUN")
print("sub:", subcommands)
print("flags:", flags)
def cmd_run(args, flags):
print("RUN", args, flags)
return 0
def cmd_build(subcommands, flags):
print("BUILD")
print("sub:", subcommands)
print("flags:", flags)
def cmd_build(args, flags):
print("BUILD", args, flags)
return 0
if __name__ == "__main__":
raise SystemExit(main())
raise SystemExit(main())

View File

@ -1,46 +1,78 @@
import argparse
from colorama import Fore, Style, init
init(autoreset=True)
class CLI:
def __init__(self, prog="nut"):
self.parser = argparse.ArgumentParser(prog=prog)
self.subparsers = self.parser.add_subparsers(dest="command", required=True)
def __init__(self, prog="nut", help_callback=None):
self.parser = argparse.ArgumentParser(prog=prog, add_help=False)
self.subparsers = self.parser.add_subparsers(dest="command")
self.help_callback = help_callback
self.parser.add_argument("-h", "--help", action="store_true")
def command(self, name):
parser = self.subparsers.add_parser(name)
parser = self.subparsers.add_parser(name, add_help=False)
cmd = _Command(parser)
return cmd
def run(self):
args = self.parser.parse_args()
# extract structured data
sub_args = getattr(args, "_args", [])
if getattr(args, "help", False) or not getattr(args, "command", None):
if self.help_callback:
for line in self.help_callback():
print(self._color(line))
else:
self.parser.print_help()
return 0
args_list = getattr(args, "_args", [])
flags = {
k: v for k, v in vars(args).items()
if k not in ("command", "func", "_args")
if k not in ("command", "func", "_args", "help")
}
return args.func(sub_args, flags)
return args.func(args_list, flags)
def _color(self, text: str) -> str:
mapping = {
"%red%": Fore.RED,
"%green%": Fore.GREEN,
"%yellow%": Fore.YELLOW,
"%blue%": Fore.BLUE,
"%magenta%": Fore.MAGENTA,
"%cyan%": Fore.CYAN,
"%white%": Fore.WHITE,
"%reset%": Style.RESET_ALL,
"%bold%": Style.BRIGHT,
}
for key, value in mapping.items():
text = text.replace(key, value)
return text
class _Command:
def __init__(self, parser):
self.parser = parser
self.parser.set_defaults(func=self._missing)
# default catch-all args
self.parser.add_argument("_args", nargs="*")
self.parser.add_argument("-h", "--help", action="store_true")
def arg(self, name, **kwargs):
self.parser.add_argument(name, **kwargs)
return self
def flag(self, name, short=None):
flags = [f"--{name}"]
opts = [f"--{name}"]
if short:
flags.append(f"-{short}")
opts.append(f"-{short}")
self.parser.add_argument(*flags, action="store_true")
self.parser.add_argument(*opts, action="store_true")
return self
def handle(self, func):
@ -48,4 +80,5 @@ class _Command:
return self
def _missing(self, *_):
raise RuntimeError("No handler defined for command")
raise RuntimeError("No handler defined")

View File

@ -7,5 +7,5 @@ setup(
author="Chipperfluff",
packages=find_packages(),
python_requires=">=3.8",
install_requires=["chipenv"],
install_requires=["chipenv", "colorama", "PyYAML"],
)