Add record functionality for recording + replaying plots as objects - #686
Merged
Conversation
- top-level "record" argument and equivalent tpar param for setting globally
- at the same time, drop the (now stale) experimental tag for "draw"
There was a problem hiding this comment.
🟡 Changes recommended
Replay state remains incomplete, direct replayPlot() bypasses context restoration, and pairs-style data frames do not return the documented object.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds opt-in recording and replay of tinyplot graphics while preserving state needed for subsequent layers.
Changes:
- Adds
recordargument andtpar()setting. - Introduces
recordedtinyplotobjects with print/structure methods. - Adds documentation, website navigation, and tests.
File summaries
| File | Description |
|---|---|
R/record.R |
Implements recorded objects and state restoration. |
R/setup_device.R |
Enables display lists for managed file devices. |
R/tinyplot.R |
Adds recording to the main plotting pipeline. |
R/tpar.R |
Adds global recording configuration. |
R/zzz.R |
Registers the new internal variable. |
R/tinyplot.ts.R |
Inherits updated return documentation. |
R/tinyplot.matrix.R |
Inherits updated return documentation. |
R/tinyplot.data.frame.R |
Inherits updated return documentation. |
R/tinyplot_add.R |
Documents recorded layer returns. |
inst/tinytest/test-record.R |
Tests recording, replay, and layering. |
NAMESPACE |
Registers methods and grDevices imports. |
NEWS.md |
Announces experimental recording support. |
vignettes/introduction.qmd |
Demonstrates saving and replaying plots. |
man/recordedtinyplot.Rd |
Documents recorded plot objects. |
man/tinyplot.Rd |
Documents the argument and return value. |
man/tpar.Rd |
Documents global recording configuration. |
man/tinyplot.ts.Rd |
Updates generated return documentation. |
man/tinyplot.matrix.Rd |
Updates generated return documentation. |
man/tinyplot.data.frame.Rd |
Updates generated return documentation. |
man/tinyplot_add.Rd |
Updates generated return documentation. |
altdoc/quarto_website.yml |
Adds the new reference page. |
altdoc/pkgdown.yml |
Updates the site-build timestamp. |
Review details
Files not reviewed (7)
- man/recordedtinyplot.Rd: Generated file
- man/tinyplot.Rd: Generated file
- man/tinyplot.data.frame.Rd: Generated file
- man/tinyplot.matrix.Rd: Generated file
- man/tinyplot.ts.Rd: Generated file
- man/tinyplot_add.Rd: Generated file
- man/tpar.Rd: Generated file
- Files reviewed: 15/22 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
recordPlot functionality for recording and replaying plots as objectsrecord functionality for recording + replaying plots as objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #121
Updated description
The PR adds a new top-level
tinyplot(..., record = <logical>)argument, which in turn enables (modified)grDevices::recordPlotfunctionality for recording and replaying tinyplots as objects. User can also enable globally via the sistertpar(record = TRUE)option.Apart from switching to an explicit opt-in, the main changes from the first iteration of this PR are related to safer handling of replayed (in turn, via better integration with
tinyplotinternals). This includes automaticdisplaylistlanding for external devices, as well as smart theme and call restoration. Some of this is enabled by the newrecordedtinyplotobject class, which is really just a thin+tinyplot-friendly wrapper aroundrecordedplot.P.S. I'm currently marking this feature as "Experimental. But I've test it pretty thoroughly locally and everything seems to be working well. There's minimal overhead and the explicit opt-in requirement also gives us an off-ramp in case we notice any (unfixable) unintended consequences down the road.
MWEs
Basic use via top-level
recordargument:We can then carry on with our session, including constructing other plots, before replaying our saved object (and add layers to it, if desired).
recordis requires explicit op-in, but users can also set globally viatpar. One cool feature is that you can record a plot written to an external device (PDF, PNG, etc.) and then recall it later to your interactive viewer.Aside: with global recording turned on (
tpar(record = TRUE)), all of the regular object-based idioms and workflows apply. For example, you can draw a plot without explicit assignment and then retrieve it immediately after with.Last.value.plt(Nile)Don't forge to disable automatic recording. The overhead is minimal, but it can start to eat into memory if you start recording+assigning lots of detailed plots with many elements.
Original (outdated) description
By adding
grDevices::recordPlot()to the very end of the maintinyplot()function, we gain the ability to record (assign) plots as objects and then replay them later.Here's a little
plt_addgotcha, though...But note that nothing stops us from layering immediately... and we can record and replay from a later layer too. Here, demonstrating with a theme to drive home the point.
Note: Due to the "canvas" nature of base graphics, we can't suppress the initial display. Unless, that is, we do something tricksy like write to a dummy device / file on disk and then recall later.
Created on 2026-08-20 with reprex v2.1.1
Discussion: To be clear, I'm not convinced that we want to add this functionality. But some quick testing, at least, suggests that it doesn't add any real overhead. Apart from the
plt_add()gotcha that I highlight above, I also haven't hit any unintended side effects. Still, I'd like others to kick the tyres too, before we consider whether merging is a good idea.