[education/rkward] /: Further tweak details of hooks to what is possible in R. Document.

Thomas Friedrichsmeier null at kde.org
Sun Aug 24 16:08:55 BST 2025


Git commit 31736ed2b2b904a0538d5b0a542e73aedd44c436 by Thomas Friedrichsmeier.
Committed on 24/08/2025 at 15:06.
Pushed by tfry into branch 'master'.

Further tweak details of hooks to what is possible in R. Document.

M  +1    -1    VERSION.cmake
M  +1    -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
M  +4    -2    rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
M  +1    -1    rkward/rbackend/rpackages/rkward/DESCRIPTION
M  +4    -0    rkward/rbackend/rpackages/rkward/NAMESPACE
M  +51   -37   rkward/rbackend/rpackages/rkward/R/public_graphics.R
M  +36   -6    rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
M  +3    -3    rkward/rbackend/rpackages/rkward/man/DeviceOverrides.Rd
A  +78   -0    rkward/rbackend/rpackages/rkward/man/RKdevicehooks.Rd
A  +49   -0    rkward/rbackend/rpackages/rkward/man/rk.eval.as.preview.Rd
M  +2    -1    rkward/rbackend/rpackages/rkward/man/rk.old.packages.Rd
M  +1    -1    rkward/windows/rkcommandeditorwindow.cpp

https://invent.kde.org/education/rkward/-/commit/31736ed2b2b904a0538d5b0a542e73aedd44c436

diff --git a/VERSION.cmake b/VERSION.cmake
index b0a2d0180..db0a2b651 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -1,3 +1,3 @@
 # DO NOT CHANGE THIS FILE MANUALLY!
 # It will be overwritten by scripts/set_dist_version.sh
-SET(RKVERSION_NUMBER 0.8.1z+0.8.2+devel3b)
+SET(RKVERSION_NUMBER 0.8.1z+0.8.2+devel3)
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
index 18b8418d6..f2b734f2d 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
@@ -42,6 +42,7 @@ struct RKGraphicsDeviceDesc {
 	}
 
   private:
+	friend SEXP RKD_AdjustSize(SEXP, SEXP);
 	int _revision = 0;
 	int _nextrevision = 1;
 };
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index 6f3896aa1..40ca60133 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -319,7 +319,9 @@ SEXP RKD_AdjustSize(SEXP _devnum, SEXP _id) {
 	// TODO: Do we want to block advancing revision, here?
 
 	RKD_SetSize(dev); // This adjusts the rendering area in the frontend
+	const auto rev = static_cast<RKGraphicsDeviceDesc *>(dev->deviceSpecific)->_revision;
 	if (gdev->dirty) RFn::GEplayDisplayList(gdev);
+	static_cast<RKGraphicsDeviceDesc *>(dev->deviceSpecific)->_revision = rev;
 	return ROb(R_NilValue);
 }
 
@@ -433,7 +435,7 @@ static double RKD_StrWidthUTF8(const char *str, R_GE_gcontext *gc, pDevDesc dev)
 
 static void RKD_NewPage(R_GE_gcontext *gc, pDevDesc dev) {
 	RK_TRACE(GRAPHICS_DEVICE);
-	callHookFun("before.blank", dev);
+	callHookFun("in.blank", dev, RFn::Rf_desc2GEDesc(dev)->savedSnapshot);
 	RKGraphicsDataStreamWriteGuard guard;
 	WRITE_HEADER(RKDNewPage, dev);
 	WRITE_FILL();
@@ -470,7 +472,7 @@ static void RKD_MetricInfo(int c, R_GE_gcontext *gc, double *ascent, double *des
 
 static void RKD_Close(pDevDesc dev) {
 	RK_TRACE(GRAPHICS_DEVICE);
-	callHookFun("after.close", dev, RFn::GEcreateSnapshot(RFn::desc2GEDesc(dev)));
+	callHookFun("in.close", dev, RFn::GEcreateSnapshot(RFn::desc2GEDesc(dev)));
 	{
 		RKGraphicsDataStreamWriteGuard guard;
 		WRITE_HEADER(RKDClose, dev);
diff --git a/rkward/rbackend/rpackages/rkward/DESCRIPTION b/rkward/rbackend/rpackages/rkward/DESCRIPTION
index cddfabf2d..3d1f2eebf 100755
--- a/rkward/rbackend/rpackages/rkward/DESCRIPTION
+++ b/rkward/rbackend/rpackages/rkward/DESCRIPTION
@@ -15,7 +15,7 @@ LazyLoad: yes
 Authors at R: c(person(given="Thomas", family="Friedrichsmeier", email="thomas.friedrichsmeier at kdemail.net", role=c("aut")), person(given="the RKWard", family="team",
                     email="rkward-devel at kde.org", role=c("cre","aut")))
 Version: 0.8.2
-Date: 2025-06-01
+Date: 2025-06-02
 RoxygenNote: 7.3.2
 Collate: 
     'base_overrides.R'
diff --git a/rkward/rbackend/rpackages/rkward/NAMESPACE b/rkward/rbackend/rpackages/rkward/NAMESPACE
index 9d503780c..69fbf600d 100644
--- a/rkward/rbackend/rpackages/rkward/NAMESPACE
+++ b/rkward/rbackend/rpackages/rkward/NAMESPACE
@@ -38,6 +38,9 @@ export(.rk.variables)
 export(.rk.with.window.hints)
 export(RK)
 export(RK.Output)
+export(RK.addHook)
+export(RK.removeHook)
+export(RK.revision)
 export(Sys.setlocale)
 export(X11)
 export(q)
@@ -61,6 +64,7 @@ export(rk.edit)
 export(rk.edit.files)
 export(rk.embed.device)
 export(rk.end.capture.output)
+export(rk.eval.as.preview)
 export(rk.first.plot)
 export(rk.flush.output)
 export(rk.force.append.plot)
diff --git a/rkward/rbackend/rpackages/rkward/R/public_graphics.R b/rkward/rbackend/rpackages/rkward/R/public_graphics.R
index e9fbb72d3..3bc6084f2 100644
--- a/rkward/rbackend/rpackages/rkward/R/public_graphics.R
+++ b/rkward/rbackend/rpackages/rkward/R/public_graphics.R
@@ -156,41 +156,60 @@
 #' \code{RK.revision()} can be used to detect changes done to an existing \code{RK()} by comparing the
 #'                      return value of two subsequent calls: If the value has increased, the plot has been touched.
 #'
-#' @param after.create (Omit this argument, if you do not want to set this type of hook.) A function to be called
-#'                     immediately after a new \code{RK()} device has been created. The function must accept at least one
-#'                     parameter (the corresponding device number). It is recommended to add \code{...} in addition,
+#' @param after.create (optional argument) A function with the signature \code{function(devnum, ...)}, to be called
+#'                     immediately after a new \code{RK()} device has been created. The function will be called with
+#'                     the corresponding device number as the first arugment. It is recommended to add \code{...} in addition,
 #'                     to remain compatible with future extensions.
 #'
-#' @param after.close (Omit this argument, if you do not want to set this type of hook.) Called immediately after a device
-#'                    is closed. At this point the device may or may not still be visible, but can no longer be accessed.
-#'                    The function is called with two parameters: the device number, and a snapshot of the most recent
-#'                    plot (as would have been produced by \code{recordPlot()}; empty, if disabled via \code{dev.control()}.
-#'                    It is recommended to add a \code{...} argument, in order to remain compatible with future extensions.
+#' @param in.close (optional argument) A function with the signature \code{function(devnum, snapshot, ...)}. Called when a device is closed.
+#'                 At this point the device may or may not still be visible, but can no longer be accessed.
+#'                 The function is called with two parameters: the device number, and a snapshot of the most recent
+#'                 plot (as would have been produced by \code{recordPlot()}; empty, if disabled via \code{dev.control()}.
 #'
-#' @param before.blank (Omit this argument, if you do not want to set this type of hook.) Called whenever an existing device
-#'                     is blanked. This usually happens when a new plot is about to be drawn. While this hook is called,
-#'                     it is still possible to access the old contents.
+#' @param in.blank (optional argument) A function with the signature \code{function(devnum, snapshot, ...)}.
+#'                 The given function will be Called whenever an existing device is blanked, i.e. usually, when a new plot 
+#'                 is about to be drawn. While this hook is called, the old plot is still visible, but \code{recordPlot()}
+#'                 / \code{dev.copy} would return / copy a blank plot, already. You can retrieve the previous plot from the
+#'                 parameter \code{snapshot}, instead (unless plot recording has been disabled via \code{dev.control()}).
 #'
 #' @param devnum Device number
 #'
-#' @details The return value of \code{RK.addHook()) may be passed to \code{RK.removeHook()) to remove the hook(s) registered
+#' @details The return value of \code{RK.addHook()} may be passed to \code{RK.removeHook()} to remove the hook(s) registered
 #'          in that call. No assumptions should be made on the exact nature of that return value (it might be subject to
 #'          change in future versions.
 #'
 #'          \code{RK.revision()} returns a integer number. This will be 0 for a device that has just been created. If the device
 #'          is modified (changes need not necessarily be visible), the next call to \code{RK.revision()} will return a larger
 #'          number. The details of how revisions are counted may be subject to change, and in particular they do not give
-#'          any information on how much has been changed..
+#'          any information on how much has been changed. Redraws due to resizing the plot window do not increase the revision number.
 #'
 #' @seealso \link{RK}
 #' @examples
 #' \dontrun{
-#' ## TODO
+#' hook <- RK.addHook(
+#'    after.create=function(devnum, ...) {
+#'        print(paste0("New device ", devnum))
+#'    },
+#'    in.close=function(devnum, snapshot, ...) {
+#'        print(paste0("Closed device ", devnum))
+#'    }
+#' )
+#'
+#' RK() # Prints "New device N"
+#' plot(1, 1)
+#' rev <- RK.revision(dev.cur())
+#' plot(2, 2) # we know this will touch the plot, but consider e.g. sourcing a script, here
+#' if (RK.revision(dev.cur()) > rev) {
+#'    print("Plot was modified")
+#' }
+#' dev.off() # Prints "Closed device N"
+#'
+#' RK.removeHook(hook)
 #' }
 #'
-#' @export
 #' @rdname RKdevicehooks
-RK.addHook <- function(after.create, after.close, before.blank) {
+#' @export
+RK.addHook <- function(after.create, in.close, in.blank) {
 	if (is.null(.rk.variables$.RKdevhooks$nextid)) .rk.variables$.RKdevhooks$nextid <- 0
 	id = .rk.variables$.RKdevhooks$nextid
 	.rk.variables$.RKdevhooks$nextid <- id + 1
@@ -202,52 +221,47 @@ RK.addHook <- function(after.create, after.close, before.blank) {
 	if (!missing(after.create)) {
 		appendHook("after.create", after.create, id)
 	}
-	if (!missing(after.close)) {
-		appendHook("after.close", after.close, id)
+	if (!missing(in.close)) {
+		appendHook("in.close", in.close, id)
 	}
-	if (!missing(before.blank)) {
-		appendHook("before.blank", before.blank, id)
+	if (!missing(in.blank)) {
+		appendHook("in.blank", in.blank, id)
 	}
 	invisible(id)
 }
 
-#' @export
 #' @rdname RKdevicehooks
+#' @export
 RK.removeHook <- function(handle) {
 	removeHook <- function(at, id) {
 		.rk.variables$.RKdevhooks[[at]] <- .rk.variables$.RKdevhooks[[at]][names(.rk.variables$.RKdevhooks[[at]]) != id]
 	}
 	removeHook("after.create", handle)
-	removeHook("after.close", handle)
-	removeHook("before.blank", handle)
+	removeHook("in.close", handle)
+	removeHook("in.blank", handle)
 	invisible(NULL)
 }
 
 # not exported
-.RK.callHook <- function(hook, id, data, ...) {
+.RK.callHook <- function(hook, id, data) {
 	for (fun in .rk.variables$.RKdevhooks[[hook]]) {
-		if (hook == "after.close") {
-			# pity it's too late for recordPlot() at this point. We need to re-create things, manually
+		if (!missing(data)) {
+			# so far, data, if present in a hook, is a graphics snapshot
+			# (which is needed, because unfortunately recordPlot() is not usuable at the points of interest)
 			attr(data, "pid") <- Sys.getpid()
 			attr(data, "Rversion") <- getRversion()
 			class(data) <- "recordedplot"
-			try({fun(id, data, ...)})
+			try({fun(id, data)})
 		} else {
-			try({fun(id, ...)})
+			try({fun(id)})
 		}
 	}
 }
 
-# TODO: document properly
-# TODO: ignore redraws?
-# For detecting changes in the graph shown in the given device, call this function twice.
-# The device has been modified, if the returned number has increased.
-# NOTE: The magnitude of the increase carries no meaning at all.
-# NOTE: Reset to 0 when the device is closed
-#' @export
 #' @rdname RKdevicehooks
-RK.revision <- function(device) {
-	.Call("rk.graphics.mod", as.integer(device), PACKAGE="(embedding)")
+#' @export
+RK.revision <- function(devnum=dev.cur()) {
+	.Call("rk.graphics.mod", as.integer(devnum), PACKAGE="(embedding)")
 }
 
 #' Embed non-RKWard device windows
diff --git a/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R b/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
index 4bf83f677..9413b4f20 100644
--- a/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
+++ b/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
@@ -281,9 +281,37 @@
 	rk.set.output.html.file (x, ...)
 }
 
-# TODO: document me
+#' Evaluate the given input file, recording a transcript to an HTML output file (including on-screen plots) 
+#'
+#' @param infile The input R file, specified as a character string, or a connection (passed to \link{parse}).
+#' @param outfile The output HTML file, specified as a character string. If this file exists, it will be overwritting, without further notice!
+#' @param echo Include the source expressions in the output? (boolean)
+#' @param env Environment of the evaluation. See details, below.
+#' @param stop.on.error Whether to stop (TRUE) or continue (FALSE) on errors
+#'
+#' @details Contrary to \link{source}, some effort is made to avoid lasting side-effects to the workspace, however these cannot be ruled out,
+#'          in all cases. Among other things, the following may lead to lasting effects:
+#'
+#'          \itemize{
+#'              \item{Installing / updating / removing / loading packages}
+#'              \item{Writing to the filesystem in any form}
+#'              \item{Targetting pre-existing graphics devices with \code{dev.set()}, \code{dev.off()}, etc.}
+#'              \item{Opening / closing windows in the RKWard workplace}
+#'              \item{Exclusively assuming the R engine (e.g. shiny apps)}
+#'              \item{Assignments outside the current scope (see also below)}
+#'          }
+#'
+#'          The default argument value for \code{env} allows the evaluated script to access objects inside the \code{globalenv()}, but
+#'          limits regular assignments (i.e. using \code{<-} rather than \code{<<-} or \code{assign()}) to a temporary local scope. Depending on the
+#'          desired semantics, \code{new.env()} or \code{globalenv()} may be useful alternatives.
+#'
+#'          The idea of \code{rk.eval.as.preview} is to visualize what would happen when running the given code in the R console,
+#'          interactively. Importantly, however, due to the evaluation inside a function, any error messages and backtraces will differ,
+#'          and taskCallbacks will not run.
+#'
+#' @rdname rk.eval.as.preview
 #' @export
-rk.eval.as.console.preview <- function(infile, outfile, env=new.env(parent=globalenv()), stop.on.error=FALSE) {
+rk.eval.as.preview <- function(infile, outfile, echo=TRUE, env=new.env(parent=globalenv()), stop.on.error=FALSE) {
 	## init output file
 	output <- rk.set.output.html.file(outfile, silent=TRUE)
 	on.exit({
@@ -310,7 +338,7 @@ rk.eval.as.console.preview <- function(infile, outfile, env=new.env(parent=globa
 			.rk.cat.output("<div align=\"right\">Plot window created</div>");
 			devs[[as.character(devnum)]] <<- RK.revision(devnum)
 		},
-		before.close=function(devnum) {
+		in.close=function(devnum) {
 			.rk.cat.output("<div align=\"right\">Plot window closed</div>");
 			devs[[as.character(devnum)]] <<- NULL
 		}
@@ -361,19 +389,21 @@ rk.eval.as.console.preview <- function(infile, outfile, env=new.env(parent=globa
 		exprs <- parse(infile, keep.source=TRUE)
 	})
 	.rk.cat.output(rk.end.capture.output(TRUE))
-	if(stop.on.error && inherits(res, "try-error")) stop(res)
+	if(isTRUE(stop.on.error) && inherits(res, "try-error")) stop(res)
 
 	# actually do it
 	rk.without.plot.history({
 		for (i in seq_len(length(exprs))) {
-			rk.print.code(as.character(attr(exprs, "srcref")[[i]]))
+			if (isTRUE(echo)) {
+				rk.print.code(as.character(attr(exprs, "srcref")[[i]]))
+			}
 			rk.capture.output(suppress.messages=TRUE, suppress.output=TRUE)
 			res <- try({
 				withAutoprint(exprs[[i]], evaluated=TRUE, echo=FALSE, local=env)
 			})
 			.rk.cat.output(rk.end.capture.output(TRUE))
 			checkSavePlot()
-			if(stop.on.error && inherits(res, "try-error")) stop(res)
+			if(isTRUE(stop.on.error) && inherits(res, "try-error")) stop(res)
 		}
 	})
 
diff --git a/rkward/rbackend/rpackages/rkward/man/DeviceOverrides.Rd b/rkward/rbackend/rpackages/rkward/man/DeviceOverrides.Rd
index ee47975ab..6eee8e0cb 100644
--- a/rkward/rbackend/rpackages/rkward/man/DeviceOverrides.Rd
+++ b/rkward/rbackend/rpackages/rkward/man/DeviceOverrides.Rd
@@ -90,8 +90,8 @@ quartz(
 \item{pointsize}{the default pointsize to be used.  Defaults to \code{12}.}
 
 \item{gamma}{gamma correction fudge factor.
-    Colours in R are sRGB;  if your monitor does not conform to
-    sRGB, you might be able to improve things by tweaking this
+    Colours in R are \abbr{sRGB};  if your monitor does not conform to
+    \abbr{sRGB}, you might be able to improve things by tweaking this
     parameter to apply additional gamma correction to the RGB channels.
     By default 1 (no additional gamma correction).}
 
@@ -123,7 +123,7 @@ quartz(
 \item{title}{character string, up to 100 bytes.  With the default,
     \code{""}, a suitable title is created internally.  A C-style format
     for an integer will be substituted by the device number (see the
-    \code{file} argument to \code{\link[grDevices]{postscript}} for further
+    \code{file} argument of \code{\link{df}} for further
     details).  How non-ASCII titles are handled is
     implementation-dependent.}
 
diff --git a/rkward/rbackend/rpackages/rkward/man/RKdevicehooks.Rd b/rkward/rbackend/rpackages/rkward/man/RKdevicehooks.Rd
new file mode 100644
index 000000000..b4615a11f
--- /dev/null
+++ b/rkward/rbackend/rpackages/rkward/man/RKdevicehooks.Rd
@@ -0,0 +1,78 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/public_graphics.R
+\name{RK.addHook}
+\alias{RK.addHook}
+\alias{RK.removeHook}
+\alias{RK.revision}
+\title{Detect changes in the RKWard native graphics device(s)}
+\usage{
+RK.addHook(after.create, in.close, in.blank)
+
+RK.removeHook(handle)
+
+RK.revision(devnum = dev.cur())
+}
+\arguments{
+\item{after.create}{(optional argument) A function with the signature \code{function(devnum, ...)}, to be called
+immediately after a new \code{RK()} device has been created. The function will be called with
+the corresponding device number as the first arugment. It is recommended to add \code{...} in addition,
+to remain compatible with future extensions.}
+
+\item{in.close}{(optional argument) A function with the signature \code{function(devnum, snapshot, ...)}. Called when a device is closed.
+At this point the device may or may not still be visible, but can no longer be accessed.
+The function is called with two parameters: the device number, and a snapshot of the most recent
+plot (as would have been produced by \code{recordPlot()}; empty, if disabled via \code{dev.control()}.}
+
+\item{in.blank}{(optional argument) A function with the signature \code{function(devnum, snapshot, ...)}.
+The given function will be Called whenever an existing device is blanked, i.e. usually, when a new plot 
+is about to be drawn. While this hook is called, the old plot is still visible, but \code{recordPlot()}
+/ \code{dev.copy} would return / copy a blank plot, already. You can retrieve the previous plot from the
+parameter \code{snapshot}, instead (unless plot recording has been disabled via \code{dev.control()}).}
+
+\item{devnum}{Device number}
+}
+\description{
+\code{RK.addHook()} registers functions to be called when plot windows are created / closed / blanked.
+}
+\details{
+\code{RK.removeHook()} removes hook functions previously registered with \code{RK.addHook()}.
+
+\code{RK.revision()} can be used to detect changes done to an existing \code{RK()} by comparing the
+                     return value of two subsequent calls: If the value has increased, the plot has been touched.
+
+The return value of \code{RK.addHook()} may be passed to \code{RK.removeHook()} to remove the hook(s) registered
+         in that call. No assumptions should be made on the exact nature of that return value (it might be subject to
+         change in future versions.
+
+         \code{RK.revision()} returns a integer number. This will be 0 for a device that has just been created. If the device
+         is modified (changes need not necessarily be visible), the next call to \code{RK.revision()} will return a larger
+         number. The details of how revisions are counted may be subject to change, and in particular they do not give
+         any information on how much has been changed. Redraws due to resizing the plot window do not increase the revision number.
+}
+\examples{
+\dontrun{
+hook <- RK.addHook(
+   after.create=function(devnum, ...) {
+       print(paste0("New device ", devnum))
+   },
+   in.close=function(devnum, snapshot, ...) {
+       print(paste0("Closed device ", devnum))
+   }
+)
+
+RK() # Prints "New device N"
+plot(1, 1)
+rev <- RK.revision(dev.cur())
+plot(2, 2) # we know this will touch the plot, but consider e.g. sourcing a script, here
+if (RK.revision(dev.cur()) > rev) {
+   print("Plot was modified")
+}
+dev.off() # Prints "Closed device N"
+
+RK.removeHook(hook)
+}
+
+}
+\seealso{
+\link{RK}
+}
diff --git a/rkward/rbackend/rpackages/rkward/man/rk.eval.as.preview.Rd b/rkward/rbackend/rpackages/rkward/man/rk.eval.as.preview.Rd
new file mode 100644
index 000000000..067f14923
--- /dev/null
+++ b/rkward/rbackend/rpackages/rkward/man/rk.eval.as.preview.Rd
@@ -0,0 +1,49 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/rk.filename-functions.R
+\name{rk.eval.as.preview}
+\alias{rk.eval.as.preview}
+\title{Evaluate the given input file, recording a transcript to an HTML output file (including on-screen plots)}
+\usage{
+rk.eval.as.preview(
+  infile,
+  outfile,
+  echo = TRUE,
+  env = new.env(parent = globalenv()),
+  stop.on.error = FALSE
+)
+}
+\arguments{
+\item{infile}{The input R file, specified as a character string, or a connection (passed to \link{parse}).}
+
+\item{outfile}{The output HTML file, specified as a character string. If this file exists, it will be overwritting, without further notice!}
+
+\item{echo}{Include the source expressions in the output? (boolean)}
+
+\item{env}{Environment of the evaluation. See details, below.}
+
+\item{stop.on.error}{Whether to stop (TRUE) or continue (FALSE) on errors}
+}
+\description{
+Evaluate the given input file, recording a transcript to an HTML output file (including on-screen plots)
+}
+\details{
+Contrary to \link{source}, some effort is made to avoid lasting side-effects to the workspace, however these cannot be ruled out,
+         in all cases. Among other things, the following may lead to lasting effects:
+
+         \itemize{
+             \item{Installing / updating / removing / loading packages}
+             \item{Writing to the filesystem in any form}
+             \item{Targetting pre-existing graphics devices with \code{dev.set()}, \code{dev.off()}, etc.}
+             \item{Opening / closing windows in the RKWard workplace}
+             \item{Exclusively assuming the R engine (e.g. shiny apps)}
+             \item{Assignments outside the current scope (see also below)}
+         }
+
+         The default argument value for \code{env} allows the evaluated script to access objects inside the \code{globalenv()}, but
+         limits regular assignments (i.e. using \code{<-} rather than \code{<<-} or \code{assign()}) to a temporary local scope. Depending on the
+         desired semantics, \code{new.env()} or \code{globalenv()} may be useful alternatives.
+
+         The idea of \code{rk.eval.as.preview} is to visualize what would happen when running the given code in the R console,
+         interactively. Importantly, however, due to the evaluation inside a function, any error messages and backtraces will differ,
+         and taskCallbacks will not run.
+}
diff --git a/rkward/rbackend/rpackages/rkward/man/rk.old.packages.Rd b/rkward/rbackend/rpackages/rkward/man/rk.old.packages.Rd
index 4211425c7..4d7f2fe84 100644
--- a/rkward/rbackend/rpackages/rkward/man/rk.old.packages.Rd
+++ b/rkward/rbackend/rpackages/rkward/man/rk.old.packages.Rd
@@ -40,7 +40,8 @@ rk.old.packages(
   }
 
 \item{method}{Download method, see \code{\link[utils]{download.file}}.
-    Unused if a non-\code{NULL} \code{available} is supplied.}
+    Unused by \code{old.packages} if a non-\code{NULL} \code{available}
+    is supplied.}
 
 \item{available}{
     an object as returned by \code{\link[utils]{available.packages}}
diff --git a/rkward/windows/rkcommandeditorwindow.cpp b/rkward/windows/rkcommandeditorwindow.cpp
index 887ef5713..634fcade2 100644
--- a/rkward/windows/rkcommandeditorwindow.cpp
+++ b/rkward/windows/rkcommandeditorwindow.cpp
@@ -711,7 +711,7 @@ void RKCommandEditorWindow::initPreviewModes() {
 	    i18n("Preview the script as if it was run in the interactive R Console"),
 	    u".R"_s,
 	    [](const QString &infile, const QString &outdir, const QString & /*preview_id*/) {
-		    auto command = QStringLiteral("rkward:::rk.eval.as.console.preview(%1, %2)\n"
+		    auto command = QStringLiteral("rkward:::rk.eval.as.preview(%1, %2)\n"
 		                                  "rk.show.html(%2)\n");
 		    return command.arg(RObject::rQuote(infile), RObject::rQuote(outdir + u"/output.html"_s));
 	    }});



More information about the rkward-tracker mailing list