Search code examples
rr-markdownknitrbookdown

Create several indices definitions / theorems at end of bookdown book


This code example to generate a list of definitions works for me but only for one index list. Whenever I try to add another list (e.g. for theorems) only the one defined last in the setup junk works.

Probably I haven't adapted knit_hooks$set() correctly:

---
title: "Create several lists"
output: bookdown::html_document2
---

```{r setup, include=FALSE}
def_list = list()
knitr::knit_hooks$set(engine = function(before, options, envir) {
    if (before && options$engine == 'definition') {
    # collect definition terms from options$name
    def_list[[options$label]] <<- options$name
    }
    NULL
})

thm_list = list()
knitr::knit_hooks$set(engine = function(before, options) {
    if (before && options$engine == 'theorem') {
    # collect theorem terms from options$name
    thm_list[[options$label]] <<- options$name
    }
    NULL
}) 
```

```{definition, d1, name='Foo: My first definition'}
Foo is defined as ...
```


```{theorem, t1, name='My first theorem'}
First theorem ...
```

```{definition, d2, name='Bar: My second definition'}
Bar is defined as ...
```

```{theorem, t2, name='My second theorem'}
Second theorem ...
```

---

**All definitions:**

```{r echo=FALSE, results='asis'}
def_list = unlist(def_list)
cat(sprintf('- \\@ref(def:%s) %s', names(def_list), def_list), sep = '\n')
```

**All theorems:**

```{r echo=FALSE, results='asis'}
thm_list = unlist(thm_list)
cat(sprintf('- \\@ref(thm:%s) %s', names(thm_list), thm_list), sep = '\n')
```

OUTPUT:

screenshot of test file for creating several lists


Solution

  • The issue is you have reset the hook. So, instead you should set the hook once to handle both lists, like so:

    ---
    title: "Create several lists"
    output: bookdown::html_document2
    ---
    
    ```{r setup, include=FALSE}
    def_list = list()
    thm_list = list()
    knitr::knit_hooks$set(engine = function(before, options) {
        if ( before ) {
            if ( options$engine == "theorem" ) {
                thm_list[[options$label]] <<- options$name
            } else if ( options$engine == "definition" ) {
                def_list[[options$label]] <<- options$name
            }
        }
        NULL
    }) 
    ```
    
    ```{definition, d1, name='Foo: My first definition'}
    Foo is defined as ...
    ```
    
    
    ```{theorem, t1, name='My first theorem'}
    First theorem ...
    ```
    
    ```{definition, d2, name='Bar: My second definition'}
    Bar is defined as ...
    ```
    
    ```{theorem, t2, name='My second theorem'}
    Second theorem ...
    ```
    
    ---
    
    **All definitions:**
    
    ```{r echo=FALSE, results='asis'}
    def_list = unlist(def_list)
    cat(sprintf('- \\@ref(def:%s) %s', names(def_list), def_list), sep = '\n')
    ```
    
    **All theorems:**
    
    ```{r echo=FALSE, results='asis'}
    thm_list = unlist(thm_list)
    cat(sprintf('- \\@ref(thm:%s) %s', names(thm_list), thm_list), sep = '\n')
    ```
    

    Then you get the output you want:

    enter image description here