#' Extract chunks from Rmd files (knitr::purl) and source them #' #' @param fileRmd Rmd file to #' @param tmpFolder Folder storing the script containing extracted chunks #' @param force.eval Force execution of chunks with parameter eval=FALSE RunRmdChunks <- function(fileRmd, tmpFolder = "../tmp", force.eval = TRUE, chunkIgnore = getChunkIgnore()) { dir.create(tmpFolder, showWarnings = FALSE) output <- file.path(tmpFolder, gsub("\\.Rmd", "\\.R", basename(fileRmd), ignore.case = TRUE)) knitr::purl(fileRmd, output = output, quiet = TRUE) sTxt <- readLines(output) if (force.eval) { sectionLines <- grep("^## ----", sTxt) chunkIgnore <- chunkIgnore[[basename(fileRmd)]] if (!is.null(chunkIgnore)) { regexChunk <- sprintf("(?!(%s))", paste(chunkIgnore, collapse = "|")) } else { regexChunk <- "" } chunksEvalStart <- grep(paste0("^## ----", regexChunk, ".*eval=F"), sTxt, ignore.case=TRUE, perl = TRUE) if (length(chunksEvalStart) > 0) { if (sectionLines[length(sectionLines)] == chunksEvalStart[length(chunksEvalStart)]) { lastEvalStart <- length(chunksEvalStart) - 1 } else { lastEvalStart <- length(chunksEvalStart) } # Search for end lines of eval=F chunks chunksEvalEnd <- sectionLines[sapply(chunksEvalStart[1:lastEvalStart], function(x) {which(sectionLines == x)}) + 1] - 1 if (lastEvalStart) { # Add last line if last chunk is eval=FALSE chunksEvalEnd <- c(chunksEvalEnd, length(sTxt)) } chunksEvalStart <- chunksEvalStart + 1 # Chunks begin one line after the section comment for (i in 1:length(chunksEvalStart)) { # Remove comments on eval=F chunk lines sTxt[chunksEvalStart[i]:chunksEvalEnd[i]] <- gsub(pattern = "^## ", replace = "", x = sTxt[chunksEvalStart[i]:chunksEvalEnd[i]]) } } } # Remove line of code displaying data removeFromGrep <- function(pattern, x) { i <- grep(pattern, x) if (length(i) > 0) { x <- x[-i] } return(x) } sTxt <- removeFromGrep("^summary\\(.*\\)$", sTxt) sTxt <- removeFromGrep("^str\\(.*\\)$", sTxt) # Switch echo off for some functions sTxt <- gsub("trace\\s?=\\s?[0-9]+", "trace = 0", sTxt) # Add parameters to example calls exLines <- grep("^example\\(.*\\)", sTxt) sTxt[exLines] <- paste0(substr(sTxt[exLines], 1, nchar(sTxt[exLines]) - 1), ", echo = FALSE, verbose = FALSE, ask = FALSE)") # Remove question "Hit to see next plot" sTxt <- c("par(ask=F)", sTxt) # Write the transformed script writeLines(sTxt, output) # Silently run the chunks invisible(capture.output(suppressMessages(suppressWarnings(source(output))), type = "output")) return(TRUE) } #' Extract chunks from vignette and source them #' #' @param vignette Name of the vignette #' @param tmpFolder Folder storing the script containing extracted chunks #' @param force.eval Force execution of chunks with parameter eval=FALSE #' #' @return TRUE if succeed. RunVignetteChunks <- function(vignette, tmpFolder = "../tmp", force.eval = TRUE) { if (file.exists(sprintf("../../vignettes/%s.Rmd", vignette))) { # testthat context in development environnement RunRmdChunks(sprintf("../../vignettes/%s.Rmd", vignette), tmpFolder = tmpFolder, force.eval =force.eval, chunkIgnore = getChunkIgnore("../../.vignettechunkignore")) } else if (file.exists(sprintf("vignettes/%s.Rmd", vignette))) { # context in direct run in development environnement RunRmdChunks(sprintf("vignettes/%s.Rmd", vignette), tmpFolder = tmpFolder, force.eval =force.eval, chunkIgnore = getChunkIgnore(".vignettechunkignore")) } else { # R CMD check context in package environnement RunRmdChunks(system.file(sprintf("doc/%s.Rmd", vignette), package = "airGR"), tmpFolder = tmpFolder, force.eval =force.eval, chunkIgnore = getChunkIgnore(".vignettechunkignore")) } return(TRUE) } #' Test if conversion from Q in mm per day into Q in L/s is good in BasinObs #' #' @param BasinObs A dataframe containing columns Qmm and Qls #' @param BasinArea Area of the basin in km2 #' @param tolerance See ?all.equal #' #' @return TestQmmQlsConversion <- function(BasinObs, BasinArea, tolerance = 1E-7) { Conversion <- BasinArea * 1000^2 / 1000 * 1000 # km2 -> m2, mm -> m and m3 -> L Conversion <- Conversion / 86400 # Day -> seconds notNA <- which(!is.na(BasinObs$Qmm)) expect_equal(BasinObs$Qmm[notNA] * Conversion, BasinObs$Qls[notNA], tolerance = tolerance) } #' Read vignettechunkignore file #' #' @param chunkIgnoreFile path to the file #' #' @return [list] with one item by vignette containing the chunk id to ignore #' getChunkIgnore <- function(chunkIgnoreFile = "../../.vignettechunkignore") { if (file.exists(chunkIgnoreFile)) { message(".vignettechunkignore file found") chunkIgnore <- read.table(file = chunkIgnoreFile, sep = " ", header = FALSE, col.names = c("vignette", "chunk"), stringsAsFactors = FALSE) chunkIgnore <- lapply(setNames(nm = unique(chunkIgnore$vignette)), function(x) { chunkIgnore$chunk[chunkIgnore$vignette == x] }) } else { message("No .vignettechunkignore file found") chunkIgnore <- list() } return(chunkIgnore) }