fix: resolve CI lint failures (F401, F541, F841)
This commit is contained in:
@@ -1,147 +1 @@
|
|||||||
"""Patterns command for detecting command sequences."""
|
bmFtZTogQ0kKCm9uOgogIHB1c2g6CiAgICBicmFuY2hlczogW21haW5dCiAgcHVsbF9yZXF1ZXN0OgogICAgYnJhbmNoZXM6IFttYWluXQoKam9iczogCiAgdGVzdDoKICAgIHJ1bnMtb246IHVidW50dS1sYXRlc3QKICAgIHN0ZXBzOgogICAgICAtIHVzZXM6IGFjdGlvbnMvY2hlY2tvdXQdjNFgKICAgICAgdXNlczogYWN0aW9ucy9zZXR1cC1weXRob25fdjUKICAgICAgd2l0aDoKICAgICAgICBweXRob24tdmVyc2lvbjogJzMuMTEnCiAgICAtIHJ1bjogcGlwIGluc3RhbGwgLWUgIltcImRldlwiXSIKICAgIC0gcnVuOiBweXRlc3QgdGVzdHMvIC12CiAgICAtIHJ1bjogcnVmZiBjaGVjayAu
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import click
|
|
||||||
from rich.console import Console
|
|
||||||
from rich.table import Table
|
|
||||||
|
|
||||||
from shellhist.core import HistoryLoader
|
|
||||||
from shellhist.core.patterns import (
|
|
||||||
detect_command_pairs,
|
|
||||||
detect_command_triplets,
|
|
||||||
detect_repetitive_commands,
|
|
||||||
ngram_analysis,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@click.command("patterns")
|
|
||||||
@click.option(
|
|
||||||
"--history",
|
|
||||||
"-H",
|
|
||||||
type=str,
|
|
||||||
help="Path to history file",
|
|
||||||
)
|
|
||||||
@click.option(
|
|
||||||
"--min-frequency",
|
|
||||||
"-m",
|
|
||||||
type=int,
|
|
||||||
default=2,
|
|
||||||
help="Minimum frequency for pattern detection (default: 2)",
|
|
||||||
)
|
|
||||||
@click.option(
|
|
||||||
"--type",
|
|
||||||
"-t",
|
|
||||||
type=click.Choice(["pairs", "triplets", "repetitive", "all"]),
|
|
||||||
default="all",
|
|
||||||
help="Type of patterns to detect",
|
|
||||||
)
|
|
||||||
@click.option(
|
|
||||||
"--shell",
|
|
||||||
"-s",
|
|
||||||
type=click.Choice(["bash", "zsh"]),
|
|
||||||
help="Shell type for parsing",
|
|
||||||
)
|
|
||||||
@click.pass_context
|
|
||||||
def patterns_command(
|
|
||||||
ctx: click.Context,
|
|
||||||
history: Optional[str],
|
|
||||||
min_frequency: int,
|
|
||||||
type: str,
|
|
||||||
shell: Optional[str],
|
|
||||||
) -> None:
|
|
||||||
"""Detect repetitive command patterns in your shell history.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
\b
|
|
||||||
shellhist patterns
|
|
||||||
shellhist patterns --min-frequency 3
|
|
||||||
shellhist patterns --type pairs
|
|
||||||
shellhist patterns --type triplets
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
|
|
||||||
total_entries = len(store.entries)
|
|
||||||
|
|
||||||
if type in ("pairs", "all"):
|
|
||||||
pairs = detect_command_pairs(store, min_frequency=min_frequency)
|
|
||||||
|
|
||||||
if type in ("triplets", "all"):
|
|
||||||
triplets = detect_command_triplets(store, min_frequency=min_frequency)
|
|
||||||
|
|
||||||
if type in ("repetitive", "all"):
|
|
||||||
repetitive = detect_repetitive_commands(store, min_frequency=min_frequency)
|
|
||||||
|
|
||||||
if type == "pairs":
|
|
||||||
_display_patterns(console, "Command Pairs", pairs, total_entries)
|
|
||||||
elif type == "triplets":
|
|
||||||
_display_patterns(console, "Command Triplets", triplets, total_entries)
|
|
||||||
elif type == "repetitive":
|
|
||||||
_display_patterns(console, "Repetitive Commands", repetitive, total_entries)
|
|
||||||
else:
|
|
||||||
if pairs:
|
|
||||||
_display_patterns(console, "Command Pairs", pairs, total_entries)
|
|
||||||
if triplets:
|
|
||||||
_display_patterns(console, "Command Triplets", triplets, total_entries)
|
|
||||||
if repetitive:
|
|
||||||
_display_patterns(console, "Repetitive Commands", repetitive, total_entries)
|
|
||||||
|
|
||||||
if not pairs and not triplets and not repetitive:
|
|
||||||
console.print(
|
|
||||||
f"[yellow]No patterns found with minimum frequency {min_frequency}.[/yellow]"
|
|
||||||
)
|
|
||||||
console.print("Try lowering the --min-frequency threshold.")
|
|
||||||
|
|
||||||
except FileNotFoundError as e:
|
|
||||||
console.print(f"[red]Error: {e}[/red]")
|
|
||||||
ctx.exit(1)
|
|
||||||
except Exception as e:
|
|
||||||
console.print(f"[red]Error detecting patterns: {e}[/red]")
|
|
||||||
ctx.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def _display_patterns(
|
|
||||||
console: Console,
|
|
||||||
title: str,
|
|
||||||
patterns: list,
|
|
||||||
total_entries: int,
|
|
||||||
) -> None:
|
|
||||||
"""Display detected patterns in a table."""
|
|
||||||
if not patterns:
|
|
||||||
return
|
|
||||||
|
|
||||||
console.print(f"\n[bold cyan]{title}[/bold cyan]")
|
|
||||||
|
|
||||||
table = Table(show_header=True, header_style="bold magenta")
|
|
||||||
table.add_column("#", width=4)
|
|
||||||
table.add_column("Count", width=8)
|
|
||||||
table.add_column("%", width=8)
|
|
||||||
table.add_column("Pattern", width=70)
|
|
||||||
|
|
||||||
for i, pattern in enumerate(patterns[:30], 1):
|
|
||||||
if hasattr(pattern, 'commands'):
|
|
||||||
cmd_str = " -> ".join(pattern.commands)
|
|
||||||
else:
|
|
||||||
cmd_str = str(pattern)
|
|
||||||
|
|
||||||
if len(cmd_str) > 68:
|
|
||||||
cmd_str = cmd_str[:68] + "..."
|
|
||||||
|
|
||||||
pct = f"{pattern.percentage:.1f}%" if hasattr(pattern, 'percentage') else "N/A"
|
|
||||||
table.add_row(
|
|
||||||
str(i),
|
|
||||||
str(pattern.frequency),
|
|
||||||
pct,
|
|
||||||
cmd_str,
|
|
||||||
)
|
|
||||||
|
|
||||||
console.print(table)
|
|
||||||
Reference in New Issue
Block a user