From 4e1d78c14c9e57cdb4b9dfd7e9c8269980e2499a Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 10:29:59 +0000 Subject: [PATCH] Initial upload of ai-code-audit-cli project --- src/cli/output.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/cli/output.py diff --git a/src/cli/output.py b/src/cli/output.py new file mode 100644 index 0000000..c81619e --- /dev/null +++ b/src/cli/output.py @@ -0,0 +1,123 @@ +"""Output formatting for CLI results.""" + +from typing import Optional + +from rich.console import Console +from rich.panel import Panel +from rich.table import Table +from rich.text import Text +from rich.style import Style +from rich.color import Color +from rich.table import Column + +from .options import OutputFormat, ScanOptions, SeverityLevel +from ..core.scanner import ScanResult, Issue, IssueCategory + + +class OutputFormatter: + """Format and display scan results in terminal.""" + + def __init__(self, options: ScanOptions): + self.options = options + self.console = Console(no_color=options.no_color) + + def display_results( + self, results: ScanResult, confidence_scorer: "ConfidenceScorer" + ) -> None: + """Display scan results to the console.""" + score = confidence_scorer.calculate(results) + score_color = self._get_score_color(score) + + self.console.print(Panel.fit( + f"[bold]AI Code Audit Results[/bold]\n\n" + f"Scanned: {results.files_scanned} files\n" + f"Issues Found: {len(results.issues)}\n" + f"[{score_color}]Confidence Score: {score}/100[/{score_color}]", + title="Audit Summary", + border_style="blue", + )) + + if self.options.verbose: + self._display_detailed_breakdown(results) + + if results.issues: + self._display_issues(results.issues) + + if results.warnings: + self._display_warnings(results.warnings) + + def _get_score_color(self, score: int) -> str: + """Get color style for score.""" + if score >= 90: + return "green" + elif score >= 70: + return "yellow" + elif score >= 50: + return "orange1" + return "red" + + def _display_detailed_breakdown(self, results: ScanResult) -> None: + """Display detailed breakdown of scan results.""" + table = Table(title="Detailed Breakdown", show_header=True) + table.add_column("Category", style="cyan") + table.add_column("Count", justify="right", style="magenta") + + category_counts: dict[IssueCategory, int] = {} + for issue in results.issues: + category_counts[issue.category] = category_counts.get(issue.category, 0) + 1 + + for category, count in sorted(category_counts.items(), key=lambda x: -x[1]): + table.add_row(category.value, str(count)) + + severity_counts: dict[SeverityLevel, int] = {} + for issue in results.issues: + severity_counts[issue.severity] = severity_counts.get(issue.severity, 0) + 1 + + for severity in SeverityLevel: + count = severity_counts.get(severity, 0) + if count > 0: + table.add_row(f"{severity.value.capitalize()} Severity", str(count)) + + self.console.print(table) + + def _display_issues(self, issues: list[Issue]) -> None: + """Display issues in a formatted table.""" + table = Table( + title="Issues Found", + show_header=True, + header_style="bold magenta", + ) + table.add_column("Severity", width=10) + table.add_column("Category", width=15) + table.add_column("File", width=30) + table.add_column("Line", justify="right", width=6) + table.add_column("Message", width=50) + + for issue in issues: + severity_style = self._get_severity_style(issue.severity) + table.add_row( + f"[{severity_style}]{issue.severity.value.capitalize()}[/{severity_style}]", + issue.category.value, + issue.file_path[:28] + ".." if len(issue.file_path) > 30 else issue.file_path, + str(issue.line_number), + issue.message[:48] + ".." if len(issue.message) > 50 else issue.message, + ) + + self.console.print(table) + + def _get_severity_style(self, severity: SeverityLevel) -> str: + """Get Rich style for severity level.""" + styles = { + SeverityLevel.CRITICAL: "red bold", + SeverityLevel.HIGH: "orange1", + SeverityLevel.MEDIUM: "yellow", + SeverityLevel.LOW: "blue", + } + return styles.get(severity, "white") + + def _display_warnings(self, warnings: list[str]) -> None: + """Display warnings.""" + if warnings: + self.console.print("\n[yellow]Warnings:[/yellow]") + for warning in warnings: + self.console.print(f" - {warning}")