[英]How to get pandoc lua filter avoid counting words using this pattern in code blocks inside Rmarkdown file?
这是这篇文章的后续问题。 我想要实现的是避免计算标题和具有这种模式的内部代码块中的单词:
```{r label-name}
all code words not to be counted.
```
而不是这种模式:
```
{r label-name}
all code words not to be counted.
```
因为当我使用后一种模式时,我在 emacs 的 Rmarkdown 缓冲区中丢失了字体化锁,所以我总是使用第一种模式。
考虑这个 MWE:
MWE (MWE-wordcount.Rmd)
# Results {-}
## Topic 1 {-}
This is just a random text with a citation in markdown \@ref(fig:pca-scree)).
Below is a code block.
```{r pca-scree, echo = FALSE, fig.align = "left", out.width = "80%", fig.cap = "Scree plot with parallel analysis using simulated data of 100 iterations (red line) suggests retaining only the first 2 components. Observed dimensions with their eigenvalues are shown in green."}
knitr::include_graphics("./plots/PCA_scree_parallel_analysis.png")
```
## Topic 2 {-}
<!-- todo: a comment that needs to be avoided by word count hopefully-->
结果应该只有 17 个字。 不计算代码块、注释或 Markdown 标记(如标题)中的单词。
我按照这里解释的方法使用 lua 过滤器让 pandoc 计算单词数。 总之我做了这些步骤:
从命令行:
mkdir -p ~/.local/share/pandoc/filters
然后在那里创建了一个名为wordcount.lua
的文件,内容如下:
-- counts words in a document words = 0 wordcount = { Str = function(el) -- we don't count a word if it's entirely punctuation: if el.text:match("%P") then words = words + 1 end end, Code = function(el) _,n = el.text:gsub("%S+","") words = words + n end, } function Pandoc(el) -- skip metadata, just count body: pandoc.walk_block(pandoc.Div(el.blocks), wordcount) print(words.. " words in body") os.exit(0) end
我将以下 elisp 代码放在临时缓冲区中并对其进行了评估:
(defun pandoc-count-words () (interactive) (shell-command-on-region (point-min) (point-max) "pandoc --lua-filter wordcount.lua"))
从 MWE Markdown 文件 (MWE-wordcount.Rmd) 中,我发出了Mx pandoc-count-words
并在迷你缓冲区中获得了计数。
使用第一个模式我得到 62 个单词。
使用第二种模式我得到 22 个单词,更合理。 这种方法成功地避免了对评论中的单词进行计数。
问题
如何获得 lua 过滤器代码避免使用第一个模式而不是第二个模式来计算单词?
如何获得 lua 过滤器避免计算标题中的单词##?
如果答案解释了 lua 代码的工作原理,我也将不胜感激。
这是一个有趣的问题,它结合了很多技术。 这里最重要的是 R Markdown,我们需要深入了解到底发生了什么。
R Markdown 处理的第一步之一是解析文档,找到所有 R 代码块(由{r...}
模式标记),执行这些块,并用评估结果替换块。修改后的输入文本是然后传递给 pandoc,后者将其解析为抽象文档树 (AST)。在 pandoc 以目标格式写入文档之前,可以使用过滤器检查或修改 AST。
这是相关的,因为识别表单输入的是 R Markdown,而不是pandoc
``` {r ...}
# code
```
作为代码块,而 pandoc 将它们解析为与` {r...} # code `
code`相同的内联代码,即代码中的所有换行符都被忽略。 原因在于 pandoc 的属性解析和 Markdown 语法中`
chars 的重载。¹
这给了我们第一个问题的答案:我们不能! 这两个代码片段在到达 pandoc 的 AST 中的过滤器时看起来完全相同; 他们无法区分。 但是,如果我们运行 R Markdown 的knitr步骤来执行代码,我们将获得带有换行符的正确代码块。
因此,一种解决方案可能是使wordcount.lua
过滤器成为 R Markdown 处理步骤的一部分,但仅在设置COUNT_WORDS
环境变量时运行过滤器。 我们可以通过将此片段添加到过滤器文件的顶部来做到这一点:
if not os.getenv 'COUNT_WORDS` then
return {}
end
有关如何 集成过滤器的信息,请参阅 R Markdown 食谱。
我省略了第二个问题,因为这个答案已经很长了,那个子问题值得单独发帖。
¹:如果r
前面有一个点,pandoc 会将其识别为代码块,如
``` {.r}
# code
```
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.