diff --git a/codemap/cli/serve.py b/codemap/cli/serve.py new file mode 100644 index 0000000..dab0ee7 --- /dev/null +++ b/codemap/cli/serve.py @@ -0,0 +1,85 @@ +import os +import sys +import threading +import webbrowser +from pathlib import Path +from http.server import HTTPServer, SimpleHTTPRequestHandler +from typing import Optional +import typer +from rich.console import Console +from codemap.cli.analyze import _collect_files +from codemap.parsers import PythonParser, JavaScriptParser, GoParser +from codemap.core import GraphBuilder, MermaidGenerator +from codemap.templates import render_html + +console = Console() + +class QuietHTTPHandler(SimpleHTTPRequestHandler): + def log_message(self, format, *args): + pass + + +def serve( + path: str = typer.Argument(..., help="Directory to serve"), + port: int = typer.Option(8080, "--port", "-p", help="Port to serve on"), + open_browser: bool = typer.Option(True, "--open/--no-open", help="Open browser automatically"), +) -> None: + target_path = Path(path) + if not target_path.exists(): + console.print(f"[red]Error: Path '{path}' does not exist[/red]") + sys.exit(1) + + output_dir = target_path / ".codemap" + output_dir.mkdir(exist_ok=True) + + html_path = output_dir / "diagram.html" + + def generate_diagram(): + files = _collect_files(target_path) + if not files: + return None + + parsers = [PythonParser(), JavaScriptParser(), GoParser()] + parsed_files = [] + + for file_path in files: + for parser in parsers: + if parser.can_parse(file_path): + try: + parsed = parser.parse(file_path) + parsed_files.append(parsed) + except Exception: + pass + break + + builder = GraphBuilder() + builder.build_from_files(parsed_files) + + graph_data = builder.get_graph_data() + mermaid_gen = MermaidGenerator(graph_data) + return render_html(mermaid_gen.generate_flowchart(), title=f"Code Map: {path}", auto_refresh=True, refresh_interval=5) + + with console.status("[bold green]Generating diagram...[/bold green]") as status: + html_content = generate_diagram() + + if html_content: + html_path.write_text(html_content, encoding="utf-8") + + os.chdir(str(output_dir)) + server = HTTPServer(('localhost', port), QuietHTTPHandler) + + url = f"http://localhost:{port}/diagram.html" + console.print(f"[bold green]Serving at: {url}[/bold green]") + console.print(f"[dim]Diagram file: {html_path}[/dim]") + console.print("[dim]Press Ctrl+C to stop[/dim]") + + if open_browser: + threading.Timer(1.0, lambda: webbrowser.open(url)).start() + + try: + server.serve_forever() + except KeyboardInterrupt: + console.print("\n[yellow]Stopping server...[/yellow]") + server.shutdown() + else: + console.print("[yellow]No files found to analyze[/yellow]")