"""Search command for fuzzy searching shell history.""" from typing import Optional import click from rich.console import Console from rich.table import Table from shellhist.core import HistoryLoader from shellhist.core.search import fuzzy_search @click.command("search") @click.argument("query", type=str) @click.option( "--history", "-H", type=str, help="Path to history file", ) @click.option( "--threshold", "-t", type=int, default=70, help="Minimum similarity threshold (0-100, default: 70)", ) @click.option( "--limit", "-l", type=int, default=20, help="Maximum number of results (default: 20)", ) @click.option( "--reverse/--no-reverse", default=False, help="Reverse sort order (newest first)", ) @click.option( "--recent", "-r", is_flag=True, default=False, help="Boost scores for recent commands (within 24h)", ) @click.option( "--shell", "-s", type=click.Choice(["bash", "zsh"]), help="Shell type for parsing", ) @click.pass_context def search_command( ctx: click.Context, query: str, history: Optional[str], threshold: int, limit: int, reverse: bool, recent: bool, shell: Optional[str], ) -> None: """Search shell history with fuzzy matching. Examples: \b shellhist search "git commit" shellhist search "npm run" --threshold 80 --limit 10 shellhist search "docker ps" --recent """ console = Console() try: loader = HistoryLoader(history_path=history) store = loader.load() if not store.entries: console.print("[yellow]No entries found in history.[/yellow]") return results = fuzzy_search( store, query, threshold=threshold, limit=limit, reverse=reverse, recent=recent, ) if not results: console.print(f"[yellow]No matches found for '{query}'.[/yellow]") return console.print(f"\n[bold cyan]Search Results for '{query}'[/bold cyan]") table = Table(show_header=True, header_style="bold magenta") table.add_column("#", width=4) table.add_column("Match", width=6) table.add_column("Command", width=70) for i, (entry, score) in enumerate(results, 1): score_str = f"{score}%".rjust(4) cmd = entry.command[:68] if len(entry.command) > 68 else entry.command table.add_row(str(i), score_str, cmd) console.print(table) except FileNotFoundError as e: console.print(f"[red]Error: {e}[/red]") ctx.exit(1) except Exception as e: console.print(f"[red]Error searching history: {e}[/red]") ctx.exit(1)