Skip to content

Commit

Permalink
close #2387: record the line numbers for inline code expressions when…
Browse files Browse the repository at this point in the history
… parsing the document, and show specific line numbers of an inline expression when it throws an error
  • Loading branch information
yihui committed Jan 9, 2025
1 parent 45bb0f3 commit 85c62f4
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 8 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: knitr
Type: Package
Title: A General-Purpose Package for Dynamic Report Generation in R
Version: 1.49.4
Version: 1.49.5
Authors@R: c(
person("Yihui", "Xie", role = c("aut", "cre"), email = "[email protected]", comment = c(ORCID = "0000-0003-0645-5666", URL = "https://yihui.org")),
person("Abhraneel", "Sarma", role = "ctb"),
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGES IN knitr VERSION 1.50

## NEW FEATURES

- 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.

## MINOR CHANGES

- 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.
Expand Down
2 changes: 2 additions & 0 deletions R/block.R
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,11 @@ inline_exec = function(
code = block$code; input = block$input
if ((n <- length(code)) == 0) return(input) # untouched if no code is found
code.src = block$code.src
lines = block$lines

ans = character(n)
for (i in 1:n) {
knit_concord$set(offset = lines[i, ])
tryCatch(parse_only(code[i]), error = function(e) {
stop2('Failed to parse the inline R code: ', code.src[i], '\nReason: ', e$message)
})
Expand Down
10 changes: 7 additions & 3 deletions R/concordance.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# record input/output lines numbers in Rnw/tex and filenames
knit_concord = new_defaults(list(
inlines = NULL, outlines = NULL, infile = NULL, outfile = NULL, block = NULL
inlines = NULL, outlines = NULL, infile = NULL, outfile = NULL, block = NULL, offset = NULL
))

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

# generate concordance for RStudio
Expand Down
1 change: 1 addition & 0 deletions R/output.R
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ process_file = function(text, output) {
},
if (labels[i] != '') sprintf(' [%s]', labels[i]), get_loc
)
knit_concord$set(offset = NULL)
}

if (!tangle) res = insert_header(res) # insert header
Expand Down
11 changes: 7 additions & 4 deletions R/parser.R
Original file line number Diff line number Diff line change
Expand Up @@ -232,18 +232,21 @@ parse_inline = function(input, patterns) {
loc = cbind(start = numeric(0), end = numeric(0))
if (group_pattern(inline.code)) loc = str_locate(input, inline.code)[[1]]
code1 = code2 = character()
lines = integer()
if (nrow(loc)) {
code = t(str_match(input, inline.code))
if (NCOL(code) >= 2L) {
code1 = code[, 1L]
code2 = apply(code[, -1L, drop = FALSE], 1, paste, collapse = '')
nl = gregexpr('\n', input, fixed = TRUE)[[1]]
lines = if (length(nl) > 1 || nl > -1) findInterval(loc, nl) else c(0L, 0L)
}
}

structure(
list(input = input, location = loc, code = code2, code.src = code1),
class = 'inline'
)
structure(list(
input = input, location = loc, code = code2, code.src = code1,
lines = matrix(lines, ncol = 2)
), class = 'inline')
}

print_inline = function(x) {
Expand Down

0 comments on commit 85c62f4

Please sign in to comment.