"""Visualize command for CLI.""" from pathlib import Path from typing import Optional import click from rich.console import Console from rich.panel import Panel from rich.text import Text from ..core.database import SessionDatabase from ..core.session import Session from ..parsers.git_parser import GitLogParser from ..parsers.pattern_analyzer import PatternDetector, SequenceAnalyzer from ..exporters.ascii_generator import ASCIIGenerator, GitGraphGenerator from ..exporters.mermaid_generator import MermaidGenerator console = Console() @click.command(name="visualize") @click.argument("source", type=str) @click.option( "--session-id", "-s", type=int, help="Session ID to visualize", ) @click.option( "--style", "visual_style", type=click.Choice(["compact", "detailed", "minimal"]), default="detailed", help="Visualization style", ) @click.option( "--format", "-f", type=click.Choice(["ascii", "mermaid"]), default="ascii", help="Output format", ) @click.option( "--output", "-o", type=click.Path(path_type=Path), help="Output file", ) @click.option( "--analyze/--no-analyze", default=True, help="Include pattern analysis", ) @click.pass_context def visualize_cmd( ctx: click.Context, source: str, session_id: Optional[int], visual_style: str, format: str, output: Optional[Path], analyze: bool, ) -> None: """Visualize a session or git workflow.""" db_path = ctx.obj.get("db", Path.home() / ".termflow" / "sessions.db") if source == "session": _visualize_session( db_path, session_id, visual_style, format, output, analyze, ) elif source == "git": _visualize_git( Path.cwd(), visual_style, format, output, ) else: console.print(f"[red]Unknown source: {source}[/red]") console.print("Use 'session' or 'git' as source") def _visualize_session( db_path: Path, session_id: Optional[int], style: str, format: str, output: Optional[Path], analyze: bool, ) -> None: """Visualize a terminal session.""" db = SessionDatabase(db_path) if session_id is None: sessions = db.get_all_sessions() if not sessions: console.print("[yellow]No sessions found[/yellow]") return session_id = sessions[0]["id"] session = db.get_session(session_id) if not session: console.print(f"[red]Session {session_id} not found[/red]") return commands = db.get_session_commands(session_id) command_list = [cmd.get("command", "") for cmd in commands] if analyze: detector = PatternDetector() patterns = detector.analyze_commands(command_list) if patterns: text = Text() text.append(f"Found {len(patterns)} patterns:\n", style="bold") for i, pattern in enumerate(patterns[:5], 1): text.append(f" {i}. {pattern.commands} (x{pattern.frequency})\n") console.print(Panel(text, title="Pattern Analysis")) metadata = { "title": f"Session: {session.get('name', 'Unknown')}", "command_count": len(command_list), "session_name": session.get("name", ""), } if format == "ascii": ascii_gen = ASCIIGenerator(style=style) result = ascii_gen.generate_from_commands(command_list, metadata) else: mermaid_gen = MermaidGenerator() result = mermaid_gen.generate_flowchart( command_list, title=f"Session: {session.get('name', 'Unknown')}", metadata=metadata, ) if output: with open(output, "w") as f: f.write(result) console.print(f"[cyan]Visualization saved to {output}[/cyan]") else: console.print(Panel(result, title=f"Session Flow: {session.get('name', 'Unknown')}")) def _visualize_git( repo_path: Path, style: str, format: str, output: Optional[Path], ) -> None: """Visualize git workflow.""" parser = GitLogParser(repo_path) if not parser.is_git_repo(): console.print("[red]Not a git repository[/red]") return commits = parser.parse_log(max_count=50) parser.get_commit_parents() workflow = parser.analyze_workflow() if format == "ascii": graph_gen = GitGraphGenerator() result = graph_gen.generate_from_parser(parser) else: mermaid_gen = MermaidGenerator() result = mermaid_gen.generate_git_graph_from_parser(parser) stats_text = Text() stats_text.append(f"Commits: {len(commits)}\n", style="bold") stats_text.append(f"Merges: {workflow.merge_count}\n") stats_text.append(f"Features: {workflow.feature_count}\n") stats_text.append(f"Branches: {len(workflow.branches)}") if output: with open(output, "w") as f: f.write(result) console.print(f"[cyan]Visualization saved to {output}[/cyan]") else: console.print(Panel(result, title="Git Workflow")) console.print(Panel(stats_text, title="Statistics"))