龙的踪迹

龙的踪迹

假设我*.tex在名为的子目录中有一些文件SourceFiles,当且仅当此子目录中的任何 tex 文件发生更改时,我该如何让 arara 编译该文档?

我试过

% arara: lualatex if changed (toFile(
% arara: --> listFilesByExtensions( toFile('/SourceFiles'), [ 'tex' ], false)
% arara: --> ))

但我收到了这个错误

[错误:未找到空指针或函数:listFilesByExtensions] [附近:{... || 已更改(toFile(listFilesByExtensions(toFile(....}]

答案1

是的,没错:listFilesByExtensions在指令上下文中不可用,仅在规则范围内可用。此外,如果评估设法到达外部函数调用,则会出现另一个问题:changed一次仅支持单个文件,而不是文件列表。

在您的特定场景中,典型的解决方案是编写适当的规则。团队正在讨论,在未来版本中,采用一种功能路线,以便在指令范围内允许all诸如any和 之类的高级构造。none

这是该团队的官方回应。:)

话虽如此...

龙的踪迹

还...

吸血鬼的希望,你吸血鬼的希望

有一种非常狡猾的方法可以实现你想要的效果。我将利用表达式语言并通过完整限定名称触发函数调用。这完全不推荐,应该不惜一切代价避免。我认为我们喜欢挑战。:)

该标题应该适合您。

% arara: lualatex if
% arara: --> entries = 
% arara: --> com.github.cereda.arara.utils.Methods.listFilesByExtensions(
% arara: --> toFile('SourceFiles/'), ['tex'], false
% arara: --> );
% arara: --> flag = false;
% arara: --> foreach(entry : entries) {
% arara: -->   flag = changed(entry) || flag;
% arara: --> };
% arara: --> return flag

关于此标头的一些说明:

% arara: lualatex if

这里没有什么新东西,arara当且仅当以下表达式成立时,才会运行引擎。

% arara: --> entries = 
% arara: --> com.github.cereda.arara.utils.Methods.listFilesByExtensions(

现在情况有所不同:首先,我listFilesByExtensions使用表达式语言中的完整限定名称进行调用。然后,此函数的返回值保存在名为的变量中entries

% arara: --> toFile('SourceFiles/'), ['tex'], false
% arara: --> );

这些是参数:目录(我/在开始时删除了,因为它会被解析为从根目录开始的完整路径,而我相信这不是你想要的,并且添加了尾随/只是为了满足我的编码强迫症),扩展列表(在本例中,我们正在寻找.tex文件)和一个布尔值,指示搜索是否应该是递归的(在我们的例子中,否)。

% arara: --> flag = false;

我创建了一个名为的布尔变量flag,最初设置为false,它将保存上次搜索产生的任何文件是否已发生改变的指示。

% arara: --> foreach(entry : entries) {
% arara: -->   flag = changed(entry) || flag;
% arara: --> };

现在这是一个循环,用于检查上一次搜索产生的每个文件。观察到它changed位于操作的左侧||。这不是一个表面选项,它有更深层的含义:如果我把它放在changed右侧,短路可能会在flag保留的情况下保存一个调用true,因此从该迭代开始文件数据库将不再更新。

% arara: --> return flag

现在,flag指示是否有任何文件已更改,因此编译将基于该决定。由于它是表达式中的最后一条语句,因此无论如何都会返回它,但我喜欢让事情更明确、更冗长、更复杂,因为我们不喜欢复杂的事情。:)

基本上就是这样。恭喜,您已使保修失效!:)

希望能帮助到你!:)


附录:注释中显示的标头至少有两个问题:第一个与语法有关,第二个与语义有关。第二个标头恰好起作用,因为短路会导致某些文件的状态不更新。这可能是对两个标头的修复:

标题 1

% arara: lualatex: { options: [ '-synctex=1',
% arara: --> '-shell-escape','-interaction=nonstopmode' ]} 
% arara: --> if 
% arara: --> flag = changed(currentFile());
% arara: --> entries = 
% arara: --> com.github.cereda.arara.utils.Methods.listFilesByExtensions(
% arara: --> toFile('SourceFiles/'), ['tex'], false
% arara: --> );
% arara: --> foreach(entry : entries) {
% arara: -->   flag = changed(entry) || flag;
% arara: --> };
% arara: --> flag = missing('log') || flag;
% arara: --> flag = missing('aux') || flag;
% arara: --> flag = (exists('log') && found ('log','(Undefined control sequence|Error)')) || flag;
% arara: --> return flag

标题 2

% arara: lualatex: { options: [ '-synctex=1',
% arara: --> '-shell-escape','-interaction=nonstopmode' ]} 
% arara: --> if
% arara: --> entries = 
% arara: --> com.github.cereda.arara.utils.Methods.listFilesByExtensions(
% arara: --> toFile('SourceFiles/'), ['tex'], false
% arara: --> ); flag = false;
% arara: --> foreach(entry : entries) {
% arara: -->   flag = changed(entry) || flag;
% arara: --> };
% arara: --> flag = changed(currentFile()) || flag;
% arara: --> flag = missing('log') || flag;
% arara: --> flag = missing('aux') || flag;
% arara: --> flag = (exists('log') && found ('log','(Undefined control sequence|Error)')) || flag;
% arara: --> return flag

由于该语法利用了表达式语言机制,因此需要一定程度的编程和调整才能正常运行。这就是为什么我认为这是一种实现所需行为的黑客方法。

相关内容