Add shellgen UI and safety modules

This commit is contained in:
2026-01-29 12:43:40 +00:00
parent 2fc806954c
commit 5cf896a70e

163
app/shellgen/ui/console.py Normal file
View File

@@ -0,0 +1,163 @@
"""Console UI using Rich library."""
import subprocess
import sys
from typing import List, Optional
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich.syntax import Syntax
from rich.prompt import Prompt, Confirm
from rich.table import Table
from rich import box
class ConsoleUI:
"""Rich-based console interface for ShellGen."""
def __init__(self):
"""Initialize console with Rich."""
self.console = Console()
def print_header(self) -> None:
"""Print the application header."""
header = Text()
header.append("ShellGen", style="bold magenta")
header.append(" - ", style="dim")
header.append("Natural Language to Shell Command", style="italic")
self.console.print(Panel(header, expand=False))
def display_generated_command(
self, command: str, explanation: str, language: str = "bash"
) -> None:
"""Display the generated command with explanation.
Args:
command: The generated shell command.
explanation: Brief explanation of the command.
language: Syntax highlighting language.
"""
self.console.print("\n[bold green]Generated Command:[/bold green]")
syntax = Syntax(command, language, theme="monokai", line_numbers=False)
self.console.print(Panel(syntax, expand=False, border_style="green"))
self.console.print(f"\n[bold]Explanation:[/bold] {explanation}\n")
def display_history(self, entries: List[dict]) -> None:
"""Display command history.
Args:
entries: List of history entry dictionaries.
"""
if not entries:
self.console.print("[yellow]No command history found.[/yellow]")
return
table = Table(
title="Command History",
show_header=True,
header_style="bold magenta",
box=box.ROUNDED,
)
table.add_column("ID", width=5, justify="right")
table.add_column("Prompt", width=40)
table.add_column("Command", width=40)
table.add_column("Shell", width=10)
table.add_column("Executed", width=10)
for entry in entries:
executed = "" if entry.get("executed") else ""
style = "green" if entry.get("executed") else "red"
table.add_row(
str(entry.get("id", 0)),
entry.get("prompt", "")[:37] + "..." if len(entry.get("prompt", "")) > 40 else entry.get("prompt", ""),
entry.get("command", "")[:37] + "..." if len(entry.get("command", "")) > 40 else entry.get("command", ""),
entry.get("shell", ""),
f"[{style}]{executed}[/{style}]",
)
self.console.print(table)
def confirm_execution(self) -> bool:
"""Prompt user for execution confirmation.
Returns:
True if user confirmed, False otherwise.
"""
return Confirm.ask("Execute this command?")
def print_safety_warning(self, warning: str) -> None:
"""Print a safety warning.
Args:
warning: The warning message.
"""
self.console.print(
Panel(
Text(warning, style="bold red"),
title="⚠️ Safety Warning",
border_style="red",
)
)
def print_cancelled(self) -> None:
"""Print cancelled message."""
self.console.print("[yellow]Command execution cancelled.[/yellow]")
def print_error(self, message: str) -> None:
"""Print an error message.
Args:
message: Error message to display.
"""
self.console.print(
Panel(
Text(message, style="bold red"),
title="Error",
border_style="red",
)
)
def execute_command(self, command: str) -> None:
"""Execute a command and show output.
Args:
command: Command to execute.
"""
self.console.print(
f"\n[bold]Executing:[/bold] [cyan]{command}[/cyan]\n"
)
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=30,
)
if result.stdout:
self.console.print(result.stdout)
if result.stderr:
self.console.print(f"[red]{result.stderr}[/red]", highlight=False)
self.console.print(
f"\n[dim]Exit code: {result.returncode}[/dim]\n"
)
except subprocess.TimeoutExpired:
self.console.print("[yellow]Command timed out after 30 seconds[/yellow]")
except Exception as e:
self.console.print(f"[red]Execution error: {e}[/red]")
def print_feedback_submitted(self) -> None:
"""Print feedback submission confirmation."""
self.console.print(
"[green]✓[/green] Feedback submitted successfully"
)