yihui / knitr

A general-purpose tool for dynamic report generation in R
https://yihui.org/knitr/
2.37k stars 874 forks source link

Improve YAML error thrown when parsing in-chunk options #2226

Closed cderv closed 8 months ago

cderv commented 1 year ago

From discussion at https://github.com/quarto-dev/quarto-cli/issues/4306 - @yihui I agree with your comment

---
title: "Example"
format: pdf
engine: knitr
editor: visual
---

```{r}
# install.packages(c("DBI", "RSQLite"))
db = DBI::dbConnect(RSQLite::SQLite(), ":memory:")
#| label: test multiqueries -5
#|  connection: db

select 1

Leading to this error 

processing file: my-homework.qmd Error in yaml::yaml.load(meta, handlers = list(expr = parse_only)) : Scanner error: mapping values are not allowed in this context at line 2, column 12 Calls: .main ... FUN -> parse_block -> partition_chunk -> Execution halted



which is not that helpful to know about the error. 

This is not specific to Qmd and would be useful to Rmd using YAML syntax too
yihui commented 1 year ago

Below is what I'd do and you can try to implement it:

First, we need to improve the error message from yaml.load():

https://github.com/yihui/knitr/blob/77970b0717a9497b5ba275689a21c0af2e58ab07/R/parser.R#L303

This could be done in tryCatch(..., error = function(e) ...). In the error handler, we parse the line/column numbers from the original message (you can access from e$message):

  Scanner error: mapping values are not allowed in this context at line 2, column 12

Then print the original YAML text and insert ^~~~~~ beneath the problematic line, with ^ pointing to the error column. Users should see an error message like this:

Failed to parse YAML: 
  Scanner error: mapping values are not allowed in this context

label: test multiqueries -5
 connection: db
           ^~~~~~~~~~

I think this can greatly improve the error message. If we want to do better, we can point out the line numbers of the code chunk. To do that, first we need to apply this lapply() to seq_along(groups) instead of groups, and we will get the index of the current chunk:

https://github.com/yihui/knitr/blob/77970b0717a9497b5ba275689a21c0af2e58ab07/R/parser.R#L23

With the index, we can emit a message similar to:

https://github.com/yihui/knitr/blob/77970b0717a9497b5ba275689a21c0af2e58ab07/R/output.R#L311-L322

That means we need to factor out these lines of code so that it can be reused, i.e., we pass an index i to a function, and it will emit a message Quitting from lines ....

Let me know if this is all clear to you. Happy to chat next week.

github-actions[bot] commented 2 months ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.