diff --git a/src/cli.py b/src/cli.py index ae567d8..c9aefb8 100644 --- a/src/cli.py +++ b/src/cli.py @@ -1,226 +1,111 @@ -import os +import sys +from datetime import datetime +from pathlib import Path from typing import Optional import click -from rich.console import Console +from rich import print as rprint -from src.git_insights import GitInsights -from src.utils.config import load_config - -console = Console() +from git_insights import GitInsights +from git_insights.formatters import DashboardFormatter, JSONFormatter, MarkdownFormatter, HTMLFormatter @click.group() -@click.option( - "--repo-path", - "-p", - default=".", - help="Path to git repository", -) -@click.option( - "--days", - "-d", - default=30, - type=int, - help="Number of days to analyze", -) -@click.option( - "--config", - "-c", - default=None, - type=str, - help="Path to config file", -) -@click.pass_context -def main( - ctx: click.Context, - repo_path: str, - days: int, - config: Optional[str], -) -> None: +def main(): """Git Insights CLI - Analyze git repositories for productivity insights.""" - ctx.ensure_object(dict) - ctx.obj["repo_path"] = repo_path - ctx.obj["days"] = days - ctx.obj["config"] = config + pass @main.command() -@click.option( - "--format", - "-f", - type=click.Choice(["json", "markdown", "html", "console"]), - default="console", - help="Output format", -) -@click.pass_context -def analyze(ctx: click.Context, format: str) -> None: - """Analyze repository for commit patterns, code churn, and productivity metrics.""" - repo_path = ctx.obj["repo_path"] - days = ctx.obj["days"] - config_path = ctx.obj["config"] - - config = load_config(config_path) if config_path else None - - if not os.path.isdir(repo_path): - console.print(f"[red]Error: Directory not found: {repo_path}[/red]") - return - +@click.argument("path", type=click.Path(exists=True), required=False, default=".") +@click.option("--days", type=int, default=30, help="Number of days to analyze") +@click.option("--format", type=click.Choice(["json", "markdown", "html"]), default="console", help="Output format") +@click.option("-v", "--verbose", is_flag=True, help="Enable verbose output") +def analyze(path: str, days: int, format: str, verbose: bool): + """Analyze a git repository for commit patterns and productivity metrics.""" try: - insights = GitInsights( - repo_path=repo_path, - days=days, - config=config, - ) - - results = insights.analyze() + insights = GitInsights(path, days=days) + result = insights.analyze() if format == "json": - from src.formatters import JSONFormatter - console.print(JSONFormatter.format(results)) + click.echo(JSONFormatter.format(result)) elif format == "markdown": - from src.formatters import MarkdownFormatter - console.print(MarkdownFormatter.format(results)) + click.echo(MarkdownFormatter.format(result)) elif format == "html": - from src.formatters import HTMLFormatter - console.print(HTMLFormatter.format(results)) + click.echo(HTMLFormatter.format(result)) else: - from src.formatters import DashboardFormatter - DashboardFormatter.display(results) + DashboardFormatter.display(result) + + if verbose: + click.echo(f"\nAnalysis period: {days} days") + click.echo(f"Repository: {Path(path).resolve()}") + click.echo(f"Timestamp: {datetime.now().isoformat()}") except Exception as e: - console.print(f"[red]Error: {e}[/red]") - raise + rprint(f"[red]Error: {e}[/red]") + sys.exit(1) @main.command() -@click.pass_context -def dashboard(ctx: click.Context) -> None: +@click.argument("path", type=click.Path(exists=True), required=False, default=".") +@click.option("--days", type=int, default=30, help="Number of days to analyze") +def dashboard(path: str, days: int): """Display productivity metrics in an interactive dashboard.""" - repo_path = ctx.obj["repo_path"] - days = ctx.obj["days"] - config_path = ctx.obj["config"] - - config = load_config(config_path) if config_path else None - - if not os.path.isdir(repo_path): - console.print(f"[red]Error: Directory not found: {repo_path}[/red]") - return - try: - insights = GitInsights( - repo_path=repo_path, - days=days, - config=config, - ) - - results = insights.analyze() - from src.formatters import DashboardFormatter - DashboardFormatter.display(results) - + insights = GitInsights(path, days=days) + result = insights.analyze() + DashboardFormatter.display(result) except Exception as e: - console.print(f"[red]Error: {e}[/red]") - raise + rprint(f"[red]Error: {e}[/red]") + sys.exit(1) @main.command() -@click.option( - "--format", - "-f", - type=click.Choice(["json", "markdown", "html"]), - default="json", - help="Output format", -) -@click.option( - "--output", - "-o", - default=None, - type=str, - help="Output file path", -) -@click.pass_context -def export(ctx: click.Context, format: str, output: Optional[str]) -> None: +@click.argument("path", type=click.Path(exists=True), required=False, default=".") +@click.option("--days", type=int, default=30, help="Number of days to analyze") +@click.option("--format", type=click.Choice(["json", "markdown", "html"]), default="json", help="Output format") +@click.option("--output", type=click.Path(), help="Output file path") +def export(path: str, days: int, format: str, output: Optional[str]): """Export analysis results to a file.""" - repo_path = ctx.obj["repo_path"] - days = ctx.obj["days"] - config_path = ctx.obj["config"] - - config = load_config(config_path) if config_path else None - - if not os.path.isdir(repo_path): - console.print(f"[red]Error: Directory not found: {repo_path}[/red]") - return - try: - insights = GitInsights( - repo_path=repo_path, - days=days, - config=config, - ) - - results = insights.analyze() + insights = GitInsights(path, days=days) + result = insights.analyze() if format == "json": - from src.formatters import JSONFormatter - output_str = JSONFormatter.format(results) + content = JSONFormatter.format(result) elif format == "markdown": - from src.formatters import MarkdownFormatter - output_str = MarkdownFormatter.format(results) + content = MarkdownFormatter.format(result) else: - from src.formatters import HTMLFormatter - output_str = HTMLFormatter.format(results) + content = HTMLFormatter.format(result) if output: - with open(output, "w") as f: - f.write(output_str) - console.print(f"[green]Exported to {output}[/green]") + Path(output).write_text(content) + click.echo(f"Exported to {output}") else: - console.print(output_str) + click.echo(content) except Exception as e: - console.print(f"[red]Error: {e}[/red]") - raise + rprint(f"[red]Error: {e}[/red]") + sys.exit(1) @main.command() -@click.option( - "--output", - "-o", - default=None, - type=str, - help="Output file path", -) -@click.pass_context -def report(ctx: click.Context, output: Optional[str]) -> None: +@click.argument("path", type=click.Path(exists=True), required=False, default=".") +@click.option("--days", type=int, default=30, help="Number of days to analyze") +@click.option("--output", type=click.Path(), help="Output file path") +def report(path: str, days: int, output: Optional[str]): """Generate a comprehensive productivity report.""" - repo_path = ctx.obj["repo_path"] - days = ctx.obj["days"] - config_path = ctx.obj["config"] - - config = load_config(config_path) if config_path else None - - if not os.path.isdir(repo_path): - console.print(f"[red]Error: Directory not found: {repo_path}[/red]") - return - try: - insights = GitInsights( - repo_path=repo_path, - days=days, - config=config, - ) - - results = insights.analyze() - from src.formatters import HTMLFormatter - report_str = HTMLFormatter.format(results) + insights = GitInsights(path, days=days) + report = insights.get_productivity_report() + content = HTMLFormatter.format(report) if output: - with open(output, "w") as f: - f.write(report_str) - console.print(f"[green]Report generated: {output}[/green]") + Path(output).write_text(content) + click.echo(f"Report generated: {output}") else: - console.print(report_str) + click.echo(content) except Exception as e: - console.print(f"[red]Error: {e}[/red]") - raise + rprint(f"[red]Error: {e}[/red]") + sys.exit(1)