Skip to content

feat: add diecut distill command#130

Open
raiderrobert wants to merge 9 commits intofeat/extract-auto-detectfrom
feat/distill-command
Open

feat: add diecut distill command#130
raiderrobert wants to merge 9 commits intofeat/extract-auto-detectfrom
feat/distill-command

Conversation

@raiderrobert
Copy link
Copy Markdown
Owner

Summary

  • Adds diecut distill command that creates templates by comparing 2+ existing projects
  • Instead of looking at one project and guessing what to parameterize, compares multiple projects and lets the differences reveal the variables
  • Reuses extract's variant generation, replacement engine, scanning, and config generation
  • Full roundtrip tested: distill produces a template that works with diecut new

Usage

diecut distill ./project-a ./project-b --var project_name=my-tool

Produces a template where:

  • Files in all projects become the skeleton
  • Content that varies where --var values appear becomes parameterized
  • Everything else is discarded

Flags: --depth N (default 1), --dry-run, --force, --output DIR

How it works

  1. Scan all projects at shallow depth (default: top-level + one subdirectory level)
  2. Intersect — keep only files present in ALL projects
  3. Cross-validate — suppress variables whose values don't actually vary across projects
  4. Replace — apply variable substitutions to project[0]'s content using case-variant-aware matching
  5. Generate diecut.toml with prompted + computed variables
  6. Write the template

Test plan

  • Unit tests for intersection logic (7 tests)
  • Unit tests for cross-validation logic (7 tests)
  • Integration tests for plan_distill (4 tests)
  • End-to-end roundtrip: distill → diecut new → verify substitutions
  • CLI smoke test with --dry-run
  • cargo fmt --check && cargo clippy -- -D warnings && cargo test all pass (277 tests)

Three minimal Rust CLI projects that share structure but vary in
project_name and author, with deliberate intersection/exclusion
properties (.gitignore and assets/ only in A+B, LICENSE only in C)
for testing diecut distill.
Add six new variants for the upcoming diecut distill command:
DistillMinProjects, DistillNoCommonFiles, DistillInvalidVarName,
DistillSlashInValue, DistillEmptyValue, and DistillOutputExists.
Adds an optional max_depth: Option<usize> parameter that limits how deep
the file walker descends into subdirectories. None preserves existing
unlimited-depth behavior. Updates all call sites to pass None.
…ctive

Implements DistillVariable struct and the is_variable_active function
that determines whether a variable genuinely varies across projects by
checking if any variant literal appears in project[0] and if at least
one other project has different content for that file. Binary files are
skipped. Includes 7 unit tests covering all specified cases.
…cans

Adds the distill module with intersect_scans, which computes the
common-file intersection across multiple ScanResults and returns
AlignedFile structs with per-project content aligned by scan index.
Implements the full plan_distill + execute_distill pipeline:
phases 0-7 covering input validation, variable expansion, project
scanning, file intersection, cross-validation, file processing,
config generation, and output writing. Adds four integration tests
covering the two-project happy path, static variable suppression,
three-project intersection, and single-project error handling.
Wire up the `distill` subcommand with `Distill` variant in the Commands
enum, a new `src/commands/distill.rs` handler, and dispatch in main.rs.
Proves the full cycle: distill a template from two projects, then
generate a new project from that template, and verify substitutions
are correctly applied in the output.
- Warn when a variable value is shorter than 3 characters (false match risk)
- Warn when two variables share the same value
- Warn when a processed file contains more {{ }} expressions than
  our replacements introduced (likely needs {{% raw %}} blocks)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant