Skip to content

Fix issue live preview#2747

Open
karenemily wants to merge 7 commits into
copier-org:masterfrom
karenemily:fix-issue-live-preview
Open

Fix issue live preview#2747
karenemily wants to merge 7 commits into
copier-org:masterfrom
karenemily:fix-issue-live-preview

Conversation

@karenemily

Copy link
Copy Markdown

What does this PR do?

Adds a new copier preview command that allows template developers to preview
how their template renders locally with hot-reloading. When a developer runs
copier preview <template_src> <destination_path>, Copier renders the template
immediately and then watches the template directory for any file changes,
automatically re-rendering whenever a change is saved.

Why was this PR needed?

Currently, template developers have no way to preview how their template renders
without going through a slow manual cycle of committing changes, pushing to
GitHub, switching to a downstream project, and running copier update. This
makes template development extremely tedious and slow, especially for small
iterative changes.

This PR implements the feature requested in issue #1451 by adding a
run_preview function that wraps the existing _render_template logic in a
watchfiles file watcher loop, and exposes it as a copier preview CLI
subcommand.

What are the relevant issue numbers?

Closes #1451

Does this PR meet the acceptance criteria?

  • Tests added for new/changed behavior
  • All tests passing (2 pre-existing Windows-only failures unrelated to
    this change)
  • Follows project style guide
  • No breaking changes introduced
  • Documentation updated (if applicable)

@karenemily

Copy link
Copy Markdown
Author

Hi @sisp — this is my first contribution to Copier. I've implemented the live preview feature requested in #1451 by adding a copier preview command with hot-reloading support using watchfiles. Would appreciate a review when you have time!

@sisp sisp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the current implementation is a correct solution to the problem.

  • It is insufficient to run Worker._render_template on source file changes – this ignores changes in the questionnaire, which likely affects the render context, and doesn't (re)run tasks, which may be essential to the render output.
  • It doesn't remove files that were previously rendered but are no longer rendered after a template change – files are only added or replaced.

I imagine a (more) correct solution might involve making a full copy (using run_copy) in a temporary destination, computing the filetree diff between the temporary copy and the user-specified destination, and syncing the latter to the former. But this is just the first idea that has come to my mind right now. I imagine the devil is in the details. For example, for good UX you'll likely want to ask only questions that were changed in copier.yml, but a template might not render an answers file which is what copier update --skip-answered uses.


Currently, template developers have no way to preview how their template renders
without going through a slow manual cycle of committing changes, pushing to
GitHub, switching to a downstream project, and running copier update. This
makes template development extremely tedious and slow, especially for small
iterative changes.

I think serious template authors need a test suite to test their templates, this manual cycle is not sustainable for non-trivial templates. FWIW, there's a trick that lets you avoid pushing to a Git platform when testing a local change on an existing Copier-managed project.

Comment thread CONTRIBUTION.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this file, it doesn't belong in this repo.

Updated contribution status and added maintainer feedback.
@karenemily

Copy link
Copy Markdown
Author

Thank you for the detailed feedback @sisp! I understand the issues with the current approach. Before I attempt a revised implementation, I have a few questions to make sure I'm on the right track:

  1. For the temporary directory approach, when run_copy() runs into the temp directory on each change, how should we handle the questionnaire? Should we capture the answers from the first run and pass them via the data parameter on subsequent runs to avoid re-prompting the user each time a file changes?

  2. For syncing the temp directory to the destination, does Copier already have utilities for computing file diffs between two directories, or should we use Python's built-in filecmp module?

  3. For deleted files, how do we distinguish between files that were rendered by Copier and files the user may have created themselves in the destination folder, so we only delete the former?

  4. For tasks, should tasks re-run on every file change, or only on the initial render?

I want to make sure I implement this correctly before writing more code. Thanks for your patience with a first-time contributor!

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.

Add template preview

2 participants