Initial upload: shell-history-semantic-search v0.1.0
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
109
src/shell_history_search/cli/commands.py
Normal file
109
src/shell_history_search/cli/commands.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import click
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from ..core import SearchEngine, IndexingService
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
@click.option("-v", "--verbose", count=True, help="Increase verbosity")
|
||||||
|
def cli(verbose: int) -> None:
|
||||||
|
log_level = logging.WARNING
|
||||||
|
if verbose == 1:
|
||||||
|
log_level = logging.INFO
|
||||||
|
elif verbose >= 2:
|
||||||
|
log_level = logging.DEBUG
|
||||||
|
logging.basicConfig(level=log_level, format="%(levelname)s: %(message)s")
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option("--shell", type=str, help="Index only specific shell (bash, zsh, fish)")
|
||||||
|
def index(shell: str | None) -> None:
|
||||||
|
click.echo("Indexing shell history...")
|
||||||
|
|
||||||
|
indexing_service = IndexingService()
|
||||||
|
|
||||||
|
shell_type = shell.lower() if shell else None
|
||||||
|
result = indexing_service.index_shell_history(shell_type)
|
||||||
|
|
||||||
|
click.echo(
|
||||||
|
f"Indexed {result['total_indexed']} commands "
|
||||||
|
f"(skipped {result['total_skipped']} duplicates)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument("query")
|
||||||
|
@click.option("--limit", "-n", type=int, default=10, help="Number of results to return")
|
||||||
|
@click.option("--shell", type=str, help="Filter by shell type (bash, zsh, fish)")
|
||||||
|
@click.option("--json", "json_output", is_flag=True, help="Output as JSON")
|
||||||
|
def search(query: str, limit: int, shell: str | None, json_output: bool) -> None:
|
||||||
|
search_engine = SearchEngine()
|
||||||
|
|
||||||
|
shell_type = shell.lower() if shell else None
|
||||||
|
|
||||||
|
results = search_engine.search(query, limit=limit, shell_type=shell_type)
|
||||||
|
|
||||||
|
if not results:
|
||||||
|
click.echo("No results found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if json_output:
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"command": r.command,
|
||||||
|
"shell": r.shell_type,
|
||||||
|
"timestamp": r.timestamp,
|
||||||
|
"similarity": round(r.similarity, 4),
|
||||||
|
}
|
||||||
|
for r in results
|
||||||
|
]
|
||||||
|
click.echo(json.dumps(output, indent=2))
|
||||||
|
else:
|
||||||
|
for i, result in enumerate(results, 1):
|
||||||
|
timestamp_str = ""
|
||||||
|
if result.timestamp:
|
||||||
|
dt = datetime.fromtimestamp(result.timestamp)
|
||||||
|
timestamp_str = dt.strftime("%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
|
similarity_pct = result.similarity * 100
|
||||||
|
click.echo(f"{i}. [{result.shell_type}] {timestamp_str}")
|
||||||
|
click.echo(f" {result.command}")
|
||||||
|
click.echo(f" Similarity: {similarity_pct:.1f}%")
|
||||||
|
click.echo()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option("--json", "json_output", is_flag=True, help="Output as JSON")
|
||||||
|
def stats(json_output: bool) -> None:
|
||||||
|
search_engine = SearchEngine()
|
||||||
|
stats_data = search_engine.get_stats()
|
||||||
|
|
||||||
|
if json_output:
|
||||||
|
click.echo(json.dumps(stats_data, indent=2))
|
||||||
|
else:
|
||||||
|
click.echo("Shell History Search Statistics")
|
||||||
|
click.echo("=" * 40)
|
||||||
|
click.echo(f"Total commands: {stats_data['total_commands']}")
|
||||||
|
click.echo(f"Total embeddings: {stats_data['total_embeddings']}")
|
||||||
|
click.echo(f"Embedding model: {stats_data['embedding_model']}")
|
||||||
|
click.echo(f"Embedding dimension: {stats_data['embedding_dim']}")
|
||||||
|
click.echo()
|
||||||
|
click.echo("Commands by shell:")
|
||||||
|
for shell_type, count in stats_data["shell_counts"].items():
|
||||||
|
click.echo(f" {shell_type}: {count}")
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.confirmation_option(prompt="Are you sure you want to clear all indexed data?")
|
||||||
|
def clear() -> None:
|
||||||
|
search_engine = SearchEngine()
|
||||||
|
search_engine.clear_all()
|
||||||
|
click.echo("All indexed data has been cleared.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli()
|
||||||
Reference in New Issue
Block a user