内容提要
knitr 的 spin() 功能可将带 #' 注释的普通脚本转为报告。近期更新:新增 engine 参数,按文件扩展名自动推断语言;新增 roxygen 参数,避免与 roxygen2 文档标签冲突;修复标签与引擎名粘连问题,使 purl 与 spin 可干净往返;改进 # /* */ 删除块的配对检查,报告未匹配行号。
延伸解读
engine 参数:让 spin() 支持多语言脚本
新增的 engine 参数可为所有代码块设置默认引擎,避免在每个块中重复写 #+ engine="python"。若不设置,spin() 会根据文件扩展名自动推断语言,例如 .py 文件直接按 Python 处理。单个块若显式指定引擎,仍会覆盖默认值。这一改进使 spin() 不再局限于 R,成为语言无关的脚本转报告工具。
roxygen 参数:解决 #' 注释的用途冲突
spin() 原本将 #' 行视为正文,但 roxygen2 也用 #' 写文档标签(如 @param)。若脚本同时用于包文档,这些标签会被错误转为正文,破坏 roxygen 解析。设置 roxygen = TRUE 后,包含 roxygen 标签的连续 #' 块会原样保留在代码块中,无标签的块仍作为文档处理。这样同一文件既能 spin 成报告,也能被 roxygen2 正常解析。
purl 与 spin 往返:修复标签粘连问题
purl(documentation = 2) 会输出 ## ----label 形式的块标签,spin() 需读取这些标签。此前 spin() 会把标签直接粘到引擎名后,生成无效头 ```{rlabel},导致再次 purl() 时 rlabel 被误认为引擎名,块内容被破坏。现在 spin() 会补上缺失空格,输出 ```{r label},使 purl() → spin() → purl() 能干净往返。
删除块配对检查:避免静默吞内容
spin() 用 # /* 和 # */ 标记要删除的行块。旧实现只比较起止定界符的数量,若出现顺序颠倒(结束符在开始符之前),中间内容可能被静默删除。现在它会检查定界符是否正确配对和排序,并报告未匹配定界符的行号,而不是悄悄吞掉内容。这有助于在脚本中快速定位并修正错误。
Q&A
knitr 的 spin() 功能是做什么的?
spin() 是 purl() 的反向操作,它把带有 #' 注释(用于散文)和 #+ 注释(用于代码块选项)的普通脚本转换成完整报告。
spin() 新增的 engine 参数有什么作用?
engine 参数用于为所有代码块设置默认引擎。如果未设置,则根据文件扩展名自动推断语言,例如 .py 文件会按 Python 处理。代码块自身设置的引擎会覆盖默认值。
spin() 的 roxygen 参数解决了什么问题?
roxygen 参数解决了 spin() 与 roxygen2 的冲突。当设置为 TRUE 时,包含 roxygen 标签(如 @param)的连续 #' 行块会原样保留在代码块中,而不是被转换为散文,从而让同一文件既能作为可 spin 的报告,又能被 roxygen2 解析。
spin() 如何修复了与 purl() 往返时标签粘连的问题?
purl(documentation = 2) 会生成 ## ----label 形式的块标签,spin() 读取时之前会将标签直接粘到引擎名上,产生无效头部如 ```{rlabel}。现在 spin() 会插入缺失的空格,生成 ```{r label},使得 purl() → spin() → purl() 可以干净地往返。
spin() 对 # /* */ 删除块的配对检查做了哪些改进?
以前只比较开始和结束分隔符的数量,可能因顺序错误而静默吞掉内容。现在会检查分隔符是否正确配对和排序,并报告未匹配分隔符的行号,而不是悄悄删除内容。
spin() 现在支持哪些语言?
spin() 现在支持多种语言,通过 engine 参数或文件扩展名自动推断。例如,.py 文件会按 Python 处理,不再需要为每个代码块手动指定 engine="python"。