Skip to content

Instantly share code, notes, and snippets.

@sellorm
Created April 15, 2021 20:54
Show Gist options
  • Save sellorm/20525aff669acafb975b7495b8f2066e to your computer and use it in GitHub Desktop.
Save sellorm/20525aff669acafb975b7495b8f2066e to your computer and use it in GitHub Desktop.
Render an Rmarkdown document in the RStudio jobs pane.
render_with_jobs <- function(){
rstudioapi::verifyAvailable()
jobs_file <- tempfile(tmpdir = "/tmp", fileext = ".R")
rmd_to_render <- rstudioapi::selectFile(caption = "Choose an Rmd file...",
filter = "Rmd files (*.Rmd)")
if (is.null(rmd_to_render)){
stop("You must choose an Rmd file to proceed!")
}
cat(paste0('rmarkdown::render("', rmd_to_render, '")'), file = jobs_file)
rstudioapi::jobRunScript(path = jobs_file,
name = basename(rmd_to_render),
workingDir = getwd())
# Wait for 5 seconds so that the tmp file isn't deleted *before* the job
# submission is complete
Sys.sleep(5)
file.remove(jobs_file)
}
@sellorm
Copy link
Author

sellorm commented Apr 15, 2021

This sort of approach is particularly useful for Rmd documents that take a long time to knit.

@sellorm
Copy link
Author

sellorm commented Apr 15, 2021

some improvements from @gadenbuie...

Here's a slight re-write that builds on what you came up with. Running the job in the working directory of the Rmd will more closely match the default knit button behavior. Rather than ask for a file, I assume they want to knit the current document, you can handle that either way. And I think you can get away with deleting the file from within the job. Finally adding a call to viewer() opens the document after running (but in a browser, not the Viewer pane)

render_with_job <- function() {
  rstudioapi::verifyAvailable()

  job_file <- tempfile(fileext = ".R")

  active_doc_ctx <- rstudioapi::getSourceEditorContext()
  rmd_path <- active_doc_ctx$path

  if (identical(rmd_path, "")) {
    rstudioapi::showDialog(
      "Cannot Render Unsaved R Markdown Document",
      "Please save the current document before rendering."
    )
    return(invisible())
  }

  rstudioapi::documentSave(active_doc_ctx$id)

  rmd_path <- normalizePath(rmd_path, mustWork = TRUE)

  cat(
    'res <- rmarkdown::render("', basename(rmd_path), '")\n',
    'unlink("', job_file, '")\n',
    'rstudioapi::viewer(res)',
    sep = "",
    file = job_file
  )

  rstudioapi::jobRunScript(
    path = job_file,
    name = basename(rmd_path),
    workingDir = dirname(rmd_path),
    importEnv = FALSE
  )
} 

@tonycmac
Copy link

tonycmac commented Oct 20, 2022

For what it's worth, just confirmed that the render_with_jobs() function works for rendering Quarto (qmd) files as well. Not a big surprise since it users knitr though :-)

@NevilHopley
Copy link

@sellorm When I run your code from 15 Apr 2021, on a Windows PC running R4.4.1 with RStudio 2024.04.2, I get the error "Error: '\U' used without hex digits in character string C:/Users/myname/AppData/Local/Temp/RtmpAnx41J/file20cc54305c20.R:2:12) Execution halted"
now, job_file = "C:\\Users\\myname\\AppData\\Local\\Temp\\RtmpAnx41J\\file20cc5b2e3d96.R"
and rmd_path = "C:\\Users\\myname\\Documents\\R\\render_with_job.R"
and basename(rmd_path) = "render_with_job.R"
and dirname(rmd_path) = "C:/Users/myname/Documents/R"
I have tried multiple workarounds, and the only one that seems to make this function work, is when I set job_file = "temp_file.R" at the start of the function. So job_file is causing the problem, it seems.
I don't want to hard code in a file name for job_file as that would prevent multiple jobs being run concurrently, that each need their own, unique temporary filename.
I have tried replacing the \\ with / using this code:
path = stringr::str_replace_all(string = job_file, pattern = "\\\\", replacement = "/")
which gives "C:/Users/hop11527/AppData/Local/Temp/RtmpAnx41J/file20cc5b2e3d96.R"
But still the same error is returned.
I am now at a loss for how to resolve this error, without hard-coding in a filename for job_file.
Can anyone help at all?

@sellorm
Copy link
Author

sellorm commented Sep 3, 2024

@NevilHopley I've only ever seen this happen if you have some piece of code using the Windows "C:\Users..." style paths instead of "C:/Users/..." somewhere in your code. The error you're getting specifically highlights '\U' as being the problem, so if there's somewhere in your code where you've typed in "C:\Users...", make sure to swap it with the other slashes and try it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment