FILE.R <- tempfile(fileext = ".R")
this.path:::.writeCode({
this.path::sys.path(verbose = TRUE)
try(this.path::env.path(verbose = TRUE))
this.path::src.path(verbose = TRUE)
this.path::this.path(verbose = TRUE)
}, FILE.R)
## here we have a source-like function, suppose this
## function is in a package for which you have write permission
sourcelike <- function (file, envir = parent.frame())
{
ofile <- file
file <- set.sys.path(file, Function = "sourcelike")
lines <- readLines(file, warn = FALSE)
filename <- sys.path(local = TRUE, for.msg = TRUE)
isFile <- !is.na(filename)
if (isFile) {
timestamp <- file.mtime(filename)[1]
## in case 'ofile' is a URL pathname / / 'unz' connection
if (is.na(timestamp))
timestamp <- Sys.time()
}
else {
filename <- if (is.character(ofile)) ofile else ""
timestamp <- Sys.time()
}
srcfile <- srcfilecopy(filename, lines, timestamp, isFile)
set.src.path(srcfile)
exprs <- parse(text = lines, srcfile = srcfile, keep.source = FALSE)
invisible(source.exprs(exprs, evaluated = TRUE, envir = envir))
}
sourcelike(FILE.R)
sourcelike(conn <- file(FILE.R)); close(conn)
## here we have another source-like function, suppose this function
## is in a foreign package for which you do not have write permission
sourcelike2 <- function (pathname, envir = globalenv())
{
if (!(is.character(pathname) && file.exists(pathname)))
stop(gettextf("'%s' is not an existing file",
pathname, domain = "R-base"))
envir <- as.environment(envir)
lines <- readLines(pathname, warn = FALSE)
srcfile <- srcfilecopy(pathname, lines, isFile = TRUE)
exprs <- parse(text = lines, srcfile = srcfile, keep.source = FALSE)
invisible(source.exprs(exprs, evaluated = TRUE, envir = envir))
}
## the above function is similar to sys.source(), and it
## expects a character string referring to an existing file
##
## with the following, you should be able
## to use 'sys.path()' within 'FILE.R':
wrap.source(sourcelike2(FILE.R), path.only = TRUE)
# ## with R >= 4.1.0, use the forward pipe operator '|>' to
# ## make calls to 'wrap.source' more intuitive:
# sourcelike2(FILE.R) |> wrap.source(path.only = TRUE)
## 'wrap.source' can recognize arguments by name, so they
## do not need to appear in the same order as the formals
wrap.source(sourcelike2(envir = new.env(), pathname = FILE.R),
path.only = TRUE)
## it it much easier to define a new function to do this
sourcelike3 <- function (...)
wrap.source(sourcelike2(...), path.only = TRUE)
## the same as before
sourcelike3(FILE.R)
## however, this is preferable:
sourcelike4 <- function (pathname, ...)
{
## pathname is now normalized
pathname <- set.sys.path(pathname, path.only = TRUE)
sourcelike2(pathname = pathname, ...)
}
sourcelike4(FILE.R)
## perhaps you wish to run several scripts in the same function
fun <- function (paths, ...)
{
for (pathname in paths) {
pathname <- set.sys.path(pathname, path.only = TRUE)
sourcelike2(pathname = pathname, ...)
unset.sys.path(pathname)
}
}
## here we have a source-like function which modularizes its code
sourcelike5 <- function (file)
{
ofile <- file
file <- set.sys.path(file, Function = "sourcelike5")
lines <- readLines(file, warn = FALSE)
filename <- sys.path(local = TRUE, for.msg = TRUE)
isFile <- !is.na(filename)
if (isFile) {
timestamp <- file.mtime(filename)[1]
## in case 'ofile' is a URL pathname / / 'unz' connection
if (is.na(timestamp))
timestamp <- Sys.time()
}
else {
filename <- if (is.character(ofile)) ofile else ""
timestamp <- Sys.time()
}
srcfile <- srcfilecopy(filename, lines, timestamp, isFile)
set.src.path(srcfile)
envir <- new.env(hash = TRUE, parent = .BaseNamespaceEnv)
envir$.packageName <- filename
oopt <- options(topLevelEnvironment = envir)
on.exit(options(oopt))
set.env.path(envir)
exprs <- parse(text = lines, srcfile = srcfile, keep.source = FALSE)
source.exprs(exprs, evaluated = TRUE, envir = envir)
envir
}
sourcelike5(FILE.R)
## the code can be made much simpler in some cases
sourcelike6 <- function (file)
{
## we expect a character string refering to a file
ofile <- file
filename <- set.sys.path(file, path.only = TRUE, ignore.all = TRUE,
Function = "sourcelike6")
lines <- readLines(filename, warn = FALSE)
timestamp <- file.mtime(filename)[1]
srcfile <- srcfilecopy(filename, lines, timestamp, isFile = TRUE)
set.src.path(srcfile)
envir <- new.env(hash = TRUE, parent = .BaseNamespaceEnv)
envir$.packageName <- filename
oopt <- options(topLevelEnvironment = envir)
on.exit(options(oopt))
set.env.path(envir)
exprs <- parse(text = lines, srcfile = srcfile, keep.source = FALSE)
source.exprs(exprs, evaluated = TRUE, envir = envir)
envir
}
sourcelike6(FILE.R)
unlink(FILE.R)
Run the code above in your browser using DataLab