Add CLI modules: main, detect, manifest
This commit is contained in:
180
confsync/cli/detect.py
Normal file
180
confsync/cli/detect.py
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
"""Detect command for configuration file detection."""
|
||||||
|
|
||||||
|
from typing import Dict, Optional, List
|
||||||
|
import typer
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.panel import Panel
|
||||||
|
|
||||||
|
from confsync.detectors.base import DetectorRegistry
|
||||||
|
from confsync.models.config_models import ConfigCategory, ConfigFile
|
||||||
|
|
||||||
|
detect_cmd = typer.Typer(
|
||||||
|
name="detect",
|
||||||
|
help="Detect and catalog configuration files",
|
||||||
|
no_args_is_help=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("all")
|
||||||
|
def detect_all(
|
||||||
|
category: Optional[str] = typer.Option(
|
||||||
|
None, "--category", "-c", help="Filter by category (editor, terminal, shell, git, ssh, docker, tmux, misc)"
|
||||||
|
),
|
||||||
|
tool: Optional[str] = typer.Option(
|
||||||
|
None, "--tool", "-t", help="Filter by tool name"
|
||||||
|
),
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
|
||||||
|
):
|
||||||
|
"""Detect all configuration files."""
|
||||||
|
categories = None
|
||||||
|
if category:
|
||||||
|
try:
|
||||||
|
categories = [ConfigCategory(category.lower())]
|
||||||
|
except ValueError:
|
||||||
|
console.print(f"[red]Error:[/red] Unknown category '{category}'")
|
||||||
|
console.print(f"Available categories: {', '.join([c.value for c in ConfigCategory])}")
|
||||||
|
return
|
||||||
|
|
||||||
|
configs = DetectorRegistry.detect_all(categories)
|
||||||
|
|
||||||
|
if tool:
|
||||||
|
configs = [c for c in configs if c.tool_name.lower() == tool.lower()]
|
||||||
|
|
||||||
|
if not configs:
|
||||||
|
console.print("[yellow]No configuration files detected.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
table = Table(title="Detected Configuration Files")
|
||||||
|
table.add_column("Tool", style="cyan")
|
||||||
|
table.add_column("Category", style="magenta")
|
||||||
|
table.add_column("File Path", style="green")
|
||||||
|
table.add_column("Size", justify="right", style="yellow")
|
||||||
|
|
||||||
|
for config in configs:
|
||||||
|
table.add_row(
|
||||||
|
config.tool_name,
|
||||||
|
config.category.value,
|
||||||
|
config.path if len(config.path) < 50 else "..." + config.path[-47:],
|
||||||
|
f"{config.size} bytes" if verbose else str(config.size),
|
||||||
|
)
|
||||||
|
|
||||||
|
console.print(Panel.fit(
|
||||||
|
f"[bold]Detected {len(configs)} configuration files[/bold]",
|
||||||
|
style="blue",
|
||||||
|
))
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
by_category: Dict[str, int] = {}
|
||||||
|
by_tool: Dict[str, int] = {}
|
||||||
|
for config in configs:
|
||||||
|
cat = config.category.value
|
||||||
|
by_category[cat] = by_category.get(cat, 0) + 1
|
||||||
|
tool = config.tool_name
|
||||||
|
by_tool[tool] = by_tool.get(tool, 0) + 1
|
||||||
|
|
||||||
|
console.print("\n[bold]By Category:[/bold]")
|
||||||
|
for cat, count in by_category.items():
|
||||||
|
console.print(f" {cat}: {count}")
|
||||||
|
|
||||||
|
console.print("\n[bold]By Tool:[/bold]")
|
||||||
|
for tool, count in by_tool.items():
|
||||||
|
console.print(f" {tool}: {count}")
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("editor")
|
||||||
|
def detect_editors(
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
|
||||||
|
):
|
||||||
|
"""Detect editor configuration files."""
|
||||||
|
configs = DetectorRegistry.detect_all([ConfigCategory.EDITOR])
|
||||||
|
|
||||||
|
if not configs:
|
||||||
|
console.print("[yellow]No editor configuration files detected.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
_display_configs(configs, "Editor", verbose)
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("terminal")
|
||||||
|
def detect_terminal(
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
|
||||||
|
):
|
||||||
|
"""Detect terminal configuration files."""
|
||||||
|
configs = DetectorRegistry.detect_all([ConfigCategory.TERMINAL])
|
||||||
|
|
||||||
|
if not configs:
|
||||||
|
console.print("[yellow]No terminal configuration files detected.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
_display_configs(configs, "Terminal", verbose)
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("shell")
|
||||||
|
def detect_shell(
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
|
||||||
|
):
|
||||||
|
"""Detect shell configuration files."""
|
||||||
|
configs = DetectorRegistry.detect_all([ConfigCategory.SHELL])
|
||||||
|
|
||||||
|
if not configs:
|
||||||
|
console.print("[yellow]No shell configuration files detected.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
_display_configs(configs, "Shell", verbose)
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("git")
|
||||||
|
def detect_git(
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
|
||||||
|
):
|
||||||
|
"""Detect Git configuration files."""
|
||||||
|
configs = DetectorRegistry.detect_all([ConfigCategory.GIT])
|
||||||
|
|
||||||
|
if not configs:
|
||||||
|
console.print("[yellow]No Git configuration files detected.[/yellow]")
|
||||||
|
return
|
||||||
|
|
||||||
|
_display_configs(configs, "Git", verbose)
|
||||||
|
|
||||||
|
|
||||||
|
@detect_cmd.command("tools")
|
||||||
|
def list_tools():
|
||||||
|
"""List all available detection tools."""
|
||||||
|
tools = DetectorRegistry.list_tools()
|
||||||
|
categories = DetectorRegistry.list_categories()
|
||||||
|
|
||||||
|
console.print("[bold]Available Detection Tools:[/bold]")
|
||||||
|
for tool in sorted(tools):
|
||||||
|
detector = DetectorRegistry.get_detector(tool)
|
||||||
|
if detector:
|
||||||
|
console.print(f" [cyan]{tool}[/cyan] ({detector.category.value})")
|
||||||
|
|
||||||
|
console.print("\n[bold]Available Categories:[/bold]")
|
||||||
|
for cat in categories:
|
||||||
|
console.print(f" [magenta]{cat.value}[/magenta]")
|
||||||
|
|
||||||
|
|
||||||
|
def _display_configs(configs: List[ConfigFile], title: str, verbose: bool):
|
||||||
|
"""Display detected configurations in a table."""
|
||||||
|
table = Table(title=f"Detected {title} Configuration Files")
|
||||||
|
table.add_column("Tool", style="cyan")
|
||||||
|
table.add_column("File Path", style="green")
|
||||||
|
table.add_column("Size", justify="right", style="yellow")
|
||||||
|
|
||||||
|
for config in configs:
|
||||||
|
path_display = config.path if len(config.path) < 60 else "..." + config.path[-57:]
|
||||||
|
table.add_row(
|
||||||
|
config.tool_name,
|
||||||
|
path_display,
|
||||||
|
f"{config.size} bytes" if verbose else str(config.size),
|
||||||
|
)
|
||||||
|
|
||||||
|
console.print(Panel.fit(
|
||||||
|
f"[bold]Detected {len(configs)} {title} configuration files[/bold]",
|
||||||
|
style="blue",
|
||||||
|
))
|
||||||
|
console.print(table)
|
||||||
Reference in New Issue
Block a user