1

Short: When inside an R library, how do you get the path of the original file calling the library?

Long: I am building a library for creating ggplots according to my organization's style. Currently, to apply the style one just needs to add + mypackage::addstyle to the code for a plot. These plots later end up on slides, and we often forget where we put the script that made it. In order to aid in reproducible research, I would like to add a caption to each figure that states where the plot came from. E.g. W:/Important Project/script27.R

There are multiple ways to get the path of the script inside of the script. For example, rstudioapi::getActiveDocumentContext()$path. However, when I embed those commands inside I get the library I get W:/mypackage/R/style.R, not W:/Important Project/script27.R.

yakzo
  • 337
  • 3
  • 8
  • 1
    Your attempt to use `rstudioapi::getActiveDocumentContext` will not work for anybody not using RStudio. I don't know if that is your intent, or how many like me do not use RStudio regularly. – r2evans Feb 26 '21 at 19:19
  • If you just type commands on the console or run then in RStudio without `source()` the commands don't actually have to be from a script file at all. You can just copy/paste code. Code doesn't always have a source. (Even an RStudio editor window might not have been saved yet and doesn't have a path). This really isn't a very practical thing to accomplish. Is there a general pipeline you are using to run this code that's more controlled? – MrFlick Feb 26 '21 at 19:24
  • @MyFlick Could you suggest an alternative pipeline? I tried teunbrand's suggestion and I just got "console", presumably for the reading you mention. – yakzo Feb 28 '21 at 00:04

1 Answers1

0

I asked a similar question some time ago. I ended up settling on this function:

get_current_document <- function() {
  
  if (interactive()) {
    
    if (rstudioapi::isAvailable()) {
      
      script <- rstudioapi::getActiveDocumentContext()
      
      if (nchar(script$path) == 0) {
        script <- script$id
      } else {
        script <- script$path
      }
      
    } else {
      
      script <- "#console"
      
    }
    
    script <- gsub("^#console$", "console", script)
    
  } else {
    
    script <- as.character(sys.call(1))[2]
    
  }
  
  return(script)
}

Which in your case would work like this:

library(ggplot2)
ggplot(mtcars, aes(wt, mpg)) +
  geom_point() +
  labs(caption = get_current_document())

enter image description here

However, the function isn't robust against all types of cases. I know that the testthat and reprex packages create temporary R sessions that the function isn't able to locate. I'd also love to know a better way.

teunbrand
  • 33,645
  • 4
  • 37
  • 63