Skip to content

Commit 3dc7dd4

Browse files
committed
Make code_highlight() handle tabs ('\t') correctly.
This moves the existing function substr_with_tabs() at file level, so it can be called by replace_in_place().
1 parent cbb3424 commit 3dc7dd4

File tree

4 files changed

+52
-23
lines changed

4 files changed

+52
-23
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* New `{.num}` and `{.bytes}` inline styles to format numbers
44
and bytes (@m-muecke, #644, #588, #643).
55

6+
* `code_highlight()` handles tab characters (`\t`) correctly (@mcol, #783).
7+
68
# cli 3.6.5
79

810
* `code_highlight()` supports long strings and symbols

R/prettycode.R

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -159,33 +159,33 @@ code_highlight <- function(code, code_theme = NULL, envir = NULL) {
159159
do_subst(code, data, hitext)
160160
}
161161

162+
substr_with_tabs <- function(x, start, stop, tabsize = 8) {
163+
widths <- rep_len(1, nchar(x))
164+
tabs <- which(strsplit(x, "")[[1]] == "\t")
165+
for (i in tabs) {
166+
cols <- cumsum(widths)
167+
widths[i] <- tabsize - (cols[i] - 1) %% tabsize
168+
}
169+
cols <- cumsum(widths)
170+
start <- which(cols >= start)
171+
if (!length(start)) {
172+
return("")
173+
}
174+
start <- start[1]
175+
stop <- which(cols <= stop)
176+
if (length(stop)) {
177+
stop <- stop[length(stop)]
178+
substr(x, start, stop)
179+
} else {
180+
""
181+
}
182+
}
183+
162184
get_parse_data <- function(x) {
163185
# getParseData(x, includeText = NA) would trim long strings and symbols
164186
data <- getParseData(x, includeText = FALSE)
165187
data$text <- character(nrow(data))
166188

167-
substr_with_tabs <- function(x, start, stop, tabsize = 8) {
168-
widths <- rep_len(1, nchar(x))
169-
tabs <- which(strsplit(x, "")[[1]] == "\t")
170-
for (i in tabs) {
171-
cols <- cumsum(widths)
172-
widths[i] <- tabsize - (cols[i] - 1) %% tabsize
173-
}
174-
cols <- cumsum(widths)
175-
start <- which(cols >= start)
176-
if (!length(start)) {
177-
return("")
178-
}
179-
start <- start[1]
180-
stop <- which(cols <= stop)
181-
if (length(stop)) {
182-
stop <- stop[length(stop)]
183-
substr(x, start, stop)
184-
} else {
185-
""
186-
}
187-
}
188-
189189
srcfile <- attr(data, "srcfile")
190190
terminal <- which(data$terminal)
191191
for (i in terminal) {
@@ -294,7 +294,10 @@ replace_in_place <- function(str, start, end, replacement) {
294294
length(end) == length(replacement)
295295
)
296296

297-
keep <- substring(str, c(1, end + 1), c(start - 1, nchar(str)))
297+
starts <- c(1, end + 1)
298+
ends <- c(start - 1, nchar(str))
299+
keep <- sapply(seq_along(starts),
300+
function(i) substr_with_tabs(str, starts[i], ends[i]))
298301

299302
pieces <- character(length(replacement) * 2 + 1)
300303

tests/testthat/_snaps/prettycode.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,17 @@
223223
Output
224224
\(x) x * 2
225225

226+
# strings with tabs [plain]
227+
228+
Code
229+
code_highlight("x\t + 1")
230+
Output
231+
[1] "x\t + 1"
232+
233+
# strings with tabs [ansi]
234+
235+
Code
236+
code_highlight("x\t + 1")
237+
Output
238+
[1] "x\t \033[33m+\033[39m \033[35m1\033[39m"
239+

tests/testthat/test-prettycode.R

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ test_that("replace_in_place", {
145145
replace_in_place("1234567890", c(1, 5), c(6, 10), c("A", "B")),
146146
"AB"
147147
)
148+
149+
expect_equal(
150+
replace_in_place("x\t + 1", c(1, 10, 12), c(1, 10, 12), c("x", "+", "1")),
151+
"x\t + 1"
152+
)
148153
})
149154

150155
test_that("replace_in_place corner cases", {
@@ -264,6 +269,11 @@ test_that_cli(configs = "ansi", "new language features, lambda functions", {
264269
)
265270
})
266271

272+
test_that_cli(configs = c("plain", "ansi"), "strings with tabs", {
273+
expect_snapshot(
274+
code_highlight("x\t + 1"))
275+
})
276+
267277
test_that("code_highlight() works on long strings and symbols", {
268278
expect_true(
269279
grepl(

0 commit comments

Comments
 (0)