Files
shell-history-automation-tool/shellhist/cli/search.py
7000pctAUTO 32f78c6985
Some checks failed
CI / test (push) Has been cancelled
Shellhist CI / test (push) Has been cancelled
Shellhist CI / build (push) Has been cancelled
fix: resolve CI type checking issues
- Add return type annotations to __hash__ (-> int) and __eq__ (-> bool) in HistoryEntry
- Add TextIO import and type annotations for file parameters
- Add type ignore comment for fuzzywuzzy import
- Add HistoryEntry import and list type annotations in time_analysis
- Add assert statements for Optional[datetime] timestamps
- Add TypedDict classes for type-safe pattern dictionaries
- Add CommandPattern import and list[CommandPattern] type annotation
- Add -> None return types to all test methods
- Remove unused HistoryEntry import (F401)
2026-01-31 14:19:17 +00:00

116 lines
2.8 KiB
Python

"""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)