Skip to content

Commit

Permalink
Simplify escape_examples() (#986)
Browse files Browse the repository at this point in the history
Fixes #967
  • Loading branch information
hadley committed Nov 21, 2019
1 parent d9fba9b commit 2a19c8b
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 69 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# roxygen2 (development version)

* Example escaping has been considerably simplified (#967), and is now
documented in `escape_example()`.

* Markdown tables with cells that contain multiple elements (e.g. text and code)
are now rendered correctly (#985).

Expand Down
62 changes: 38 additions & 24 deletions R/rd-examples.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,43 @@ format.rd_section_examples <- function(x, ...) {
rd_macro(x$type, value, space = TRUE)
}

# We take out the \dontshow{} etc. commands, because these should be
# left as is, to allow the user to escape braces for example:
# #' @examples
# #' \\dontshow{ \{ }
# #' # Hidden!
# #' \\dontshow{ \} }
#
# Otherwise, it works like escape, but unescapes special rd example commands.
# Also unescapes quotes because they must already be in strings and hence
# don't need an additional layer of quoting.
#' Escape examples
#'
#' This documentation topic is used primarily for testing and to record
#' our understanding of the `\example{}` escaping rules.
#'
#' @keywords internal
#' @examples
#' # The only thing that must be escaped in examples is Rd comments:
#' 100 %% 30
#' # even if they are in strings
#' "50%"
#'
#' # Otherwise, backslashes and braces can be left as is
#' "\""
#' "{"
#' # It looks like you could use Rd tags in comments, but these are
#' # not actually parsed
#' 1 # \link{mean}
#'
#' # The only place that a backslash can occur in R code is as part of
#' # an infix operator or in a non-syntactic name. If you do either of those
#' # things, you'll need to escape it yourself.
#' `%\\\\%` <- function(x, y) x + y
#' 10 %\\% 20
#'
#' # You must escape braces if they are unbalanced, which typically
#' # only occurs in \dontshow{}:
#' \dontshow{if (FALSE) \{ }
#' print("Hello")
#' \dontshow{ \} }
#'
#' # Otherwise, you _can_ escape them, but there's little point.
#' # The following two lines are equivalent
#' f <- function() { NULL }
#' f <- function() \{ NULL \}
escape_examples <- function(x) {
x <- paste(x, collapse = "\n")
ex_tags <- c("\\dontshow", "\\dontrun", "\\donttest", "\\testonly")
rd_tags <- find_fragile_rd_tags(x, ex_tags)
x <- x0 <- protect_rd_tags(x, rd_tags)

attr(x, "roxygen-markdown-subst") <- NULL
x <- gsub("\\", "\\\\", x, fixed = TRUE, useBytes = TRUE)
x <- gsub("\\\\dont", "\\dont", x, fixed = TRUE)
x <- gsub("\\\\'", "\\'", x, fixed = TRUE)
x <- gsub('\\\\"', '\\"', x, fixed = TRUE)

x1 <- rd(unescape_rd_for_md(x, x0))
x2 <- gsub("%", "\\%", x1, fixed = TRUE, useBytes = TRUE)
rd(x2)
x <- paste0(x, collapse = "\n")
x <- gsub("%", "\\%", x, fixed = TRUE, useBytes = TRUE)
rd(x)
}
43 changes: 43 additions & 0 deletions man/escape_examples.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 3 additions & 45 deletions tests/testthat/test-rd-examples.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,54 +90,12 @@ test_that("% in @examples escaped before matching braces test (#213)", {

# escapes ------------------------------------------------------------------

test_that("% and \\ in @example escaped", {
expect_equal(escape_examples("x %*% y # \\x"), rd("x \\%*\\% y # \\\\x"))
})

test_that("escapes within strings are not double escaped", {
test_that("only % escaped in @examples", {
expect_equal(escape_examples("x %*% y"), rd("x \\%*\\% y"))
expect_equal(escape_examples("# \\x"), rd("# \\x"))
expect_equal(escape_examples("'34.00\\'"), rd("'34.00\\'"))
})

test_that("\\dontrun etc. is not escaped much #1", {
expect_equal(escape_examples("\\dontrun{x <- 1}"), rd("\\dontrun{x <- 1}"))

expect_equal(
escape_examples("\\dontrun{ \\{ x <- 1 \\} }"),
rd("\\dontrun{ \\{ x <- 1 \\} }")
)
})

test_that("\\dontrun etc. is not escaped much #2", {
out <- roc_proc_text(rd_roclet(), "
#' @name a
#' @title a
#' @examples
#' \\dontshow{ \\{ }
#' # Hidden!
#' \\dontshow{ \\} }
NULL")[[1]]

verify_output(test_path("test-rd-examples-dontrun-escape.txt"), {
out$get_section("examples")
})
})

test_that("but % is still escaped in \\dontrun", {
out <- roc_proc_text(rd_roclet(), "
#' Title
#' @examples
#' mtcars %>% identity()
#'
#' \\dontrun{
#' mtcars %>% identity()
#' }
foo <- function() {}")[[1]]

verify_output(test_path("test-rd-examples-dontrun-escape-2.txt"), {
out$get_section("examples")
})
})

test_that("multi-line macros in @example", {
# https://github.com/r-lib/roxygen2/issues/974
out <- roxygen2:::roc_proc_text(roxygen2:::rd_roclet(), "
Expand Down

0 comments on commit 2a19c8b

Please sign in to comment.