Add init init-global to subparsers

This commit is contained in:
Roland Thomas Jr 2025-05-31 09:29:24 -04:00
parent 3d3a706784
commit 1585098513
Signed by: roland
GPG Key ID: 7C3C2B085A4C2872
6 changed files with 125 additions and 12 deletions

View File

@ -8,12 +8,13 @@ Licensed under the MIT License. See LICENSE file for details.
import asyncio
import os
import sys
from argparse import ArgumentParser, Namespace, _SubParsersAction
from pathlib import Path
from typing import Any
from falyx.config import loader
from falyx.falyx import Falyx
from falyx.parsers import CommandArgumentParser
from falyx.parsers import CommandArgumentParser, get_root_parser, get_subparsers
def find_falyx_config() -> Path | None:
@ -48,6 +49,42 @@ def init_config(parser: CommandArgumentParser) -> None:
)
def init_callback(args: Namespace) -> None:
"""Callback for the init command."""
if args.command == "init":
from falyx.init import init_project
init_project(args.name)
elif args.command == "init_global":
from falyx.init import init_global
init_global()
def get_parsers() -> tuple[ArgumentParser, _SubParsersAction]:
root_parser: ArgumentParser = get_root_parser()
subparsers = get_subparsers(root_parser)
init_parser = subparsers.add_parser(
"init",
help="Initialize a new Falyx project",
description="Create a new Falyx project with mock configuration files.",
epilog="If no name is provided, the current directory will be used.",
)
init_parser.add_argument(
"name",
type=str,
help="Name of the new Falyx project",
default=".",
nargs="?",
)
subparsers.add_parser(
"init-global",
help="Initialize Falyx global configuration",
description="Create a global Falyx configuration at ~/.config/falyx/.",
)
return root_parser, subparsers
def main() -> Any:
bootstrap_path = bootstrap()
if not bootstrap_path:
@ -60,17 +97,23 @@ def main() -> Any:
init_project,
aliases=["init"],
argument_config=init_config,
help_epilogue="If no name is provided, the current directory will be used.",
)
flx.add_command(
"G",
"Initialize Falyx global configuration",
init_global,
aliases=["init-global"],
help_text="Create a global Falyx configuration at ~/.config/falyx/.",
)
else:
flx = loader(bootstrap_path)
return asyncio.run(flx.run())
root_parser, subparsers = get_parsers()
return asyncio.run(
flx.run(root_parser=root_parser, subparsers=subparsers, callback=init_callback)
)
if __name__ == "__main__":

View File

@ -25,7 +25,7 @@ import asyncio
import logging
import shlex
import sys
from argparse import Namespace
from argparse import ArgumentParser, Namespace, _SubParsersAction
from difflib import get_close_matches
from enum import Enum
from functools import cached_property
@ -1029,6 +1029,8 @@ class Falyx:
async def run(
self,
falyx_parsers: FalyxParsers | None = None,
root_parser: ArgumentParser | None = None,
subparsers: _SubParsersAction | None = None,
callback: Callable[..., Any] | None = None,
) -> None:
"""Run Falyx CLI with structured subcommands."""
@ -1046,6 +1048,8 @@ class Falyx:
self.description,
self.epilog,
commands=self.commands,
root_parser=root_parser,
subparsers=subparsers,
)
self.cli_args = falyx_parsers.parse_args()
self.options.from_namespace(self.cli_args, "cli_args")

View File

@ -6,12 +6,14 @@ Licensed under the MIT License. See LICENSE file for details.
"""
from .argparse import Argument, ArgumentAction, CommandArgumentParser
from .parsers import FalyxParsers, get_arg_parsers
from .parsers import FalyxParsers, get_arg_parsers, get_root_parser, get_subparsers
__all__ = [
"Argument",
"ArgumentAction",
"CommandArgumentParser",
"get_arg_parsers",
"get_root_parser",
"get_subparsers",
"FalyxParsers",
]

View File

@ -40,7 +40,7 @@ class FalyxParsers:
return self.as_dict().get(name)
def get_arg_parsers(
def get_root_parser(
prog: str | None = "falyx",
usage: str | None = None,
description: str | None = "Falyx CLI - Run structured async command workflows.",
@ -55,9 +55,7 @@ def get_arg_parsers(
add_help: bool = True,
allow_abbrev: bool = True,
exit_on_error: bool = True,
commands: dict[str, Command] | None = None,
) -> FalyxParsers:
"""Returns the argument parser for the CLI."""
) -> ArgumentParser:
parser = ArgumentParser(
prog=prog,
usage=usage,
@ -86,7 +84,70 @@ def get_arg_parsers(
help="Enable default lifecycle debug logging",
)
parser.add_argument("--version", action="store_true", help="Show Falyx version")
subparsers = parser.add_subparsers(dest="command")
return parser
def get_subparsers(
parser: ArgumentParser,
title: str = "Falyx Commands",
description: str | None = "Available commands for the Falyx CLI.",
) -> _SubParsersAction:
"""Create and return a subparsers action for the given parser."""
if not isinstance(parser, ArgumentParser):
raise TypeError("parser must be an instance of ArgumentParser")
subparsers = parser.add_subparsers(
title=title,
description=description,
metavar="COMMAND",
dest="command",
)
return subparsers
def get_arg_parsers(
prog: str | None = "falyx",
usage: str | None = None,
description: str | None = "Falyx CLI - Run structured async command workflows.",
epilog: (
str | None
) = "Tip: Use 'falyx run ?[COMMAND]' to preview any command from the CLI.",
parents: Sequence[ArgumentParser] | None = None,
prefix_chars: str = "-",
fromfile_prefix_chars: str | None = None,
argument_default: Any = None,
conflict_handler: str = "error",
add_help: bool = True,
allow_abbrev: bool = True,
exit_on_error: bool = True,
commands: dict[str, Command] | None = None,
root_parser: ArgumentParser | None = None,
subparsers: _SubParsersAction | None = None,
) -> FalyxParsers:
"""Returns the argument parser for the CLI."""
if root_parser is None:
parser = get_root_parser(
prog=prog,
usage=usage,
description=description,
epilog=epilog,
parents=parents,
prefix_chars=prefix_chars,
fromfile_prefix_chars=fromfile_prefix_chars,
argument_default=argument_default,
conflict_handler=conflict_handler,
add_help=add_help,
allow_abbrev=allow_abbrev,
exit_on_error=exit_on_error,
)
else:
if not isinstance(root_parser, ArgumentParser):
raise TypeError("root_parser must be an instance of ArgumentParser")
parser = root_parser
if subparsers is None:
subparsers = get_subparsers(parser)
if not isinstance(subparsers, _SubParsersAction):
raise TypeError("subparsers must be an instance of _SubParsersAction")
run_description = ["Run a command by its key or alias.\n"]
run_description.append("commands:")
@ -105,7 +166,9 @@ def get_arg_parsers(
epilog=run_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
run_parser.add_argument("name", help="Run a command by its key or alias")
run_parser.add_argument(
"name", help="Run a command by its key or alias", metavar="COMMAND"
)
run_parser.add_argument(
"--summary",
action="store_true",
@ -143,6 +206,7 @@ def get_arg_parsers(
"command_args",
nargs=REMAINDER,
help="Arguments to pass to the command (if applicable)",
metavar="ARGS",
)
run_all_parser = subparsers.add_parser(

View File

@ -1 +1 @@
__version__ = "0.1.42"
__version__ = "0.1.43"

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "falyx"
version = "0.1.42"
version = "0.1.43"
description = "Reliable and introspectable async CLI action framework."
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
license = "MIT"