Skip to content

Commit 236c957

Browse files
Merge pull request #554 from r-lib/b-551-quote-newlines
- Fix handling of newlines when converting quotes (#551).
2 parents c9447aa + b0d6eba commit 236c957

File tree

9 files changed

+746
-663
lines changed

9 files changed

+746
-663
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ importFrom(purrr,pwalk)
3434
importFrom(purrr,reduce)
3535
importFrom(purrr,when)
3636
importFrom(rlang,abort)
37+
importFrom(rlang,is_empty)
3738
importFrom(rlang,is_installed)
3839
importFrom(rlang,seq2)
3940
importFrom(rlang,warn)

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333

3434
* Escape characters in roxygen code examples are now correctly escaped (#512).
3535

36+
* Special characters such as `\n` in strings are now preseved in text and not
37+
turned into literal values like a line break (#554).
38+
3639
* Style selection Addin now preserves line break when the last line selected is
3740
an entire line (#520).
3841

R/rules-spacing.R

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,34 @@ remove_space_after_unary_pm_nested <- function(pd) {
126126
#' '")
127127
#' @importFrom purrr map map_chr
128128
#' @param pd_flat A flat parse table.
129+
#' @importFrom rlang is_empty
129130
#' @keywords internal
130131
fix_quotes <- function(pd_flat) {
131-
str_const <- pd_flat$token == "STR_CONST"
132-
str_const_change <- grepl("^'([^\"]*)'$", pd_flat$text[str_const])
133-
pd_flat$text[str_const][str_const_change] <-
134-
map(pd_flat$text[str_const][str_const_change], parse_text) %>%
135-
map_chr(~ paste0("\"", .x, "\""))
132+
str_const <- which(pd_flat$token == "STR_CONST")
133+
if (is_empty(str_const)) {
134+
return(pd_flat)
135+
}
136+
137+
pd_flat$text[str_const] <- map(pd_flat$text[str_const], fix_quotes_one)
136138
pd_flat
137139
}
138140

141+
#' @importFrom rlang is_empty
142+
fix_quotes_one <- function(x) {
143+
rx <- "^'([^\"]*)'$"
144+
i <- grep(rx, x)
145+
if (is_empty(i)) {
146+
return(x)
147+
}
148+
149+
# replace outer single quotes
150+
xi <- gsub(rx, '"\\1"', x[i])
151+
152+
# Replace inner escaped quotes (\') by ' and keep all other instances of \., including \\
153+
x[i] <- gsub("\\\\(')|(\\\\[^'])", "\\1\\2", xi)
154+
x
155+
}
156+
139157
remove_space_before_opening_paren <- function(pd_flat) {
140158
paren_after <- pd_flat$token == "'('"
141159
if (!any(paren_after)) {

tests/testthat/escaping/basic-escape-in.R

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ NULL
2222
#' things
2323
#'
2424
#' @examples
25-
#' call('\n') # FIXME when single quotes are used, the newline is evaluated
25+
#' call('\n')
2626
#' ano("\\.", further = X)
2727
NULL
28+
29+
'single quotes with
30+
embedded and \n not embedded line breaks'
31+
32+
x <- ' 2' # there is a tab emebbed (created with writeLines("x <- '\t2'"))
33+
34+
x <- '\001'
35+
'\x01'
36+
37+
# FIXME: "\01" gives an error when not in a comment
38+
# FIXME: this too: '\01'

tests/testthat/escaping/basic-escape-in_tree

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

tests/testthat/escaping/basic-escape-out.R

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,17 @@ NULL
2222
#' things
2323
#'
2424
#' @examples
25-
#' call("
26-
#' ") # FIXME when single quotes are used, the newline is evaluated
25+
#' call("\n")
2726
#' ano("\\.", further = X)
2827
NULL
28+
29+
"single quotes with
30+
embedded and \n not embedded line breaks"
31+
32+
x <- " 2" # there is a tab emebbed (created with writeLines("x <- '\t2'"))
33+
34+
x <- "\001"
35+
"\x01"
36+
37+
# FIXME: "\01" gives an error when not in a comment
38+
# FIXME: this too: '\01'

tests/testthat/strict/non_strict-in.R

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ test <- function() {
1313
single quotes are used
1414
.'
1515

16-
'strings with embeded\nline breaks are unfortunately split'
16+
'strings with embedded\nline breaks are handled correctly'
17+
18+
'\\'
19+
'\\\''
20+
'\\\\'
21+
'\\\\\''
22+
'\'\\\\\''
1723

1824
# Comments are always preserved
1925

0 commit comments

Comments
 (0)