From a14aba3854450637794ffa4a25573c8a73883896 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sat, 31 Jan 2026 13:13:08 +0000 Subject: [PATCH] Initial upload with CI/CD workflow --- shellhist/cli/alias.py | 153 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 shellhist/cli/alias.py diff --git a/shellhist/cli/alias.py b/shellhist/cli/alias.py new file mode 100644 index 0000000..58f7006 --- /dev/null +++ b/shellhist/cli/alias.py @@ -0,0 +1,153 @@ +"""Alias suggestion command.""" + +import os +from pathlib import Path +from typing import Optional + +import click +from rich.console import Console + +from shellhist.core import HistoryLoader +from shellhist.core.export import generate_alias, generate_alias_name +from shellhist.core.patterns import detect_common_sequences + + +@click.command("suggest-aliases") +@click.option( + "--history", + "-H", + type=str, + help="Path to history file", +) +@click.option( + "--auto-create", + "-a", + is_flag=True, + default=False, + help="Automatically create aliases without prompting", +) +@click.option( + "--dry-run", + "-n", + is_flag=True, + default=False, + help="Preview aliases without creating them", +) +@click.option( + "--shell-file", + "-f", + type=str, + help="Shell config file to append to (default: ~/.bashrc or ~/.zshrc)", +) +@click.option( + "--shell", + "-s", + type=click.Choice(["bash", "zsh"]), + help="Shell type for parsing", +) +@click.option( + "--min-occurrences", + "-m", + type=int, + default=3, + help="Minimum occurrences for pattern (default: 3)", +) +@click.pass_context +def suggest_aliases_command( + ctx: click.Context, + history: Optional[str], + auto_create: bool, + dry_run: bool, + shell_file: Optional[str], + shell: Optional[str], + min_occurrences: int, +) -> None: + """Suggest shell aliases for detected command patterns. + + Examples: + + \b + shellhist suggest-aliases + shellhist suggest-aliases --auto-create + shellhist suggest-aliases --dry-run --shell-file ~/.bashrc + """ + 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 + + sequences = detect_common_sequences( + store, + max_length=4, + min_occurrences=min_occurrences, + ) + + if not sequences: + console.print( + f"[yellow]No significant patterns found with minimum {min_occurrences} occurrences.[/yellow]" + ) + console.print("Try lowering --min-occurrences or run more commands.") + return + + shell_type = shell or ("zsh" if "zsh" in os.environ.get("SHELL", "") else "bash") + + if shell_file is None: + home = os.path.expanduser("~") + shell_file = f"{home}/.bashrc" if shell_type == "bash" else f"{home}/.zshrc" + + console.print(f"[bold cyan]Detected Patterns for Alias Suggestions[/bold cyan]\n") + + aliases_to_create = [] + + for i, pattern in enumerate(sequences[:10], 1): + alias_name = generate_alias_name(pattern) + alias_line = generate_alias(pattern, alias_name) + + console.print(f"{i}. [cyan]{alias_name}[/cyan]") + console.print(f" Command: {' -> '.join(pattern.commands)}") + console.print(f" Alias: {alias_line}") + console.print(f" Frequency: {pattern.frequency} times\n") + + if dry_run: + continue + + if auto_create: + aliases_to_create.append(alias_line) + else: + if click.confirm(f"Create alias '{alias_name}'?", default=True): + aliases_to_create.append(alias_line) + + if not aliases_to_create: + console.print("\n[yellow]No aliases selected for creation.[/yellow]") + return + + if dry_run: + console.print("\n[bold]Aliases to create (dry-run):[/bold]") + for alias in aliases_to_create: + console.print(f" {alias}") + return + + shell_path = Path(shell_file) + shell_path.parent.mkdir(parents=True, exist_ok=True) + + with open(shell_file, "a", encoding="utf-8") as f: + f.write("\n# Shell History Automation Tool - Generated Aliases\n") + for alias in aliases_to_create: + f.write(f"{alias}\n") + + console.print( + f"\n[green]Successfully added {len(aliases_to_create)} aliases to {shell_file}[/green]" + ) + console.print("Run 'source " + shell_file + "' or restart your shell to use them.") + + except FileNotFoundError as e: + console.print(f"[red]Error: {e}[/red]") + ctx.exit(1) + except Exception as e: + console.print(f"[red]Error suggesting aliases: {e}[/red]") + ctx.exit(1)