Source code for scaffold_kit.main

"""Main CLI entry point for scaffold-kit.

This module provides a unified command-line interface for all scaffold-kit
subcommands: init, scaffold, checklist, and tree. It imports the core
functionality from each module and builds a proper CLI interface around them.

Usage:
    To run this script, navigate to your project's root directory or parent
    directory and execute it as a module:
    $ uv run python -m scaffold_kit.main init [options]
    $ uv run python -m scaffold_kit.main scaffold [options]
    $ uv run python -m scaffold_kit.main checklist
    $ uv run python -m scaffold_kit.main tree [options]
    $ uv run python -m scaffold_kit.main --help

    During development:
    $ uv run scaffold-kit init [options]
    $ uv run scaffold-kit scaffold [options]
    $ uv run scaffold-kit checklist
    $ uv run scaffold-kit tree [options]
    $ uv run scaffold-kit --help

    After installation:
    $ scaffold-kit init [options]
    $ scaffold-kit scaffold [options]
    $ scaffold-kit checklist
    $ scaffold-kit tree [options]
    $ scaffold-kit --help
"""

from __future__ import annotations

import sys
import argparse

from typing import NoReturn

from scaffold_kit import __description__, __title__, __url__, __version__
from scaffold_kit.checklist import generate_checklist
from scaffold_kit.config import (
    CHECKLIST_DIRECTORY,
    CHECKLIST_FILE,
    IGNORE_FILE,
    SCAFFOLD_FILE,
    TREE_DIRECTORY,
    TREE_FILE,
)
from scaffold_kit.init import init_project
from scaffold_kit.scaffold import scaffold_project
from scaffold_kit.tree import generate_tree


[docs] def create_parser() -> argparse.ArgumentParser: """Creates and configures the main argument parser with subcommands. Returns: Configured ArgumentParser with subcommands for scaffold, checklist, and tree. """ parser = argparse.ArgumentParser( prog=__title__, description=__description__, formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( "--version", action="version", version=f"{__title__} {__version__}", ) # Create subparsers for each command subparsers = parser.add_subparsers( dest="command", title="available commands", description="Choose a command to run", help=f"Run '{__title__} <command> --help' for command-specific help", metavar="<command>", ) # Init subcommand init_parser = subparsers.add_parser( "init", help="Initialize a new project by copying example files", description="Initialize a new project by copying example files.", ) # 2. Add the optional target argument. init_parser.add_argument( "target", type=str, nargs="?", choices=["ignore-file", "config-file", "scaffold-file"], help="Target file to copy (optional). " "If not provided, all files will be copied.", ) # Scaffold subcommand scaffold_parser = subparsers.add_parser( "scaffold", help="Create project structure from a structured data file", description=( "Creates a project structure from a YAML or JSON file definition. " "Supports creating top-level root folders and nested structures." ), ) scaffold_parser.add_argument( "-r", "--root", action="store_true", default=False, help="Create the root folder defined in the structured data file", ) # Checklist subcommand _checklist_parser = subparsers.add_parser( "checklist", help="Generate a checklist of files in the current directory", description=( "Scans the current directory and creates a text-based checklist " "of all files, marking them as complete [x] or incomplete [ ] " "based on content." ), ) # Tree subcommand tree_parser = subparsers.add_parser( "tree", help="Generate a hierarchical tree representation of a directory", description=( "Generates an ASCII tree diagram of directory structure, " "respecting ignore patterns and supporting partial trees." ), ) tree_parser.add_argument( "root_dir", nargs="?", default=".", help="Root directory to scan (default: current directory)", ) tree_parser.add_argument( "--ignore-file", default=IGNORE_FILE, help=f"Ignore file to use (default: {IGNORE_FILE})", ) return parser
[docs] def main() -> NoReturn: """Main entry point for the scaffold-kit CLI. Parses command-line arguments and dispatches to the appropriate subcommand. Exits with status code 0 on success, 1 on error, or 2 on invalid arguments. """ parser = create_parser() args = parser.parse_args() # If no subcommand provided, show help and exit. if not args.command: parser.print_help() sys.exit(2) try: # Dispatch to appropriate subcommand using core functions. if args.command == "init": exit_code = init_project(args.target) sys.exit(exit_code) elif args.command == "scaffold": scaffold_project(root=args.root, scaffold_file=SCAFFOLD_FILE) elif args.command == "checklist": generate_checklist( ignore_file=IGNORE_FILE, output_file=CHECKLIST_FILE, output_dir=CHECKLIST_DIRECTORY, ) elif args.command == "tree": generate_tree( root_dir=args.root_dir, ignore_file=args.ignore_file, output_file=TREE_FILE, output_dir=TREE_DIRECTORY, ) except KeyboardInterrupt: print("\nOperation cancelled by user.", file=sys.stderr) sys.exit(1) except Exception as e: # pylint: disable=broad-except print(f"Error: {e}", file=sys.stderr) sys.exit(1) sys.exit(0)
if __name__ == "__main__": main()