如何在 Rmarkdown 中添加跨块的行号?
How can I add line numbers that go across chunks in Rmarkdown?
我想将代码行编号添加到我的 Rmarkdown 文件的 HTML 输出中。我很高兴 唯一地 识别输出中每一行代码的任何方法(例如,在整个文档中递增的连续行号,或者代码块由它们自己的索引标识,并且在这些代码块中,行号从 1) 开始。
我一直无法做到这一点。
使用其他 Whosebug 答案和 this blog post 我得到了行号,但它们会随着每个新块而重置。
我有以下 Rmd 文件:
---
output:
html_document:
highlight: kate
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
编译为:
如您所见,当一个块被输出拆分或一个新块开始时,行号会重置。我希望看到行号为 1、2、3、4,而不是 1、1、1、2。
有人知道如何让它工作吗?
这是我可以建议的:使用行自动编号功能 + 使用 CSS 计数器在右侧显示块编号 ("cell")。然后你可以参考一个块+行。
---
title: "ChunkLine numbering"
author: "WeLoveDataScience"
output:
html_document:
highlight: pygments
---
```{css, echo=FALSE}
body {
counter-reset: nchunk;
}
pre.r {
counter-increment: nchunk;
position: relative;
overflow: visible;
}
pre.r::before {
content: 'C[' counter(nchunk) ']';
display: inline-block;
position: absolute;
right: 0em;
color: rgb(50, 60, 160);
}
```
```{r cars, class.source = c("numCode", "r", "numberLines")}
summary(cars)
head(cars)
foo=function(x){
2*x
}
```
```{r other, class.source = c("numCode", "r", "numberLines")}
1+1
```
我设法通过在 Rmd
文档末尾添加一些 jquery 来获得 HTML 文档的连续行号:
---
output:
rmdformats::html_clean:
highlight: kate
toc: true
use_bookdown: true
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
<!--
The javascript below will reset the line numbers when
the document loads.
-->
<script>
$(function() {
$(".sourceLine").each( function( index ){
$( this ).attr( "data-line-number", index + 1 );
});
});
</script>
生成的文档具有连续的行号,如下所示:
它有点老套,因为它需要 jquery(可能是通过包含一些覆盖现有的 css 来做到这一点的方法),但它可以工作并且看起来很整洁。
2020 年 8 月 4 日更新
他们改变了行编号的工作方式(现在它基于 CSS 计数器)。为了让它现在在整个文档中按顺序工作,您需要插入一些 CSS。下面是一个完整的工作示例。重要的代码在 <style>
块中。它在 body
(文档)级别重置相关计数器,并防止为每个代码块重置计数器。
---
output:
rmdformats::html_clean:
highlight: kate
toc: true
use_bookdown: true
---
<style>
body
{ counter-reset: source-line 0; }
pre.numberSource code
{ counter-reset: none; }
</style>
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
正如@mb21 在评论中指出的那样,可以通过添加 startFrom
属性来控制代码块的第一行号。但是,这不能手动完成,因为 knitr 可以根据内容将代码块拆分为多个块。我们希望以编程方式添加此属性。
我知道的最简单的方法是让 pandoc 修改结构,因为在 pandoc 看到它们时所有的块都已经被评估过。我们将使用 Lua instead of R for scripting, as that is the most efficient when working with pandoc filters.
该脚本将跟踪它到目前为止看到的代码行数,并将正确的 startFrom
属性添加到源代码块。我们可以通过检查 numberLines
class 来区分源块和结果块:只有前者有 class.
-- Number of code lines seen so far.
local total_lines_count = 0
-- Count the number of newlines in a string.
function count_lines (text)
local count = 0
local last_pos = 0
repeat
last_pos = string.find(text, '\n', last_pos + 1, true)
count = count + 1
until not last_pos
return count
end
function CodeBlock (cb)
-- do nothing for result blocks
if not cb.classes:includes 'numberLines' then return nil end
cb.attributes['startFrom'] = total_lines_count + 1
total_lines_count = total_lines_count + count_lines(cb.text)
return cb
end
现在唯一剩下的就是告诉 pandoc 在转换期间调用过滤器。这可以通过将 --lua-filter
选项添加到 pandoc_args
:
来完成
---
output:
html_document:
highlight: kate
pandoc_args: ['--lua-filter=number-lines.lua']
---
文件 number-lines.lua
应包含上面的 Lua 代码并放在与您的文档相同的文件夹中,或者放在 pandoc 数据目录下的 filters
文件夹中(参见 pandoc -v
).
这种方法的优点是它适用于 HTML 以及 PDF 输出。
我想将代码行编号添加到我的 Rmarkdown 文件的 HTML 输出中。我很高兴 唯一地 识别输出中每一行代码的任何方法(例如,在整个文档中递增的连续行号,或者代码块由它们自己的索引标识,并且在这些代码块中,行号从 1) 开始。
我一直无法做到这一点。
使用其他 Whosebug 答案和 this blog post 我得到了行号,但它们会随着每个新块而重置。
我有以下 Rmd 文件:
---
output:
html_document:
highlight: kate
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
编译为:
如您所见,当一个块被输出拆分或一个新块开始时,行号会重置。我希望看到行号为 1、2、3、4,而不是 1、1、1、2。
有人知道如何让它工作吗?
这是我可以建议的:使用行自动编号功能 + 使用 CSS 计数器在右侧显示块编号 ("cell")。然后你可以参考一个块+行。
---
title: "ChunkLine numbering"
author: "WeLoveDataScience"
output:
html_document:
highlight: pygments
---
```{css, echo=FALSE}
body {
counter-reset: nchunk;
}
pre.r {
counter-increment: nchunk;
position: relative;
overflow: visible;
}
pre.r::before {
content: 'C[' counter(nchunk) ']';
display: inline-block;
position: absolute;
right: 0em;
color: rgb(50, 60, 160);
}
```
```{r cars, class.source = c("numCode", "r", "numberLines")}
summary(cars)
head(cars)
foo=function(x){
2*x
}
```
```{r other, class.source = c("numCode", "r", "numberLines")}
1+1
```
我设法通过在 Rmd
文档末尾添加一些 jquery 来获得 HTML 文档的连续行号:
---
output:
rmdformats::html_clean:
highlight: kate
toc: true
use_bookdown: true
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
<!--
The javascript below will reset the line numbers when
the document loads.
-->
<script>
$(function() {
$(".sourceLine").each( function( index ){
$( this ).attr( "data-line-number", index + 1 );
});
});
</script>
生成的文档具有连续的行号,如下所示:
它有点老套,因为它需要 jquery(可能是通过包含一些覆盖现有的 css 来做到这一点的方法),但它可以工作并且看起来很整洁。
2020 年 8 月 4 日更新
他们改变了行编号的工作方式(现在它基于 CSS 计数器)。为了让它现在在整个文档中按顺序工作,您需要插入一些 CSS。下面是一个完整的工作示例。重要的代码在 <style>
块中。它在 body
(文档)级别重置相关计数器,并防止为每个代码块重置计数器。
---
output:
rmdformats::html_clean:
highlight: kate
toc: true
use_bookdown: true
---
<style>
body
{ counter-reset: source-line 0; }
pre.numberSource code
{ counter-reset: none; }
</style>
```{r setup, include=FALSE}
knitr::opts_chunk$set(
class.source = "numberLines lineAnchors"
)
```
```{r}
5 + 5
3 * 9
```
```{r}
x <- 5
x * 3
```
正如@mb21 在评论中指出的那样,可以通过添加 startFrom
属性来控制代码块的第一行号。但是,这不能手动完成,因为 knitr 可以根据内容将代码块拆分为多个块。我们希望以编程方式添加此属性。
我知道的最简单的方法是让 pandoc 修改结构,因为在 pandoc 看到它们时所有的块都已经被评估过。我们将使用 Lua instead of R for scripting, as that is the most efficient when working with pandoc filters.
该脚本将跟踪它到目前为止看到的代码行数,并将正确的 startFrom
属性添加到源代码块。我们可以通过检查 numberLines
class 来区分源块和结果块:只有前者有 class.
-- Number of code lines seen so far.
local total_lines_count = 0
-- Count the number of newlines in a string.
function count_lines (text)
local count = 0
local last_pos = 0
repeat
last_pos = string.find(text, '\n', last_pos + 1, true)
count = count + 1
until not last_pos
return count
end
function CodeBlock (cb)
-- do nothing for result blocks
if not cb.classes:includes 'numberLines' then return nil end
cb.attributes['startFrom'] = total_lines_count + 1
total_lines_count = total_lines_count + count_lines(cb.text)
return cb
end
现在唯一剩下的就是告诉 pandoc 在转换期间调用过滤器。这可以通过将 --lua-filter
选项添加到 pandoc_args
:
---
output:
html_document:
highlight: kate
pandoc_args: ['--lua-filter=number-lines.lua']
---
文件 number-lines.lua
应包含上面的 Lua 代码并放在与您的文档相同的文件夹中,或者放在 pandoc 数据目录下的 filters
文件夹中(参见 pandoc -v
).
这种方法的优点是它适用于 HTML 以及 PDF 输出。