123 lines
3.7 KiB
Python
123 lines
3.7 KiB
Python
"""Output formatting with Rich."""
|
|
|
|
from typing import Optional
|
|
|
|
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(f"[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,
|
|
))
|