65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
"""Build a target library tree preview from an execution plan."""
|
|||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from collections import defaultdict
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from vlm.models import ExecutionPlan
|
||
|
|
from vlm.review_display import display_path
|
||
|
|
|
||
|
|
|
||
|
|
def build_structure_preview_lines(
|
||
|
|
plan: ExecutionPlan,
|
||
|
|
library_root: Path,
|
||
|
|
*,
|
||
|
|
max_titles: int = 40,
|
||
|
|
max_paths_per_title: int = 8,
|
||
|
|
) -> list[str]:
|
||
|
|
"""Return ASCII lines showing where move/rename operations will place files."""
|
||
|
|
by_title: dict[str, list[str]] = defaultdict(list)
|
||
|
|
|
||
|
|
for op in plan.operations:
|
||
|
|
if op.operation_type not in ("move", "rename") or not op.destination_path:
|
||
|
|
continue
|
||
|
|
ctx = op.review_context if isinstance(op.review_context, dict) else {}
|
||
|
|
title = str(ctx.get("title") or op.destination_path.parent.parent.name)
|
||
|
|
rel = display_path(op.destination_path, library_root)
|
||
|
|
by_title[title].append(rel)
|
||
|
|
|
||
|
|
lines = [
|
||
|
|
"Target library structure preview (move/rename destinations)",
|
||
|
|
f"Library root: {library_root}",
|
||
|
|
"",
|
||
|
|
]
|
||
|
|
if not by_title:
|
||
|
|
lines.append("(no move/rename destinations)")
|
||
|
|
return lines
|
||
|
|
|
||
|
|
sorted_titles = sorted(by_title.keys())[:max_titles]
|
||
|
|
for title in sorted_titles:
|
||
|
|
paths = sorted(set(by_title[title]))[:max_paths_per_title]
|
||
|
|
lines.append(f"{title}/")
|
||
|
|
for p in paths:
|
||
|
|
lines.append(f" {p}")
|
||
|
|
remaining = len(by_title[title]) - len(paths)
|
||
|
|
if remaining > 0:
|
||
|
|
lines.append(f" ... +{remaining} more path(s)")
|
||
|
|
lines.append("")
|
||
|
|
|
||
|
|
if len(by_title) > max_titles:
|
||
|
|
lines.append(f"... +{len(by_title) - max_titles} more title(s)")
|
||
|
|
|
||
|
|
return lines
|
||
|
|
|
||
|
|
|
||
|
|
def write_structure_preview(
|
||
|
|
plan: ExecutionPlan,
|
||
|
|
library_root: Path,
|
||
|
|
output_path: Path,
|
||
|
|
) -> None:
|
||
|
|
"""Write structure preview text to a file."""
|
||
|
|
lines = build_structure_preview_lines(plan, library_root)
|
||
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
|
output_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|