Set as interactive on startup, set options(device =)
to a string
#905
+156
−48
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.
Addresses posit-dev/positron#7681
My preferred alternative to #895
In a fresh R session,
.Device
in RStudio returns"null device"
andgetOption("device")
returns"RStudioGD"
. i.e. R doesn't have a current device active, but it knows to use a function namedRStudioGD()
when it needs to make one (and indeed you can callRStudioGD
at the console and you can find it yourself).For these reasons, I do not think we should inject ourselves as the current active device on startup as proposed by #895. I think we should also follow RStudio's lead and let the device be
"null device"
until a plot is actually required.To solve the problem a different way, we just recognize that the main issue is that we are calling
grDevices::deviceIsInteractive()
to register ourselves as an interactive device too late - we are calling it at first plot time, but should call it at startup time. I have made that change in this PR, and in theory that should have been enough to fix the issue.In practice there is one other issue I had to deal with. We set
options(device = <fn>)
where RStudio setsoptions(device = "RStudioGD")
. This is surprisingly important. In a fresh session,grDevices::dev.interactive(orNone = TRUE)
(used bydemo(graphics)
) will look to see if the current device is in the set of known devices provided bydeviceIsInteractive()
. However, if that device is"null device"
, then it will consultgetOption("device")
and see if that name is in the set provided bydeviceIsInteractive()
instead. But if you setoptions(device =)
to a function rather than a name then you don't get to take advantage of this nice feature. I've reworked a few things to take advantage of this now. Importantly, we now mimic RStudio exactly here.I've also updated docs and added tests to assert our beliefs about how these functions work on startup.
QA Notes
Running
demo(graphics)
in a fresh session with release Positron should render all the plots non-interactively:Screen.Recording.2025-05-14.at.08.14.06.mov
With the fix, this should now prompt you to type Enter between each plot.
Screen.Recording.2025-08-09.at.16.31.17.mov