Files
2026-02-01 08:51:31 +00:00

160 lines
5.6 KiB
Python

"""Interactive UI for reviewing alias suggestions using Rich."""
from typing import List, Set
from rich.console import Console
from rich.table import Table
from rich.prompt import Prompt
from rich.text import Text
from rich.style import Style
from rich import box
from .command_analyzer import AliasSuggestion
class InteractiveUI:
"""Interactive UI for reviewing and selecting alias suggestions."""
def __init__(self):
self.console = Console()
self.selected_aliases: Set[str] = set()
def display_suggestions(
self,
suggestions: List[AliasSuggestion],
title: str = "Alias Suggestions"
) -> None:
"""Display alias suggestions in a formatted table."""
if not suggestions:
self.console.print("[yellow]No alias suggestions found.[/yellow]")
return
table = Table(
title=title,
box=box.ROUNDED,
show_header=True,
header_style="bold magenta"
)
table.add_column("#", style="dim", width=4)
table.add_column("Alias", style="bold green", width=15)
table.add_column("Command", style="cyan", max_width=50)
table.add_column("Freq", justify="right", width=5)
table.add_column("Score", justify="right", width=6)
for i, suggestion in enumerate(suggestions, start=1):
command_preview = suggestion.original_command[:47] + "..." \
if len(suggestion.original_command) > 50 \
else suggestion.original_command
style = Style() if i % 2 == 0 else None
table.add_row(
str(i),
f"={suggestion.alias_name}",
command_preview,
str(suggestion.frequency),
f"{suggestion.score:.2f}",
style=style
)
self.console.print(table)
def run_review_session(
self,
suggestions: List[AliasSuggestion]
) -> List[AliasSuggestion]:
"""Run interactive review session for alias suggestions."""
selected = []
index = 0
while index < len(suggestions):
suggestion = suggestions[index]
self.console.clear()
self._display_single_suggestion(suggestion, index + 1, len(suggestions))
choice = Prompt.ask(
"\n[bold](a)ccept[/] | (r)eject | (n)ext | (p)revious | (q)uit | (s)elect all remaining | (A)ccept all",
choices=["a", "r", "n", "p", "q", "s", "A"],
default="n"
)
if choice == "a":
if suggestion.alias_name not in self.selected_aliases:
self.selected_aliases.add(suggestion.alias_name)
selected.append(suggestion)
index += 1
elif choice == "r":
index += 1
elif choice == "n":
index += 1
elif choice == "p":
index = max(0, index - 1)
elif choice == "q":
break
elif choice == "s":
for remaining in suggestions[index:]:
if remaining.alias_name not in self.selected_aliases:
self.selected_aliases.add(remaining.alias_name)
selected.append(remaining)
break
elif choice == "A":
for s in suggestions:
if s.alias_name not in self.selected_aliases:
self.selected_aliases.add(s.alias_name)
selected.append(s)
break
return selected
def _display_single_suggestion(
self,
suggestion: AliasSuggestion,
current: int,
total: int
) -> None:
"""Display a single suggestion with full command."""
self.console.print(f"\n[bold]Suggestion {current}/{total}[/]\n")
table = Table(box=box.SIMPLE)
table.add_column("Property", style="dim")
table.add_column("Value")
table.add_row("Alias Name", f"[bold green]={suggestion.alias_name}[/]")
table.add_row("Frequency", str(suggestion.frequency))
table.add_row("Score", f"{suggestion.score:.2f}")
table.add_row(
"Command",
f"[cyan]{suggestion.original_command}[/]"
)
self.console.print(table)
def display_summary(self, selected: List[AliasSuggestion]) -> None:
"""Display summary of selected aliases."""
if not selected:
self.console.print("[yellow]No aliases were selected.[/yellow]")
return
self.console.print(f"\n[bold green]Selected {len(selected)} aliases:[/]\n")
for i, suggestion in enumerate(selected, start=1):
self.console.print(f" {i}. ={suggestion.alias_name} => {suggestion.original_command}")
def confirm_selection(self) -> bool:
"""Ask user to confirm their selection."""
return Prompt.ask(
"\n[bold]Proceed with these aliases?[/]",
choices=["y", "n"],
default="y"
) == "y"
def show_progress(self, current: int, total: int, message: str = "") -> None:
"""Show progress indicator."""
percent = (current / total * 100) if total > 0 else 100
self.console.print(
f"\r[dim]{message} {percent:.0f}%[/]",
end="",
justify="left"
)
if current == total:
self.console.print()