Project Templates and .Rprofile


#1

Hello Community!
I really enjoy the new project templates and want to use them for an existing project I am contributing to. https://github.com/benmarwick/rrtools .The project templates idea fit the package philosophy very well,

My issue is that rrtools has a two-step approach to package creation and I cannot get this to fully impliment with the project template approach; I hope to address this issue.

Simply, the rrtools approach is to:

  1. run a function use_compendium(path) from command line of IDE that creates an R package in a given directory; then spawn a new Rstudio session for the package.
  2. within the new Rstudio session run additional functions to define the project (e.g. use_github(x,y), use_travis(x,y,z), etc…).

I want to define these parameters (x,y,z) as options in the project template and have them help control project setup in the newly created package session.

The issue is that the project template can create the package and spawn a new Rstudio session for that package, but cannot then execute the subsequent functions to further setup the package. In your examples for templates, I can write the INDEX file to the project/package directory and cat() the options from the template UI, but I have no means of executing functions based on those options.

One approach I am working towards is to have the function bound to project template (e.g. hello_world()) write .Rprofile instead INDEX and use the options from the template UI as arguments in the subsequent functions:

if(isTRUE(dots[["checkInput_Travis"]])){ 
     use_travis(dots[["selectInput_TravisOptions"]]) 
}

I am unable to fully test this at the moment, but I think it will (may?) work.

Questions:

  1. Is there a better way to do this?
  2. If the .Rprofile ideas does work, is there a way to rename/delete .Rprofile after it is executed the first time the project is loaded?

Thank you for any clarity or help that the community can provide!
Matt


#2

Hi Matt, here are a couple ideas:

  1. I think your .Rprofile approach is indeed the best way to accomplish what you want. You may simply be able to remove it (using file.remove()) from within .Rprofile itself, because R has already parsed it and may not have a handle open to it any more. If that doesn’t work, you can use addTaskCallback to tell R to remove the .Rprofile after the console prompt appears.
  1. If the .Rprofile approach winds up being finicky, another thing you could do would be to prime the new session by launching R itself in the project’s directory using a synchronous system() command.

Finally, all of this presumes that (for some reason) it is necessary to run use_travis etc. in a new R session established in the directory. I’m not very familiar with rrtools, but it might be possible to do what you want just by running a setwd() to the new directory inside your project template directory, just prior to running the project setup commands.

Jonathan.


#3

Hello Jonathan, Thank you for the speedy reply and excellent thoughts. I will move forward with the .Rprofile method this evening and see if those solutions work. Your final though about using setwd() is ultimately preferable, but I have not yet tried it. I’ll give it a whirl too and report back to update the thread.
Best!
MH


#4

About the Rprofile approach

You can have your .Rprofile script looks for an external file at the end and sources it if available. That way you don’t have to worry about messing with you existing settings. Something like:

~/.Rprofile:

## My startup settings here
[...]

## One time startup settings
if ((file.exists("/tmp/project_init.R")) source("/tmp/project_init.R")

with /tmp/project_init.R:

if (Sys.getenv("RSTUDIO") == "1") local({
  on.exit(file.remove("/tmp/project_init.R"))
  ## Setup here
  ## ...
})

Possibly overkill, but this can be simplified by using the startup package in ~/.Rprofile as:

startup::startup()

then just add a ~/.Rprofile.d/rstudio=TRUE/tmp/project_init.R:

local({
  on.exit(file.remove("~/.Rprofile.d/rstudio=TRUE/tmp/project_init.R"))
  ## Setup here
  ## ...
})

(In next startup, it’ll be possible to do file.remove(startup::current_script())).


#5

About the system() approach:

To evaluate R code in a background session, you can setup a PSOCK worker an use parallel::clusterEvalQ(), or you could use futures (my last shameless self-promotion ;))

library("future")
# Evalute in background R session
plan(cluster, workers = 1L)
f <- future({
  ## Setup here...
  [...]
  TRUE
})
# Make sure it completes
v <- value(f)
stopifnot(isTRUE(v))