this.path {this.path} | R Documentation |
Determine Script's Filename
Description
this.path()
returns the
normalized
path of
the script in which it was written.
this.dir()
returns the directory of this.path()
.
Usage
this.path(verbose = getOption("verbose"), original = FALSE,
for.msg = FALSE, contents = FALSE, local = FALSE,
n = 0, envir = parent.frame(n + 1),
matchThisEnv = getOption("topLevelEnvironment"),
srcfile = if (n) sys.parent(n) else 0,
default, else.)
this.dir(verbose = getOption("verbose"), local = FALSE,
n = 0, envir = parent.frame(n + 1),
matchThisEnv = getOption("topLevelEnvironment"),
srcfile = if (n) sys.parent(n) else 0,
default, else.)
Arguments
verbose |
|
original |
|
for.msg |
|
contents |
In ‘Jupyter’, a list of character vectors will be returned, the
contents separated into cells. Otherwise, a character vector will be
returned. If the executing script cannot be determined and You could use
This is intended for logging purposes. This is useful in ‘Rgui’, ‘RStudio’, ‘VSCode’, and ‘Emacs’ when the source document has contents but no path. |
local |
|
n |
the number of additional generations to go back. By default,
|
envir , matchThisEnv |
arguments passed to
|
srcfile |
source file in which to search for a pathname, or an object containing a source file. This includes a source reference, a call, an expression object, or a closure. |
default |
this value is returned if there is no executing script. |
else. |
function to apply if there is an executing script. See
|
Details
this.path()
starts by examining argument srcfile
. It looks at
the bindings filename
and wd
to determine the associated file
path. A source file of class "srcfilecopy"
in which binding
isFile
is FALSE
will be ignored. A source file of class
"srcfilealias"
will use the aliased filename
in determining the
associated path. Filenames such as ""
, "clipboard"
, and
"stdin"
will be ignored since they do not refer to files.
If it does not find a path associated with srcfile
, it will next
examine arguments envir
and matchThisEnv
. Specifically, it
calculates topenv(envir, matchThisEnv)
then
looks for an associated path. It will find a path associated with the top
level environment in two ways:
from a package:box module's namespace
from an attribute
"path"
If it does not find an associated path with envir
and
matchThisEnv
, it will next examine the call stack looking for a source
call; a call to one of these functions:
source()
debugSource
()
in ‘RStudio’box::use()
targets::tar_callr_inner_try()
targets::tar_load_globals()
targets::tar_source()
targets::tar_workspace()
If a source call is
found, the file argument is returned from the function's evaluation
environment. If you have your own source()
-like function that you would
like to be recognized by this.path()
, please use
set.sys.path()
or contact the package maintainer so that it can
be implemented.
If no source call is found up the calling stack, it will next examine the GUI in use. If R is running from:
- a shell, such as the Windows command-line / / Unix terminal
-
then the shell arguments are searched for -f FILE or --file=FILE (the two methods of taking input from FILE) (-f - and --file=- are ignored). The last FILE is extracted and returned. If no arguments of either type are supplied, an error is thrown.
If R is running from a shell under a Unix-alike with -g Tk or --gui=Tk, an error is thrown. ‘Tk’ does not make use of its -f FILE, --file=FILE arguments.
- ‘Rgui’
-
then the source document's filename (the document most recently interacted with) is returned (at the time of evaluation). Please note that minimized documents WILL be included when looking for the most recently used document. It is important to not leave the current document (either by closing the document or interacting with another document) while any calls to
this.path()
have yet to be evaluated in the run selection. If no documents are open or the source document does not exist (not saved anywhere), an error is thrown. - ‘RStudio’
-
then the active document's filename (the document in which the cursor is active) is returned (at the time of evaluation). If the active document is the R console, the source document's filename (the document open in the current tab) is returned (at the time of evaluation). Please note that the source document will NEVER be a document open in another window (with the Show in new window button). Please also note that an active document open in another window can sometimes lose focus and become inactive, thus returning the incorrect path. It is best NOT to not run R code from a document open in another window. It is important to not leave the current tab (either by closing or switching tabs) while any calls to
this.path()
have yet to be evaluated in the run selection. If no documents are open or the source document does not exist (not saved anywhere), an error is thrown. - ‘VSCode’
-
then the source document's filename is returned (at the time of evaluation). It is important to not leave the current tab (either by closing or switching tabs) while any calls to
this.path()
have yet to be evaluated in the run selection. If no documents are open or the source document does not exist (not saved anywhere), an error is thrown. - ‘Jupyter’
-
then the source document's filename is guessed by looking for R notebooks in the initial working directory, then searching the contents of those files for an expression matching the top-level expression. Please be sure to save your notebook before using
this.path()
, or explicitly useset.jupyter.path()
. - ‘Emacs’
-
then the source document's filename is returned (at the time of evaluation). ‘Emacs’ must be running as a server, either by running
(server-start)
(consider adding to your ‘~/.emacs’ file) or typingM-x server-start
. It is important to not leave the current window (either by closing or switching buffers) while any calls tothis.path()
have yet to be evaluated in the run selection. If multiple frames are active,this.path()
will pick the first frame containing the corresponding R session.If multiple ‘Emacs’ sessions are active,
this.path()
will only work in the primary session due to limitations in‘emacsclient’. If you want to run multiple R sessions, it is better to run one ‘Emacs’ session with multiple frames, one R session per frame. Use
M-x make-frame
to make a new frame, orC-x 5 f
to visit a file in a new frame.Additionally, never use
C-c C-b
to send the current buffer to the R process. This copies the buffer contents to a new file which is thensource()
-ed. The source references now point to the wrong file. Instead, useC-x h
to select the entire buffer thenC-c C-r
to evaluate the selection. - ‘AQUA’
-
then the executing script's path cannot be determined. Unlike ‘Rgui’, ‘RStudio’, ‘VSCode’, ‘Jupyter’, and ‘Emacs’, there is currently no way to request the path of an open document. Until such a time that there is a method for requesting the path of an open document, consider using another GUI.
If R is running in another manner, an error is thrown.
If your GUI of choice is not implemented with this.path()
, please
contact the package maintainer so that it can be implemented.
Value
character string.
Argument 'n'
By default, this.path()
will look for a path based on the
srcref
of the call to this.path()
and the environment in which
this.path()
was called. For example:
{ #line 1 "file1.R" fun <- function() this.path::this.path(original = TRUE) fun() } { #line 1 "file2.R" fun() }
Both of these will return "file1.R"
because that is where the call to
this.path()
is written.
But suppose we do not care to know where this.path()
is called, but
instead want to know where fun()
is called. Pass argument n = 1
;
this.path()
will inspect the call and the calling environment one
generation up the stack:
{ #line 1 "file1.R" fun <- function() this.path::this.path(original = TRUE, n = 1) fun() } { #line 1 "file2.R" fun() }
These will return "file1.R"
and "file2.R"
, respectively,
because those are where the calls to fun()
are written.
But now suppose we wish to make a second function that uses fun()
. We
do not care to know where fun()
is called, but instead want to know
where fun2()
is called. Add a formal argument n = 0
to each
function and pass n = n + 1
to each sub-function:
{ #line 1 "file1.R" fun <- function(n = 0) { this.path::this.path(original = TRUE, n = n + 1) } fun() } { #line 1 "file2.R" fun2 <- function(n = 0) fun(n = n + 1) list(fun = fun(), fun2 = fun2()) } { #line 1 "file3.R" fun3 <- function(n = 0) fun2(n = n + 1) list(fun = fun(), fun2 = fun2(), fun3 = fun3()) }
Within each file, all these functions will return the path in which they are
called, regardless of how deep this.path()
is called.
Note
If you need to use this.path()
inside a user profile, please use
with_init.file()
. i.e. instead of writing:
<expr 1> <expr 2> <...>
write this:
this.path::with_init.file({ <expr 1> <expr 2> <...> })
See Also
shFILE()
Examples
FILE1.R <- tempfile(fileext = ".R")
writeLines("writeLines(sQuote(this.path::this.path()))", FILE1.R)
## 'this.path()' works with 'source()'
source(FILE1.R)
## 'this.path()' works with 'sys.source()'
sys.source(FILE1.R, envir = environment())
## 'this.path()' works with 'debugSource()' in 'RStudio'
if (.Platform$GUI == "RStudio")
get("debugSource", "tools:rstudio", inherits = FALSE)(FILE1.R)
## 'this.path()' works with 'testthat::source_file()'
if (requireNamespace("testthat"))
testthat::source_file(FILE1.R, chdir = FALSE, wrap = FALSE)
## 'this.path()' works with 'compiler::loadcmp()'
if (requireNamespace("compiler")) {
FILE2.Rc <- tempfile(fileext = ".Rc")
compiler::cmpfile(FILE1.R, FILE2.Rc)
compiler::loadcmp(FILE2.Rc)
unlink(FILE2.Rc)
}
## 'this.path()' works with 'Rscript'
this.path:::.Rscript(c("--default-packages=NULL", "--vanilla", FILE1.R))
## 'this.path()' also works when 'source()'-ing a URL
## (included tryCatch in case an internet connection is not available)
tryCatch({
source(paste0("https://raw.githubusercontent.com/ArcadeAntics/",
"this.path/main/tests/sys-path-with-urls.R"))
}, condition = this.path:::.cat_condition)
unlink(FILE1.R)