diff --git a/.lintr b/.lintr index 34473d27..0a0bb22f 100644 --- a/.lintr +++ b/.lintr @@ -1,5 +1,6 @@ linters: linters_with_defaults( line_length_linter = line_length_linter(120), cyclocomp_linter = NULL, - object_usage_linter = NULL + object_usage_linter = NULL, + indentation_linter = NULL ) diff --git a/DESCRIPTION b/DESCRIPTION index 99ec742e..7c0ff475 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -31,6 +31,7 @@ Imports: zip (>= 1.1.0) Suggests: DT (>= 0.13), + formatR (>= 1.5), ggplot2 (>= 3.4.0), lattice (>= 0.18-4), png, @@ -44,8 +45,8 @@ RdMacros: Config/Needs/verdepcheck: rstudio/bslib, mllg/checkmate, rstudio/htmltools, yihui/knitr, r-lib/lifecycle, r-lib/R6, rstudio/rmarkdown, rstudio/shiny, dreamRs/shinyWidgets, - yaml=vubiostat/r-yaml, r-lib/zip, davidgohel/flextable, rstudio/DT, - tidyverse/ggplot2, deepayan/lattice, cran/png, + yaml=vubiostat/r-yaml, r-lib/zip, davidgohel/flextable, rstudio/DT, + yihui/formatR, tidyverse/ggplot2, deepayan/lattice, cran/png, insightsengineering/rtables, r-lib/testthat, rstudio/tinytex Config/Needs/website: insightsengineering/nesttemplate Encoding: UTF-8 diff --git a/NEWS.md b/NEWS.md index a210d1ef..54b61fff 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,8 @@ * `add_card_button_srv` allows to specify `card_fun` with `label` parameter for card's title & content customization. +* Supports automatic `Rcode` formatting using the suggested `formatR` package in reports. + # teal.reporter 0.2.1 ### Miscellaneous diff --git a/R/DownloadModule.R b/R/DownloadModule.R index f3f080a8..147b5269 100644 --- a/R/DownloadModule.R +++ b/R/DownloadModule.R @@ -33,11 +33,16 @@ download_report_button_ui <- function(id) { #' For more details see the vignette: `vignette("simpleReporter", "teal.reporter")`. #' @param id `character(1)` this `shiny` module's id. #' @param reporter [`Reporter`] instance. +#' @param global_knitr `list` a of `knitr` parameters (passed to `knitr::opts_chunk$set`) +#' for customizing the rendering process. #' @inheritParams reporter_download_inputs #' @return `shiny::moduleServer` +#' @details `r global_knitr_details()` +#' #' @export download_report_button_srv <- function(id, reporter, + global_knitr = getOption("teal.reporter.global_knitr"), rmd_output = c( "html" = "html_document", "pdf" = "pdf_document", "powerpoint" = "powerpoint_presentation", "word" = "word_document" @@ -48,6 +53,7 @@ download_report_button_srv <- function(id, toc = FALSE )) { checkmate::assert_class(reporter, "Reporter") + checkmate::assert_subset(names(global_knitr), names(knitr::opts_chunk$get())) checkmate::assert_subset( rmd_output, c( @@ -134,8 +140,7 @@ download_report_button_srv <- function(id, shiny::showNotification("Rendering and Downloading the document.") input_list <- lapply(names(rmd_yaml_args), function(x) input[[x]]) names(input_list) <- names(rmd_yaml_args) - global_knitr <- list() - if (is.logical(input$showrcode)) global_knitr <- list(echo = input$showrcode) + if (is.logical(input$showrcode)) global_knitr[["echo"]] <- input$showrcode report_render_and_compress(reporter, input_list, global_knitr, file) }, contentType = "application/zip" diff --git a/R/Previewer.R b/R/Previewer.R index 7ccaf2ff..41a3d913 100644 --- a/R/Previewer.R +++ b/R/Previewer.R @@ -31,10 +31,15 @@ reporter_previewer_ui <- function(id) { #' For more details see the vignette: `vignette("previewerReporter", "teal.reporter")`. #' @param id `character(1)` this `shiny` module's id. #' @param reporter `Reporter` instance +#' @param global_knitr `list` a of `knitr` parameters (passed to `knitr::opts_chunk$set`) +#' for customizing the rendering process. #' @inheritParams reporter_download_inputs +#' @details `r global_knitr_details()` +#' #' @export reporter_previewer_srv <- function(id, reporter, + global_knitr = getOption("teal.reporter.global_knitr"), rmd_output = c( "html" = "html_document", "pdf" = "pdf_document", "powerpoint" = "powerpoint_presentation", @@ -45,6 +50,7 @@ reporter_previewer_srv <- function(id, toc = FALSE )) { checkmate::assert_class(reporter, "Reporter") + checkmate::assert_subset(names(global_knitr), names(knitr::opts_chunk$get())) checkmate::assert_subset( rmd_output, c( @@ -179,8 +185,7 @@ reporter_previewer_srv <- function(id, shiny::showNotification("Rendering and Downloading the document.") input_list <- lapply(names(rmd_yaml_args), function(x) input[[x]]) names(input_list) <- names(rmd_yaml_args) - global_knitr <- list() - if (is.logical(input$showrcode)) global_knitr <- list(echo = input$showrcode) + if (is.logical(input$showrcode)) global_knitr[["echo"]] <- input$showrcode report_render_and_compress(reporter, input_list, global_knitr, file) }, contentType = "application/zip" diff --git a/R/Renderer.R b/R/Renderer.R index 1ce2be5b..f086cc82 100644 --- a/R/Renderer.R +++ b/R/Renderer.R @@ -22,14 +22,16 @@ Renderer <- R6::R6Class( # nolint: object_name_linter. #' @description getting the `Rmd` text which could be easily rendered later. #' #' @param blocks `list` of `c("TextBlock", "PictureBlock", "NewpageBlock")` objects. - #' @param yaml_header `character` a `rmarkdown` `yaml` header. - #' @param global_knitr `list` a global `knitr` parameters, like echo. - #' But if local parameter is set it will have priority. - #' Defaults to empty `list()`. + #' @param yaml_header `character` an `rmarkdown` `yaml` header. + #' @param global_knitr `list` a of `knitr` parameters (passed to `knitr::opts_chunk$set`) + #' for customizing the rendering process. + #' @details `r global_knitr_details()` #' #' @return `character` a `Rmd` text (`yaml` header + body), ready to be rendered. - renderRmd = function(blocks, yaml_header, global_knitr = list()) { + renderRmd = function(blocks, yaml_header, global_knitr = getOption("teal.reporter.global_knitr")) { checkmate::assert_list(blocks, c("TextBlock", "PictureBlock", "NewpageBlock", "TableBlock", "RcodeBlock")) + checkmate::assert_subset(names(global_knitr), names(knitr::opts_chunk$get())) + if (missing(yaml_header)) { yaml_header <- md_header(yaml::as.yaml(list(title = "Report"))) } @@ -84,13 +86,13 @@ Renderer <- R6::R6Class( # nolint: object_name_linter. #' #' @param blocks `list` of `c("TextBlock", "PictureBlock", "NewpageBlock")` objects. #' @param yaml_header `character` an `rmarkdown` `yaml` header. - #' @param global_knitr `list` a global `knitr` parameters, like echo. - #' But if local parameter is set it will have priority. - #' Defaults to empty `list()`. - #' @param ... `rmarkdown::render` arguments, `input` and `output_dir` should not be updated.z + #' @param global_knitr `list` a of `knitr` parameters (passed to `knitr::opts_chunk$set`) + #' for customizing the rendering process. + #' @param ... `rmarkdown::render` arguments, `input` and `output_dir` should not be updated. + #' @details `r global_knitr_details()` #' #' @return `character` path to the output - render = function(blocks, yaml_header, global_knitr = list(), ...) { + render = function(blocks, yaml_header, global_knitr = getOption("teal.reporter.global_knitr"), ...) { args <- list(...) input_path <- self$renderRmd(blocks, yaml_header, global_knitr) args <- append(args, list( diff --git a/R/ReportCard.R b/R/ReportCard.R index 37f902bf..49352409 100644 --- a/R/ReportCard.R +++ b/R/ReportCard.R @@ -60,7 +60,7 @@ ReportCard <- R6::R6Class( # nolint: object_name_linter. self$append_content(TextBlock$new(text, style)) invisible(self) }, - #' @description Appends a `rmarkdown` R chunk to this `ReportCard`. + #' @description Appends an `rmarkdown` R chunk to this `ReportCard`. #' #' @param text (`character(0)` or `character(1)`) the text #' @param ... any `rmarkdown` R chunk parameter and its value. diff --git a/R/SimpleReporter.R b/R/SimpleReporter.R index a5f0d1bb..6766fab9 100644 --- a/R/SimpleReporter.R +++ b/R/SimpleReporter.R @@ -46,12 +46,16 @@ simple_reporter_ui <- function(id) { #' @param reporter [`Reporter`] instance. #' @param card_fun `function` which returns a [`ReportCard`] instance, #' the function has a `card` argument and an optional `comment` argument. +#' @param global_knitr `list` a global `knitr` parameters for customizing the rendering process. #' @inheritParams reporter_download_inputs +#' @details `r global_knitr_details()` +#' #' @return `shiny::moduleServer` #' @export simple_reporter_srv <- function(id, reporter, card_fun, + global_knitr = getOption("teal.reporter.global_knitr"), rmd_output = c( "html" = "html_document", "pdf" = "pdf_document", "powerpoint" = "powerpoint_presentation", "word" = "word_document" @@ -68,6 +72,7 @@ simple_reporter_srv <- function(id, download_report_button_srv( "download_button_simple", reporter = reporter, + global_knitr = global_knitr, rmd_output = rmd_output, rmd_yaml_args = rmd_yaml_args ) diff --git a/R/utils.R b/R/utils.R index 59064a22..c9b10403 100644 --- a/R/utils.R +++ b/R/utils.R @@ -277,3 +277,21 @@ split_text_block <- function(x, n) { ind <- rep(1:nblocks, each = n)[seq_along(lines)] unname(lapply(split(lines, ind), paste, collapse = "\n")) } + +#' Retrieve text details for global_knitr options +#' This function returns a character string describing the default settings for the global_knitr options. +#' @noRd +#' +#' @keywords internal +global_knitr_details <- function() { + paste0( + c( + " To access the default values for the `global_knitr` parameter,", + " use `getOption('teal.reporter.global_knitr')`. These defaults include:", + " - `echo = TRUE`", + " - `tidy.opts = list(width.cutoff = 60)`", + " - `tidy = TRUE` if `formatR` package is installed, `FALSE` otherwise" + ), + collapse = "\n" + ) +} diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 00000000..61c594fc --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,22 @@ +.onLoad <- function(libname, pkgname) { + op <- options() + default_global_knitr <- list(teal.reporter.global_knitr = list( + echo = TRUE, + tidy.opts = list(width.cutoff = 60), + tidy = requireNamespace("formatR", quietly = TRUE) + )) + + if (!("teal.reporter.global_knitr" %in% names(op))) { + options(default_global_knitr) + } + + invisible() +} + +.onAttach <- function(libname, pkgname) { + packageStartupMessage( + if (!requireNamespace("formatR", quietly = TRUE)) { + "For better code formatting, consider installing the formatR package." + } + ) +} diff --git a/man/Renderer.Rd b/man/Renderer.Rd index e2e2610e..990d95c2 100644 --- a/man/Renderer.Rd +++ b/man/Renderer.Rd @@ -53,7 +53,11 @@ Finalizes a \code{Renderer} object. \subsection{Method \code{renderRmd()}}{ getting the \code{Rmd} text which could be easily rendered later. \subsection{Usage}{ -\if{html}{\out{