Files
doc-forge/docforge/cli/main.py
Vishesh 'ironeagle' Bangotra b6e5114532
All checks were successful
continuous-integration/drone/tag Build is passing
added docs strings
2026-01-21 01:00:12 +05:30

192 lines
4.7 KiB
Python

"""
Main entry point for the doc-forge CLI. This module defines the core command
group and the 'tree', 'generate', 'build', and 'serve' commands.
"""
from pathlib import Path
from typing import Sequence, Optional
import click
from docforge.loader import GriffeLoader, discover_module_paths
from docforge.renderers.mkdocs import MkDocsRenderer
from docforge.cli.mkdocs import mkdocs_cmd
@click.group()
def cli() -> None:
"""
doc-forge CLI: A tool for introspecting Python projects and generating
documentation.
"""
pass
cli.add_command(mkdocs_cmd)
# ---------------------------------------------------------------------
# tree
# ---------------------------------------------------------------------
@cli.command()
@click.option(
"--modules",
multiple=True,
required=True,
help="Python module import paths to introspect",
)
@click.option(
"--project-name",
help="Project name (defaults to first module)",
)
def tree(
modules: Sequence[str],
project_name: Optional[str],
) -> None:
"""
Visualize the project structure including modules and their members.
Args:
modules: List of module paths to introspect.
project_name: Optional project name override.
"""
loader = GriffeLoader()
project = loader.load_project(list(modules), project_name)
click.echo(project.name)
for module in project.get_all_modules():
click.echo(f"├── {module.path}")
for obj in module.get_all_objects():
_print_object(obj, indent="")
def _print_object(obj, indent: str) -> None:
"""
Recursive helper to print doc objects.
"""
click.echo(f"{indent}├── {obj.name}")
for member in obj.get_all_members():
_print_object(member, indent + "")
# ---------------------------------------------------------------------
# generate
# ---------------------------------------------------------------------
@cli.command()
@click.option(
"--module",
required=True,
help="Python module import paths to document",
)
@click.option(
"--project-name",
help="Project name (defaults to first module)",
)
@click.option(
"--docs-dir",
type=click.Path(path_type=Path),
default=Path("docs"),
)
def generate(
module: str,
project_name: Optional[str],
docs_dir: Path,
) -> None:
"""
Generate Markdown source files for the specified module.
Args:
module: The primary module path to document.
project_name: Optional project name override.
docs_dir: Directory where documentation sources will be written.
"""
loader = GriffeLoader()
discovered_paths = discover_module_paths(
module,
)
project = loader.load_project(
discovered_paths,
project_name
)
renderer = MkDocsRenderer()
renderer.generate_sources(project, docs_dir)
click.echo(f"Documentation sources generated in {docs_dir}")
# ---------------------------------------------------------------------
# build
# ---------------------------------------------------------------------
@cli.command()
@click.option(
"--mkdocs-yml",
type=click.Path(path_type=Path),
default=Path("mkdocs.yml"),
)
def build(mkdocs_yml: Path) -> None:
"""
Build the documentation site using MkDocs.
Args:
mkdocs_yml: Path to the mkdocs.yml configuration file.
"""
if not mkdocs_yml.exists():
raise click.ClickException(f"mkdocs.yml not found: {mkdocs_yml}")
from mkdocs.config import load_config
from mkdocs.commands.build import build as mkdocs_build
mkdocs_build(load_config(str(mkdocs_yml)))
click.echo("MkDocs build completed")
# ---------------------------------------------------------------------
# serve
# ---------------------------------------------------------------------
@cli.command()
@click.option(
"--mkdocs-yml",
type=click.Path(path_type=Path),
default=Path("mkdocs.yml"),
)
def serve(mkdocs_yml: Path) -> None:
"""
Serve the documentation site with live-reload using MkDocs.
Args:
mkdocs_yml: Path to the mkdocs.yml configuration file.
"""
if not mkdocs_yml.exists():
raise click.ClickException(f"mkdocs.yml not found: {mkdocs_yml}")
from mkdocs.commands.serve import serve as mkdocs_serve
host = "127.0.0.1"
port = 8000
url = f"http://{host}:{port}/"
click.echo(f"Serving documentation at {url}")
mkdocs_serve(config_file=str(mkdocs_yml))
# ---------------------------------------------------------------------
# entry point
# ---------------------------------------------------------------------
def main() -> None:
"""
CLI Entry point.
"""
cli()
if __name__ == "__main__":
main()