Using rstudioapi to create a new file and insert text

Hi,

I am playing around with the rstudioapi package to try and write a toy function that would take a file name as an argument, create a file with this name, open the file, and insert some code. Here is what I have so far:

open_and_write <- function(path = NULL){
  fs::file_create(path)
  rstudioapi::navigateToFile(path)
  id <- rstudioapi::getSourceEditorContext()$id
  rstudioapi::insertText(c(1,1), '# Here is a sweet comment', id)
}
open_and_write('~/foo.R')

I anticipated that when RStudio navigated to the newly created file (foo.R) in the editor pane, the getActiveDocumentContext() would return the ID for foo.R. But instead, it seems to returns the ID for the script containing open_and_write() function, and it places the comment at the start of that script, and not the new file...What am I doing wrong?

EDIT: So it seems that when I add a Sys.sleep(1) to the code, it works as expected. Is rstudioapi::insertText() just inserting the text too quickly? The working code is:

open_and_write <- function(path = NULL){
  fs::file_create(path)
  rstudioapi::navigateToFile(path)
  Sys.sleep(1)
  id <- rstudioapi::getSourceEditorContext()$id
  rstudioapi::insertText(c(1,1), '# Here is a sweet comment', id)
}

The problem is that, when

rstudioapi::navigateToFile(path)

is called, RStudio does not actually wait until the file has been opened and focused -- rather, it just sends the request to open the file to RStudio, and then continues along.

I agree this is not ideal (and is perhaps worth filing as a bug) but I would agree that the appropriate workaround is to either sleep, or loop and wait until a source editor context is available.

1 Like

Ah I see. So the rstudioapi::getSourceEditorContext() won't be getting the newly opened document context if the request hasn't been processed fast enough (i.e. opened and focused). The Sys.sleep(1) hack works, but I don't know how generalizable it is. The amount of time you need to sleep could vary based on situational context, I think your suggestion of a loop might actually create a more robust approach.

The code below works and I think it should work in most/all situations, regardless of the speed at which the computer/RStudio session opens the file with rstudioapi::navigateToFile(). Basically the while loop waits until the document context changes before getting the new context ID and inserting the text.

open_and_write <- function(path = NULL){
  fs::file_create(path)
  id <- rstudioapi::getSourceEditorContext()$id
  rstudioapi::navigateToFile(path)
  
  while(rstudioapi::getSourceEditorContext()$id == id){
    next()
    Sys.sleep(0.1) # slow down the while loop to avoid over-processing
  }
  id <- rstudioapi::getSourceEditorContext()$id
  rstudioapi::insertText(c(1L,1L), '# Here is a sweet comment', id)
}

Sharing the code in case someone else in the future finds it useful.

1 Like

That's exactly what I was thinking of. :slight_smile: You might also want to insert a short sleep in the while loop; e.g. Sys.sleep(0.1), to avoid a "busy" loop -- otherwise, R could end up chewing more CPU than you might want while waiting for the file to open.

1 Like

Thanks for the suggestion. I have edited the above code to reflect it.