Skip to content

Commit 961ac86

Browse files
Merge pull request #313 from lorenzwalthert/fun-dec
- Only consider R code as code to format (#313).
2 parents 630bacd + 87bebd4 commit 961ac86

File tree

9 files changed

+167
-34
lines changed

9 files changed

+167
-34
lines changed

R/transform-code.R

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,48 +29,79 @@ transform_code <- function(path, fun, verbose = FALSE, ...) {
2929
#' @param transformer_fun A styler transformer function
3030
#' @importFrom purrr flatten_chr
3131
transform_rmd <- function(lines, transformer_fun) {
32-
chunks <- identify_chunks(lines)
32+
chunks <- separate_chunks(lines)
3333
chunks$r_chunks <- map(chunks$r_chunks, transformer_fun)
3434

3535
map2(chunks$text_chunks, c(chunks$r_chunks, list(character(0))), c) %>%
3636
flatten_chr()
3737
}
3838

3939

40-
#' Identify chunks within Rmd contents
41-
#'
42-
#' Identifies the code and text chunks within an Rmd file, and returns these
43-
#' as a nested list.
40+
#' Separate chunks within Rmd contents
4441
#'
42+
#' Identifies and separates the code and text chunks (the latter includes non-R
43+
#' code) within an Rmd file, and returns these separately.
4544
#' @param lines a character vector of lines from an Rmd file
46-
#'
4745
#' @importFrom purrr map2
4846
#' @importFrom rlang seq2
49-
identify_chunks <- function(lines) {
47+
separate_chunks <- function(lines) {
48+
r_raw_chunks <- identify_r_raw_chunks(lines)
49+
r_chunks <- map2(
50+
r_raw_chunks$starts, r_raw_chunks$ends, ~lines[seq2(.x + 1, .y - 1)]
51+
)
52+
53+
text_chunks <- map2(
54+
c(1, r_raw_chunks$ends), c(r_raw_chunks$starts, length(lines)),
55+
~lines[seq2(.x, .y)]
56+
)
57+
lst(r_chunks, text_chunks)
58+
}
59+
60+
#' Identifies raw R code chunks
61+
#'
62+
#' Raw in the sense that these chunks don't contain pure R code, but they
63+
#' contain a header and footer of markdown. Only code chunks that have an engine
64+
#' whose name matches `engine-pattern` are considered as R code.
65+
#' @inheritParams separate_chunks
66+
#' @param engine_pattern A regular expression that must match the engine name.
67+
identify_r_raw_chunks <- function(lines, engine_pattern = get_engine_pattern()) {
5068
pattern <- get_knitr_pattern(lines)
5169
if (is.null(pattern$chunk.begin) || is.null(pattern$chunk.end)) {
5270
stop("Unrecognized chunk pattern!", call. = FALSE)
5371
}
54-
55-
starts <- grep(pattern$chunk.begin, lines, perl = TRUE)
56-
ends <- grep(pattern$chunk.end, lines, perl = TRUE)
72+
starts <- grep("^[\t >]*```+\\s*\\{\\s*([a-zA-Z0-9]+.*)\\}\\s*$", lines, perl = TRUE)
73+
ends <- grep("^[\t >]*```+\\s*$", lines, perl = TRUE)
5774

5875
if (length(starts) != length(ends)) {
5976
stop("Malformed file!", call. = FALSE)
6077
}
6178

62-
r_chunks <- map2(starts, ends, ~lines[seq2(.x + 1, .y - 1)])
63-
64-
text_chunks <- map2(c(1, ends), c(starts, length(lines)), ~lines[seq2(.x, .y)])
79+
is_r_code <- grepl(
80+
paste0("^[\t >]*```+\\s*\\{\\s*", engine_pattern, "[\\s\\},]"),
81+
lines[starts], perl = TRUE
82+
)
83+
list(starts = starts[is_r_code], ends = ends[is_r_code])
84+
}
6585

66-
lst(r_chunks, text_chunks)
86+
#' What's the engine pattern for rmd code chunks?
87+
#'
88+
#' The function returns the regular expression pattern that identifies
89+
#' all r engines in Rmd chunks. Defaults to `[Rr]`. You probably only want to
90+
#' change this if you create a knitr engine that processes R code but is not
91+
#' the default engine `r`.
92+
#' The pattern must be followed by a space (in the case the chunk is given
93+
#' a name), a comma (if no name is given but further options are passed to the
94+
#' engine) or a closing curly brace (in case no option and no name is given to
95+
#' the chunk).
96+
get_engine_pattern <- function() {
97+
"[rR]"
6798
}
6899

69100
#' Get chunk pattern
70101
#'
71102
#' Determine a regex pattern for identifying R code chunks.
72103
#'
73-
#' @inheritParams identify_chunks
104+
#' @inheritParams separate_chunks
74105
get_knitr_pattern <- function(lines) {
75106
knitr::all_patterns[["md"]]
76107
}

man/get_engine_pattern.Rd

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/identify_chunks.Rd

Lines changed: 0 additions & 15 deletions
This file was deleted.

man/identify_r_raw_chunks.Rd

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/separate_chunks.Rd

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/public-api/xyzfile_rmd/random2.Rmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Some text before empty chunk
77
```
88
Final text before longer code chunk
99
This text chunk has multiple lines
10-
```{r}
10+
```{R}
1111
# random
1212
this(is_a_call(x))
1313
if (x) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Header
2+
3+
Some text.
4+
5+
```{R}
6+
1+1
7+
```
8+
9+
```{r}
10+
1+1
11+
```
12+
13+
```{r, a = 3}
14+
1+1
15+
```
16+
17+
```{ r }
18+
1+1
19+
```
20+
21+
More text.
22+
23+
```{nonR}
24+
I like the jungle, I like the .2'
25+
```
26+
27+
```{blabla }
28+
I like the jungle,
29+
```
30+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Header
2+
3+
Some text.
4+
5+
```{R}
6+
1 + 1
7+
```
8+
9+
```{r}
10+
1 + 1
11+
```
12+
13+
```{r, a = 3}
14+
1 + 1
15+
```
16+
17+
```{ r }
18+
1 + 1
19+
```
20+
21+
More text.
22+
23+
```{nonR}
24+
I like the jungle, I like the .2'
25+
```
26+
27+
```{blabla }
28+
I like the jungle,
29+
```
30+

tests/testthat/test-rmd.R

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
context("rmd")
22

33
test_that("can style .Rmd files", {
4-
test_collection(
5-
"rmd",
4+
expect_error(test_collection(
5+
"rmd", "simple",
66
transformer = transform_rmd,
77
transformer_fun = style_text,
88
write_tree = FALSE
9-
)
9+
), NA)
10+
expect_error(test_collection(
11+
"rmd", "r_and_non_r_code_chunks",
12+
transformer = transform_rmd,
13+
transformer_fun = style_text,
14+
write_tree = FALSE
15+
), NA)
1016
})

0 commit comments

Comments
 (0)