Skip to content

Commit

Permalink
make spin() work again with input that can't be parsed as R code
Browse files Browse the repository at this point in the history
  • Loading branch information
yihui committed Mar 28, 2024
1 parent 76142a2 commit 74bcff8
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 5 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: knitr
Type: Package
Title: A General-Purpose Package for Dynamic Report Generation in R
Version: 1.45.16
Version: 1.45.17
Authors@R: c(
person("Yihui", "Xie", role = c("aut", "cre"), email = "[email protected]", comment = c(ORCID = "0000-0003-0645-5666")),
person("Abhraneel", "Sarma", role = "ctb"),
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

## BUG FIXES

- `spin()` stopped working with input that cannot be parsed as R code due to #1605. Now it works again (thanks, @Hemken, #1773).

- `write_bib()` generated empty entries for packages without URLs (thanks, @bastistician, #2304).

- The `family` argument was not passed to the `pdf` device (thanks, @sebkopf, rstudio/rmarkdown#2526).
Expand Down
15 changes: 11 additions & 4 deletions R/spin.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,24 @@ spin = function(

# 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'])
is_matchable = function(x) {
# if code can't be parsed, assume all lines are matchable
p = tryCatch(parse(text = x, keep.source = TRUE), error = function(e) NULL)
n = length(x)
if (is.null(p)) return(rep(TRUE, n))
d = getParseData(p)
seq_len(n) %in% d[d$col1 == 1, 'line1']
}
matchable = is_matchable(x)

# .Rmd/.qmd need to be treated specially
is_md = grepl('^[Rq]md$', format)
p = if (is_md) .fmt.rmd(x) else .fmt.pat[[tolower(format)]]

# 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])
if (any(i <- matchable & grepl(inline, x))) x[i] = gsub(inline, p[4], x[i])

r = rle((is_matchable & grepl(doc, x)) | i) # inline expressions are treated as doc instead of code
r = rle((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))

for (i in seq_len(n)) {
Expand Down

0 comments on commit 74bcff8

Please sign in to comment.