Skip to content

Commit

Permalink
Parse the text to detect doc comments and inlines properly in spin() (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
yutannihilation authored and yihui committed Oct 9, 2018
1 parent bcb1204 commit 45eee67
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 9 deletions.
13 changes: 9 additions & 4 deletions R/spin.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#' if you want to use \code{##} to denote documentation, you can use
#' \code{'^##\\\\s*'}.
#' @param inline A regular expression to identify inline R expressions; by
#' default, code of the form \code{((code))} on its own line is treated as an
#' default, code of the form \code{\{\{code\}\}} on its own line is treated as an
#' inline expression.
#' @param comment A pair of regular expressions for the start and end delimiters
#' of comments; the lines between a start and an end delimiter will be
Expand Down Expand Up @@ -64,11 +64,16 @@ spin = function(
# remove comments
if (length(c1)) x = x[-unique(unlist(mapply(seq, c1, c2, SIMPLIFY = FALSE)))]

# remove multiline string literals and symbols (note that this ignores lines with spaces at their
# beginnings, assuming doc and inline regex don't match these lines anyway)
parsed_data = getParseData(parse(text = x, keep.source = TRUE))
is_matchable = seq_along(x) %in% unique(parsed_data[parsed_data$col1 == 1, 'line1'])

p = .fmt.pat[[tolower(format)]]
# turn ((expr)) into inline expressions, e.g. `r expr` or \Sexpr{expr}
if (any(i <- grepl(inline, x))) x[i] = gsub(inline, p[4], x[i])
# turn {{expr}} into inline expressions, e.g. `r expr` or \Sexpr{expr}
if (any(i <- is_matchable & grepl(inline, x))) x[i] = gsub(inline, p[4], x[i])

r = rle(grepl(doc, x) | i) # inline expressions are treated as doc instead of code
r = rle((is_matchable & grepl(doc, x)) | i) # inline expressions are treated as doc instead of code
n = length(r$lengths); txt = vector('list', n); idx = c(0L, cumsum(r$lengths))
p1 = gsub('\\{', '\\\\{', paste0('^', p[1L], '.*', p[2L], '$'))

Expand Down
11 changes: 6 additions & 5 deletions man/spin.Rd

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

26 changes: 26 additions & 0 deletions tests/testit/test-spin.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
library(testit)

spin_w_tempfile = function(...) {
tmp = tempfile(fileext = ".R")
writeLines(c(...), tmp)
spinned = spin(tmp, knit = FALSE)
result = readLines(spinned)
file.remove(c(tmp, spinned))
result
}

assert(
'spin() detects lines for documentation',
identical(spin_w_tempfile("#' test", "1 * 1", "#' test"),
c("test", "", "```{r }", "1 * 1", "```", "", "test")),
# a multiline string literal contains the pattern of doc or inline
identical(spin_w_tempfile("code <- \"", "#' test\""),
c("", "```{r }", "code <- \"", "#' test\"", "```", "")),
identical(spin_w_tempfile("code <- \"", "{{ 1 + 1 }}", "\""),
c("", "```{r }", "code <- \"", "{{ 1 + 1 }}", "\"", "```", "")),
# a multiline symbol contains the pattern of doc or inline
identical(spin_w_tempfile("`", "#' test", "`"),
c("", "```{r }", "`", "#' test", "`", "```", "")),
identical(spin_w_tempfile("`", "{{ 1 + 1 }}", "`"),
c("", "```{r }", "`", "{{ 1 + 1 }}", "`", "```", ""))
)

0 comments on commit 45eee67

Please sign in to comment.