让 latexmk 同时处理 .tex 和 .Rnw 文件

让 latexmk 同时处理 .tex 和 .Rnw 文件

系统信息

  • 薄荷 19.2
  • latexmk 4.41
  • pdfTeX 3.14159265-2.6-1.40.18(TeX Live 2017/Debian)

目标

我正在尝试设置我的 .latexmkrc 配置,以便它检测传递的文件是否是 .Rnw 文件,如果是,则在编译成 .pdf 之前将其编织起来。

试图

我发现了一个博客文章这表明以下.latexmkrc 文件:

@default_files = ("*.Rnw");
$pdf_mode = 1;
$graphicx_opts = "final";
$color_opts = "usenames,dvipsnames";
$pdflatex = '([[ ! "%T" =~ \.Rnw$ ]] || Rscript -e "'.
'library(knitr);' .
'opts_knit\$set(latex.options.graphicx = \"' .
$graphicx_opts .
'\", latex.options.color = \"' .
$color_opts .
'\", concordance = TRUE); ' .
'knit(\'%B.Rnw\');" ' .
') && pdflatex -shell-escape -synctex=1 %O %B ' .
'&& ([[ ! "%T" =~ \.Rnw$ ]] || Rscript -e "' .
'library(patchSynctex); ' .
'patchSynctex(\'%B\', verbose = TRUE);")'
;

我唯一添加的是-synctex=1标志,因为我发现否则在我的系统上将不会生成 synctex 文件并且最后的命令patchSynctex将会失败。

问题 1

它似乎不适用于标准.tex文件。我认为这是因为第一部分没有$pdflatex正确检查文件是否为 .Rnw?

$latexmk plain-example.tex
Latexmk: This is Latexmk, John Collins, 1 January 2015, version: 4.41.
Latexmk: applying rule 'pdflatex'...
Rule 'pdflatex': File changes, etc:
   Non-existent destination files:
      'plain-example.pdf'
------------
Run number 1 of rule 'pdflatex'
------------
------------
Running '([[ ! ""plain-example.tex"" =~ \.Rnw$ ]] || Rscript -e "library(knitr);opts_knit\$set(latex.options.graphicx = \"final\", latex.options.color = \"usenames,dvipsnames\", concordance = TRUE); knit('"plain-example".Rnw');" ) && pdflatex -shell-escape -synctex=1  -recorder  "plain-example" && ([[ ! ""plain-example.tex"" =~ \.Rnw$ ]] || Rscript -e "library(patchSynctex); patchSynctex('"plain-example"', verbose = TRUE);")'
------------
sh: 1: [[: not found
Error in file(con, "r") : cannot open the connection
Calls: knit -> readLines -> file
In addition: Warning message:
In file(con, "r") :
  cannot open file 'plain-example.Rnw': No such file or directory
Execution halted
Latexmk: Errors, so I did not complete making targets
Collected error summary (may duplicate other messages):
  pdflatex: (Pdf)LaTeX failed to generate the expected log file 'plain-example.log'
Latexmk: Did not finish processing file 'plain-example.tex':
   (Pdf)LaTeX failed to generate the expected log file 'plain-example.log'
Latexmk: Use the -f option to force complete processing,
 unless error was exceeding maximum runs of latex/pdflatex.

我对 shell 脚本了解甚少,因此这可能很明显。

问题 2

它似乎在简单的 Rnw 文件上运行良好,比如这个,它是我从Overleaf 的解释

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}

\begin{document}

You can type R commands in your \LaTeX{} document and they will be properly run and the output printed in the document.

<<>>=
# Create a sequence of numbers
X = 2:10

# Display basic statistical measures
summary(X)

@

<<summary_plot, fig.height=8>>=
plot(sin, -pi, 2*pi)
@

\end{document}

在此文件上运行 latexmk 似乎工作正常,特别是 latexmk 最终终止。

然而,在更复杂的例子中,latexmk 似乎永远不会终止。例如,在这篇博文有一个相当复杂的文件knitr-example.Rnw叫做链接到这里。如果我尝试运行latexmk knitr-example.Rnw,latexmk 似乎永远不会干净地终止,除非达到 pdflatex 的最大运行次数。

我猜想第二个问题可能也是由第一个问题引起的?如果 shell 脚本中的控制流无法正常工作?


编辑

这是一个部分解决方法,虽然不是很好,但对于我目前的目的来说似乎没问题。这个想法就是让 latexmk 调用另一个 bash 脚本。

我修改了latexmkrc文件使其看起来像这样:

@default_files = ("*.Rnw", "*.tex");
$pdf_mode = 1;
$graphicx_opts = "final";
$color_opts = "usenames,dvipsnames";
$pdflatex = 'knitr-pdflatex.sh "%T" "%B" "%O"';

然后我编写了一个简单的 bash 脚本,knitr-pdflatex.sh如下所示:

#!/bin/bash
if [ ${1: -4} == ".Rnw" ]
then
    rcommand="library(knitr);"
    rcommand+="opts_knit\$set("
    rcommand+="latex.options.graphicx='final',"
    rcommand+="latex.options.color='usenames,dvipsnames',"
    rcommand+="concordance=TRUE);"
    rcommand+="knit('$1');"
    Rscript --verbose -e $rcommand
fi

pdflatex -shell-escape -synctex=1 $3 $2

if [ ${1: -4} == ".Rnw" ]
then
    rcommand="\"library(patchSynctex);"
    rcommand+="patchSynctex('$2',verbose=TRUE);\""
    Rscript --verbose -e $rcommand
fi

这“解决”了导致 1 的所有语法问题。

问题 2 仍然存在。我认为这是因为如果 knitr 没有缓存图像文件,那么每次运行 $pdflatex 时都会重新生成它们。latexmk 注意到引用的 .pdf 文件(图像)已更改,然后重新运行。这会产生无限循环。我的“解决方案”再次不是解决方案——我只是打开了缓存,这样就不会重新创建已创建的图像。

我还是想知道解决这两个问题的正确方法!

答案1

配置在程旭的帖子对我有用。我将以下代码附加到我的.latexmkrc并运行latexmk -pdf -pvc [filename].Rnw,pdf 成功编译:

# only enable when compiling .Rnw or .Rtex file
if(grep(/\.(rnw|rtex)$/i, @ARGV)) {
    $latex = 'internal knitrlatex ' . $latex;
    $pdflatex = 'internal knitrlatex ' . $pdflatex;
    my $knitr_compiled = {};
    sub knitrlatex {
        for (@_) {
            next unless -e $_;
            my $input = $_;
            next unless $_ =~ s/\.(rnw|rtex)$/.tex/i;
            my $tex = $_;
            my $checksum = (fdb_get($input))[-1];
            if (!$knitr_compiled{$input} || $knitr_compiled{$input} ne $checksum) {
                my $ret = system("Rscript -e \"knitr::knit('$input')\"");
                if($ret) { return $ret; }
                rdb_ensure_file($rule, $tex);
                $knitr_compiled{$input} = $checksum;
            }
        }
        return system(@_);
    }
    # clean up generated .tex file when running `latexmk -c <root_file>`
    $clean_ext .= ' %R.tex';
}

我仍在尝试理解代码,并且不确定此配置是否能解决您的问题,但希望这能为您提供一些线索。干杯!

相关内容