Add CLI modules: main, detect, manifest
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-02-04 20:03:53 +00:00
parent 503f61b562
commit c3a7243bb9

180
confsync/cli/detect.py Normal file
View 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)