Skip to content

Commit 85c62f4

Browse files
committed
close #2387: record the line numbers for inline code expressions when parsing the document, and show specific line numbers of an inline expression when it throws an error
1 parent 45bb0f3 commit 85c62f4

File tree

6 files changed

+22
-8
lines changed

6 files changed

+22
-8
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: knitr
22
Type: Package
33
Title: A General-Purpose Package for Dynamic Report Generation in R
4-
Version: 1.49.4
4+
Version: 1.49.5
55
Authors@R: c(
66
person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666", URL = "https://yihui.org")),
77
person("Abhraneel", "Sarma", role = "ctb"),

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGES IN knitr VERSION 1.50
22

3+
## NEW FEATURES
4+
5+
- For inline code expressions, their specific line numbers will be shown in the message when errors occur (thanks, @kevinushey, #2387). Previously, the numbers were not specific to the inline code but the lines of the whole text chunk containing the inline code, which are often quite vague.
6+
37
## MINOR CHANGES
48

59
- Moved implementations of `combine_words()` and `write_bib()` to the **xfun** package as `xfun::join_words()` and `xfun::pkg_bib()`, respectively, since they are not directly relevant to **knitr**. The functions `combine_words()` and `write_bib()` are still kept in **knitr**, and can continue to be used in the future.

R/block.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,11 @@ inline_exec = function(
568568
code = block$code; input = block$input
569569
if ((n <- length(code)) == 0) return(input) # untouched if no code is found
570570
code.src = block$code.src
571+
lines = block$lines
571572

572573
ans = character(n)
573574
for (i in 1:n) {
575+
knit_concord$set(offset = lines[i, ])
574576
tryCatch(parse_only(code[i]), error = function(e) {
575577
stop2('Failed to parse the inline R code: ', code.src[i], '\nReason: ', e$message)
576578
})

R/concordance.R

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# record input/output lines numbers in Rnw/tex and filenames
44
knit_concord = new_defaults(list(
5-
inlines = NULL, outlines = NULL, infile = NULL, outfile = NULL, block = NULL
5+
inlines = NULL, outlines = NULL, infile = NULL, outfile = NULL, block = NULL, offset = NULL
66
))
77

88
# do not consider child mode for concordance
@@ -13,8 +13,12 @@ concord_mode = function() {
1313
current_lines = function(i = knit_concord$get('block')) {
1414
# a helpr function to return line numbers for block i
1515
n = knit_concord$get('inlines')
16-
n1 = sum(head(n, i)); n0 = n1 - n[i] + 2
17-
paste(c(min(n0, n1), n1), collapse = '-')
16+
n1 = sum(head(n, i)); n0 = min(n1, n1 - n[i] + 1)
17+
# adjust line numbers for inline code expressions
18+
if (length(o <- knit_concord$get('offset')) == 2) {
19+
n1 = n0 + o[2]; n0 = n0 + o[1]
20+
}
21+
paste(c(n0, n1), collapse = '-')
1822
}
1923

2024
# generate concordance for RStudio

R/output.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ process_file = function(text, output) {
323323
},
324324
if (labels[i] != '') sprintf(' [%s]', labels[i]), get_loc
325325
)
326+
knit_concord$set(offset = NULL)
326327
}
327328

328329
if (!tangle) res = insert_header(res) # insert header

R/parser.R

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,18 +232,21 @@ parse_inline = function(input, patterns) {
232232
loc = cbind(start = numeric(0), end = numeric(0))
233233
if (group_pattern(inline.code)) loc = str_locate(input, inline.code)[[1]]
234234
code1 = code2 = character()
235+
lines = integer()
235236
if (nrow(loc)) {
236237
code = t(str_match(input, inline.code))
237238
if (NCOL(code) >= 2L) {
238239
code1 = code[, 1L]
239240
code2 = apply(code[, -1L, drop = FALSE], 1, paste, collapse = '')
241+
nl = gregexpr('\n', input, fixed = TRUE)[[1]]
242+
lines = if (length(nl) > 1 || nl > -1) findInterval(loc, nl) else c(0L, 0L)
240243
}
241244
}
242245

243-
structure(
244-
list(input = input, location = loc, code = code2, code.src = code1),
245-
class = 'inline'
246-
)
246+
structure(list(
247+
input = input, location = loc, code = code2, code.src = code1,
248+
lines = matrix(lines, ncol = 2)
249+
), class = 'inline')
247250
}
248251

249252
print_inline = function(x) {

0 commit comments

Comments
 (0)