rmarkdown 是否允许代码块的标题和引用?

Does rmarkdown allow captions and references for code chunks?

在 rmarkdown(不是 运行 代码的结果)中添加字幕和引用一段代码是否有技巧?例如,我如何引用此代码块:

```{r blah}
blah <- "blah"
```

我知道我可以使用 \@ref(fig:theFig) 或 \@ref(tab:theTable) 来获取 fig.cap 或标题(带 kable),但我看不到办法标题和引用代码本身。

这将是一个很棒的功能。而且我认为它还没有集成。这是一种适用于 PDF 文档并允许您为 cross-referencing:

生成标题和标签的方法
  1. 包含一个header.tex,内容如下

\usepackage{caption}
\usepackage{floatrow}

\DeclareNewFloatType{chunk}{placement=H, fileext=chk, name=}
\captionsetup{options=chunk}
\renewcommand{\thechunk}{Chunk~\thesection.\arabic{chunk}}
\makeatletter
\@addtoreset{chunk}{section}
\makeatother

由于用于块的环境不是浮动类型,我们声明了一个新环境,命名为 chunk。选项 name 留空,因为我们已经通过在下一行中添加单词 Chunk 来重新定义 \thechunk(尝试使用 name 选项,看看会发生什么)。

块应该按部分枚举,因此我们告诉 tex 在每次新部分开始时重置计数器。

如果您不使用节编号(通过设置 YAML 选项),则替换行

\renewcommand{\thechunk}{Chunk~\thesection.\arabic{chunk}}

来自

\renewcommand{\thechunk}{Chunk~\arabic{chunk}}
  1. 修改 rmarkdown 文档中的 knitr 源挂钩

library(knitr)
oldSource <- knit_hooks$get("source")
knit_hooks$set(source = function(x, options) {
  x <- oldSource(x, options)
  x <- ifelse(!is.null(options$ref), paste0("\label{", options$ref,"}", x), x)
  ifelse(!is.null(options$codecap), paste0("\captionof{chunk}{", options$codecap,"}", x), x)
})

这里我们使用了两个新的块选项 refcodecap。如果其中一个不是 NULL,则使用命令 \label\captionof.

生成相应的标签或标题

MWE:

---
title: "Cross-referencing Code Chunks"
output: 
  pdf_document: 
    includes:
      in_header: header.tex
    number_sections: true
---

```{r, echo=FALSE}
library(knitr)
oldSource <- knit_hooks$get("source")
knit_hooks$set(source = function(x, options) {
  x <- oldSource(x, options)
  x <- ifelse(!is.null(options$ref), paste0("\label{", options$ref,"}", x), x)
  ifelse(!is.null(options$codecap), paste0("\captionof{chunk}{", options$codecap,"}", x), x)
})
```

# Foo

Jump to \ref{TheBarChunk}

```{r Foo, ref = "TheFooChunk", codecap = "My Chunk"}
print("Foo!")
```

\newpage

# Bar

```{r Bar, ref = "TheBarChunk", codecap = "My second chunk"}
print("Bar!")
```

Head back to \ref{TheFooChunk}

这是(两个页面的)输出:

在代码块

下方添加标题

如果您希望在代码块下方添加标题,而不是在上方,这可以通过更改在 knitr 钩子上方阅读:

oldSource <- knit_hooks$get("source")
knit_hooks$set(source = function(x, options) {
  x <- oldSource(x, options)
  x <- ifelse(!is.null(options$codecap), paste0(x, "\captionof{chunk}{", options$codecap,"}"), x)
  ifelse(!is.null(options$ref), paste0(x, "\label{", options$ref,"}"), x)
})

评论:

您可以通过检查所需的输出类型来改进代码,以便新的源挂钩仅用于 pdf 输出(由于是午餐时间而跳过)。