Skip to content

Commit 2b1bb6d

Browse files
committed
close #15
1 parent d1a31a2 commit 2b1bb6d

8 files changed

+54
-35
lines changed

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ Imports:
2020
Suggests:
2121
testthat
2222
LazyData: true
23-
RoxygenNote: 7.1.0
23+
RoxygenNote: 7.2.3
2424
Encoding: UTF-8
2525
Roxygen: list(markdown = TRUE)

NAMESPACE

-2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,3 @@ export(str_rmd_wrap)
66
export(wrap_rmd_addin)
77
import(stringr)
88
importFrom(magrittr,"%>%")
9-
importFrom(utils,head)
10-
importFrom(utils,tail)

NEWS.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
# WrapRmd 0.0.0.9005
2+
3+
- Inline math (that starts and ends with a `$` character) is treated like R
4+
code during text-wrapping. It is protected from line breaks and having
5+
`\` escapes from being inserted.
6+
17
# WrapRmd 0.0.0.9004
28

3-
* Added support for avoiding inserting line breaks into `bookdown` cross-references (such as `Figure\ \@ref(fig:example)`).
9+
- Added support for avoiding inserting line breaks into `bookdown`
10+
cross-references (such as `Figure\ \@ref(fig:example)`).
411

512
# WrapRmd 0.0.0.9003
613

R/package.R

+39-23
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
#' @name WrapRmd
77
#' @docType package
88
#' @import stringr
9-
#' @importFrom utils head tail
109
NULL
1110

1211

13-
1412
#' Wrap text but don't insert lines breaks into inline R code
1513
#'
1614
#' Call this addin to wrap paragraphs in an R Markdown document.
@@ -41,7 +39,9 @@ knit_selection_addin <- function() {
4139
text <- unlist(selection)["text"]
4240
cat(
4341
commonmark::markdown_commonmark(
44-
knitr::knit(text = text, quiet = TRUE)))
42+
knitr::knit(text = text, quiet = TRUE)
43+
)
44+
)
4545
}
4646

4747

@@ -69,7 +69,8 @@ str_rmd_wrap <- function(string, width = getOption("WrapRmd.width", 80)) {
6969
re_blanks_at_start,
7070
re_paragraph_sep,
7171
re_blanks_at_close,
72-
sep = "|")
72+
sep = "|"
73+
)
7374

7475
# Find paragraph separations
7576
paragraph_seps <- string %>%
@@ -79,12 +80,12 @@ str_rmd_wrap <- function(string, width = getOption("WrapRmd.width", 80)) {
7980
# Split at those points to get paragraphs.
8081
paragraphs <- string %>%
8182
str_split(re_start_or_sep_or_close) %>%
82-
unlist %>%
83+
unlist() %>%
8384
unname()
8485

8586
# Wrap each paragraph.
8687
paragraphs <- Map(function(...) str_rmd_wrap_one(..., width), paragraphs) %>%
87-
unlist %>%
88+
unlist() %>%
8889
unname()
8990

9091
str_interleave(paragraphs, paragraph_seps)
@@ -97,8 +98,8 @@ str_interleave <- function(strings, interleaves) {
9798
stopifnot(length(strings) - length(interleaves) == 1)
9899

99100
# Pop the first string off. Concatenate pairs of interleaves and strings.
100-
start <- head(strings, 1)
101-
left <- tail(strings, -1)
101+
start <- utils::head(strings, 1)
102+
left <- utils::tail(strings, -1)
102103
body <- paste0(interleaves, left, collapse = "")
103104

104105
# Reattach head
@@ -109,42 +110,54 @@ str_interleave <- function(strings, interleaves) {
109110
str_rmd_wrap_one <- function(string, width) {
110111
output <- string
111112

113+
# Patterns to protect from line breaks
112114
re_inline_code <- "(`r)( )([^`]+`)"
115+
re_inline_math <- "((?!=[$])[$][^$]+[$])"
113116
re_cross_references <- "(\\w+\\\\ \\\\@ref\\(.*?\\))"
114-
re_nonword <- "\\W|_"
115117

118+
# Locate the patterns
116119
inline_code <- string %>%
117120
str_extract_all(re_inline_code) %>%
118121
unlist()
119122

123+
inline_math <- string %>%
124+
str_extract_all(re_inline_math) %>%
125+
unlist()
126+
120127
cross_references <- string %>%
121128
str_extract_all(re_cross_references) %>%
122129
unlist()
123130

131+
# Substrings that match the patterns
124132
wrap_ignore <- c(
125133
inline_code,
134+
inline_math,
126135
cross_references
127136
)
128137

129-
# Just wrap if no code or cross-references
138+
# Just wrap if no substrings need to be protected
130139
if (length(wrap_ignore) == 0) {
131140
return(md_wrap(string, width))
132141
}
133142

134-
# Make R code spans into long words
143+
# Make protected strings spans into long words
135144

136-
# I used to replace with "_" but md_wrap() escapes them as "\\_" which messes
137-
# up the line width
145+
# Replace all nonwords and _'s with Qs
146+
re_nonword <- "\\W|_"
138147
spaceless_wrap_ignore <- str_replace_all(wrap_ignore, re_nonword, "Q")
139148

140149
for (i in seq_along(wrap_ignore)) {
141-
output <- str_replace(output, coll(wrap_ignore[i]), spaceless_wrap_ignore[i])
150+
output <- str_replace(
151+
string = output,
152+
pattern = coll(wrap_ignore[i]),
153+
replacement = spaceless_wrap_ignore[i]
154+
)
142155
}
143156

144-
# Wrap
157+
# Wrap the text now that the strings are protected
145158
output <- md_wrap(output, width)
146159

147-
# Put original code spans back
160+
# Put original versions of protected strings back in
148161
for (i in seq_along(wrap_ignore)) {
149162
output <- stringi::stri_replace_first_coll(
150163
str = output,
@@ -157,12 +170,14 @@ str_rmd_wrap_one <- function(string, width) {
157170
}
158171

159172

160-
md_wrap <- function(string,
161-
width,
162-
hardbreaks = FALSE,
163-
smart = getOption("WrapRmd.smart", FALSE),
164-
normalize = FALSE,
165-
extensions = getOption("WrapRmd.extensions", TRUE)) {
173+
md_wrap <- function(
174+
string,
175+
width,
176+
hardbreaks = FALSE,
177+
smart = getOption("WrapRmd.smart", FALSE),
178+
normalize = FALSE,
179+
extensions = getOption("WrapRmd.extensions", TRUE)
180+
) {
166181
raw_string <- string
167182

168183
wrapped <- string %>%
@@ -171,7 +186,8 @@ md_wrap <- function(string,
171186
extensions = extensions,
172187
normalize = normalize,
173188
smart = smart,
174-
width = width) %>%
189+
width = width
190+
) %>%
175191
str_replace("\\n$", "")
176192

177193
wrapped %>%

tests/testthat/test-escaping.R

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
context("escaping.R")
2-
31
test_that("does not escape !, [, ]", {
42
string <- "This is a confidence interval [0, 1], [0, 1]!"
53
expect_equal(str_rmd_wrap(string), string)
@@ -16,3 +14,9 @@ test_that("does not unescape \\@ref", {
1614
})
1715

1816

17+
test_that("escape \ in math mode", {
18+
string <- "a continuous parameter $\\beta$ with no $\\theta$s"
19+
expect_equal(str_rmd_wrap(string), string)
20+
})
21+
22+

tests/testthat/test-interleave.R

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
context("interleave.R")
2-
31
test_that("interleaving strings", {
42
# sneak private function out
53
str_interleave <- WrapRmd:::str_interleave

tests/testthat/test-options.R

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
context("test-options.R")
2-
31
test_that("wrapping can use options()", {
42
# Default is 80
53
long_paragraph <-

tests/testthat/test-wrap.R

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
context("wrap.R")
2-
31
test_that("basic wrapping", {
42
no_code <- "regular words on a line"
53
expect_equal(str_rmd_wrap(no_code), no_code)

0 commit comments

Comments
 (0)