Create index of definitions / theorems at end of bookdown book

别说谁变了你拦得住时间么 提交于 2020-01-01 05:18:31

问题


For reader convenience, I'd like to include, at the end of my bookdown book, written in markdown, a simple list or index of definitions from the body of the book. i.e. ones created using custom blocks, like this:

```{definition, bar, echo=T}
A bar is defined here as a foo-like thing.
```

(My need is for definitions, but others might like lists of theorems, etc. Don't know if lists of figures and tables could be covered in the same way?)

Thanks to @yihui I know that knitr::all_labels(engine == 'definition') is my friend.

So I can do this anywhere in the end of the book, usually at the end:

```{r comment="",results="asis",echo=FALSE}
knitr::all_labels(engine == 'definition') %>% unlist %>% paste0("\n\n","\\@ref(def:",.,"): ",.,"\n\n",collapse="\n\n") %>% cat

```

Which prints this:

1: bar

2: foobar

With clickable numbers. Which is OK. But wouldn't it be nice if, after each label, the actual definition could be printed too? (The content of the blocks is not available in knitr::all_labels(engine == 'definition'))


回答1:


Here is an example using the output format bookdown::html_document2, and it should also work for any other book output formats:

---
title: "Test Definitions"
output: bookdown::html_document2
---

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

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

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

All definitions in this document:

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

Output:

The basic idea is to use a chunk hook to collect definition labels and names, and print them at the end. You do not have to use the chunk option name. It can be an arbitrary option, e.g., term. The option name is special because the name of the definition will be printed in the output. If you don't like that, you can use, for example, term:

```{definition, d2, term='Bar'}
Bar is defined as ...
```



回答2:


Perfect, so adding on from Yihui's suggestion, this prints out the definitions as well, and no need to bother with names, just labels will do:

```{definition, 'Bar',echo=T,cache=F}
Bar is defined as something
```

```{definition, 'Bar2',echo=T,cache=F}
Bar2 is defined as something else.
```

Here are all the definitions in this book.

```{r comment="",results="asis",echo=FALSE,cache=F}


for(x in knitr::all_labels(engine == 'definition')){
   paste0("\n\n","\\@ref(def:",x,"): ",x,"\n\n>",knitr:::knit_code$get(x),collapse="\n\n") %>% cat
} 

```

... produces this:

Here are all the definitions in this book.

1: Bar

Bar is defined as something

2: Bar2

Bar2 is defined as something else.



来源:https://stackoverflow.com/questions/40735727/create-index-of-definitions-theorems-at-end-of-bookdown-book

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!