Files
shell-speak/shell_speak/output.py
Auto User 95459fb4c8 fix: resolve CI test failure in output.py
- Fixed undefined 'tool' variable in display_history function
- Changed '[tool]' markup tag usage to proper Rich syntax
- All tests now pass (38/38 unit tests)
- Type checking passes with mypy --strict
2026-01-31 06:22:27 +00:00

120 lines
3.6 KiB
Python

"""Output formatting with Rich."""
from rich.console import Console
from rich.panel import Panel
from rich.syntax import Syntax
from rich.text import Text
from rich.theme import Theme
from shell_speak.models import CommandMatch, HistoryEntry
from shell_speak.nlp import tokenize
custom_theme = Theme({
"command": "bold cyan",
"keyword": "bold green",
"tool": "bold magenta",
"explanation": "italic",
"error": "bold red",
"warning": "yellow",
"success": "bold green",
"info": "blue",
})
console = Console(theme=custom_theme)
def display_command(match: CommandMatch, explain: bool = False) -> None:
"""Display a command match with rich formatting."""
syntax = Syntax(match.command, "bash", theme="monokai", line_numbers=False)
title = f"[tool]{match.pattern.tool}[/tool] command"
panel = Panel(
syntax,
title=title,
expand=False,
border_style="cyan",
)
console.print(panel)
if explain or match.confidence < 0.8:
confidence_pct = int(match.confidence * 100)
confidence_color = "success" if match.confidence >= 0.8 else "warning" if match.confidence >= 0.5 else "error"
console.print(f"Confidence: [{confidence_color}]{confidence_pct}%[/]")
if match.explanation:
console.print(f"\n[explanation]{match.explanation}[/]")
if explain:
_show_detailed_explanation(match)
def _show_detailed_explanation(match: CommandMatch) -> None:
"""Show detailed breakdown of a command."""
console.print("\n[info]Command breakdown:[/]")
tokens = tokenize(match.command)
for token in tokens:
if token in ("docker", "kubectl", "git", "ls", "cd", "cat", "grep", "find", "rm", "cp", "mv"):
console.print(f" [keyword]{token}[/]", end=" ")
else:
console.print(f" {token}", end=" ")
def display_error(message: str) -> None:
"""Display an error message."""
console.print(f"[error]Error:[/] {message}")
def display_warning(message: str) -> None:
"""Display a warning message."""
console.print(f"[warning]Warning:[/] {message}")
def display_info(message: str) -> None:
"""Display an info message."""
console.print(f"[info]{message}[/]")
def display_history(entries: list[HistoryEntry], limit: int = 20) -> None:
"""Display command history."""
console.print(f"\n[info]Command History (last {limit}):[/]\n")
for i, entry in enumerate(entries[-limit:], 1):
timestamp = entry.timestamp.strftime("%Y-%m-%d %H:%M")
console.print(f"{i}. [tool]{entry.tool}[/tool] | {timestamp}")
console.print(f" Query: {entry.query}")
console.print(f" [command]{entry.command}[/]")
console.print()
def display_suggestions(suggestions: list[str]) -> None:
"""Display command suggestions."""
if not suggestions:
return
console.print("\n[info]Did you mean?[/]")
for i, suggestion in enumerate(suggestions[:5], 1):
console.print(f" {i}. {suggestion}")
def display_learn_success(query: str, command: str) -> None:
"""Display confirmation of learning."""
console.print("[success]Learned new command:[/]")
console.print(f" Query: {query}")
console.print(f" [command]{command}[/]")
def display_forget_success(query: str) -> None:
"""Display confirmation of forgetting a pattern."""
console.print(f"[success]Forgot pattern for:[/] {query}")
def display_help_header() -> None:
"""Display the help header."""
console.print(Panel(
Text("Shell Speak - Natural Language to Shell Commands", justify="center", style="bold cyan"),
subtitle="Type a description of what you want to do",
expand=False,
))