Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Feature Request: box::get_script_path() #239

@GregYannes

Description

@GregYannes

Issue

Per the documentation for box::set_script_path(), we can capture the previous script path when setting it anew:

Value

box::set_script_path returns the previously set script path, or NULL if none was explicitly set.

However, when I try to capture each previous path, I get the following output

# Set new path.
box::set_script_path("C:/Users/gyannes/Documents/Test.R")

# Set another new path and capture old.
test <- box::set_script_path("C:/Users/Public/Public Documents")
test
# [1] "C:/Users/gyannes/Documents"

# Set yet another new path and capture old.
test <- box::set_script_path(".")
test
# [1] "C:/Users/Public"

where the terminal filename (Test.R) or directory name (Public Documents) is "lopped off" each captured path.

Notably, this behavior ends at the root drive, which is not lopped off:

box::set_script_path("C:/Users")

test <- box::set_script_path("C:/")
test
# [1] "C:/"

test <- box::set_script_path(".")
test
# [1] "C:/"

Thus, valuable information can be lost whenever we change a path.

Acknowledgement

After perusing the source code, I see that this behavior is due to the intentional use of dirname(), and it is baked into the script_path_env$value as soon as the script path is set. This feature is doubtless tied to important functionality, so I obviously wouldn't request a massive rewrite.

However, the manual strongly indicates the filepath itself, rather than the path to the parent directory. A slight revision to the manual would greatly improve clarity.

Request

This issue arose while I was hacking together an augmentation for box. I always like to have a get*() for every set*(), so I put together a get_script_path() function in a utility module:

#####
#' @title Get Script Path
#' @description Helper to get the script path last set by
#'   \href{https://rdrr.io/cran/box/man/set_script_path.html}{box::set_script_path()}.
#' @export
#####
#' 
#' @param script_env The global
#'   \href{https://rdrr.io/r/base/environment.html}{environment} of the calling
#'   script.
#' 
#' @return A \code{character} string with the filepath to the calling script, or
#'   \code{NULL} when no script path has previously been set.
#####
get_script_path <- function(script_env = parent.frame(n = 1)) {
  # Capture the original script path by resetting it.
  # * Since 'box' is the only package on which this module relies, and since it
  #   has no 'box::get_script_path()', we must use this workaround.
  original_path <- evalq(
    # For the appropriate side effect, it is prudent to call
    # 'box::set_script_path(NULL)' as a literal command in the calling
    # environment.
    expr = box::set_script_path(NULL),
    envir = script_env
  )
  
  # For existing path, append a "dummy" terminus that will get "lopped off" from
  # the path as soon as it is set:
  #   https://github.com/klmr/box/blob/3d1644b8913657d236130271f340aef0c66fb4b7/R/paths.r#L18
  if(length(original_path) > 0) {
    new_path <- file.path(original_path, "dummy")
  }
  # Otherwise the path is missing ('NULL' or 'character(0)').
  else {
    new_path <- NULL
  }
  
  # Reset the script path to its original.
  on.exit(expr = {eval(
    # For the appropriate side effect, it is necessary for
    # 'box::set_script_path()' to evaluate in the calling environment; yet as if
    # it contained the literal string stored in 'new_path', a variable
    # inaccessible to the calling environment.
    #   'box::set_script_path("original/path/as/literal/string")'
    expr = substitute(box::set_script_path(new_path)),
    envir = script_env
  )})
  
  return(original_path)
}

However, this approach might prove unstable. Would it be possible to provide a box::get_script_path() function, which simply returns the character string currently being used as the script path?

Thanks, as always! — Greg

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions