系统信息
- 薄荷 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';
}
我仍在尝试理解代码,并且不确定此配置是否能解决您的问题,但希望这能为您提供一些线索。干杯!