From c5007a7bb8faae3caeff6ca40fd99b70d20bfb71 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sat, 31 Jan 2026 13:13:10 +0000 Subject: [PATCH] Initial upload with CI/CD workflow --- shellhist/cli/export.py | 151 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 shellhist/cli/export.py diff --git a/shellhist/cli/export.py b/shellhist/cli/export.py new file mode 100644 index 0000000..c552785 --- /dev/null +++ b/shellhist/cli/export.py @@ -0,0 +1,151 @@ +"""Export command for generating scripts from detected patterns.""" + +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_script, generate_script_name +from shellhist.core.patterns import detect_common_sequences + + +@click.command("export-script") +@click.option( + "--history", + "-H", + type=str, + help="Path to history file", +) +@click.option( + "--output", + "-o", + type=str, + default=".", + help="Output directory for generated scripts (default: current directory)", +) +@click.option( + "--name", + "-n", + type=str, + help="Custom name for the script file", +) +@click.option( + "--dry-run", + "-d", + is_flag=True, + default=False, + help="Preview script without writing to disk", +) +@click.option( + "--force", + "-f", + is_flag=True, + default=False, + help="Overwrite existing scripts", +) +@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 export_script_command( + ctx: click.Context, + history: Optional[str], + output: str, + name: Optional[str], + dry_run: bool, + force: bool, + shell: Optional[str], + min_occurrences: int, +) -> None: + """Export detected command patterns to executable shell scripts. + + Examples: + + \b + shellhist export-script --output ./scripts/ + shellhist export-script --output ./scripts/ --name myroutine + shellhist export-script --dry-run --min-occurrences 5 + """ + 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=5, + 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 + + console.print(f"[bold cyan]Detected Patterns for Script Export[/bold cyan]\n") + + scripts_generated = 0 + + for i, pattern in enumerate(sequences[:5], 1): + script_name = name or generate_script_name(pattern) + + console.print(f"{i}. Pattern: {' -> '.join(pattern.commands)}") + console.print(f" Script name: {script_name}") + + try: + script_path, content = generate_script( + pattern=pattern, + script_name=script_name, + output_dir=output, + dry_run=dry_run, + force=force, + ) + + if dry_run: + console.print(f" [yellow](dry-run) Would create: {script_path}[/yellow]") + console.print(f" Content preview:") + for line in content.split("\n")[:5]: + console.print(f" {line}") + console.print() + else: + console.print(f" [green]Created: {script_path}[/green]\n") + scripts_generated += 1 + + except FileExistsError: + console.print(f" [yellow]Skipped: {script_name}.sh (already exists, use --force to overwrite)[/yellow]\n") + except Exception as e: + console.print(f" [red]Error: {e}[/red]\n") + + if not dry_run and scripts_generated > 0: + console.print( + f"[green]Successfully generated {scripts_generated} script(s) in {output}[/green]" + ) + elif dry_run: + console.print("[yellow]Scripts not created (dry-run mode)[/yellow]") + + except FileNotFoundError as e: + console.print(f"[red]Error: {e}[/red]") + ctx.exit(1) + except Exception as e: + console.print(f"[red]Error exporting scripts: {e}[/red]") + ctx.exit(1)