我有一个memoir
包含我博士论文的文档。我想自动为每一章创建一个单独的 PDF,以及一个主 PDF。我发现这 arara
规则,这似乎正是我想要的。但是,格式与arara
4.0 不兼容。主要问题似乎是可以将其用作items
参数,然后会自动进行迭代(?)。
arara
4.0 不接受此items
参数。我能够定义一个新参数chapters
,并对其进行迭代。但我不知道如何在 MVEL(?)环境中编译新的 PDF。
这是我目前的代码。它首先编译整个文档,然后遍历chapters
,打印它们的名称(第 9 行)。目标是改为在第 9 行运行以下命令。
- <arara> @{engine} "\includeonly{@{chapter}}\input{@{chapter}}"
!config
identifier: makechapters
name: MakeChapters
commands:
- command: <arara> @{ isTrue( compileAll, engine.concat(' ').concat(file) )}
- command: >
@{
foreach (chapter : chapters) {
System.out.println(chapter)
}
}
arguments:
- identifier: engine
flag: <arara> @{parameters.engine}
default: xelatex
- identifier: compileAll
flag: <arara> @{parameters.compileAll}
default: true
- identifier: chapters
flag: <arara> @{parameters.chapters}
default: []
答案1
我认为这可能是我们规则的一个良好开端:
!config
identifier: makechapters
name: MakeChapters
commands:
- name: Making chapters
command: >
@{
if (compile == 'all') {
return getCommand(engine, file);
}
else {
entries = [];
base = getBasename(file);
foreach (chapter: chapters) {
entries.add(getCommand(engine, '\\includeonly{' + chapter +
'}\\input{' + base + '}'));
}
return entries;
}
}
arguments:
- identifier: engine
flag: >
@{
if ([ 'pdflatex', 'latex', 'xelatex',
'lualatex' ].contains(parameters.engine)) {
return parameters.engine;
}
else {
throwError('The provided engine is not valid');
}
}
default: xelatex
- identifier: compile
flag: >
@{
if ([ 'all', 'chapters' ].contains(parameters.compile)) {
return parameters.compile;
}
else {
throwError('I was expecting "all" or "chapters".');
}
}
default: 'all'
- identifier: chapters
flag: >
@{
if (isList(parameters.chapters)) {
return parameters.chapters;
}
else {
throwError('I was expecting a list of chapters.');
}
}
让我们分解一下:
!config
identifier: makechapters
name: MakeChapters
这些是标题,没有什么新内容。:)
commands:
现在我们正在创建命令(实际上,只有一个,我们马上就会看到)。
- name: Making chapters
command: >
@{
这就是我们的统治的核心。
if (compile == 'all') {
return getCommand(engine, file);
}
我决定创建compile
一个字符串变量而不是布尔变量,这样我们就可以为它指定两个值:all
,以防我们想要编译文档,或者chapters
,以防我们想要编译每个章节。
else {
现在我们处于else
分支内,即我们将单独编译每个章节。
entries = [];
base = getBasename(file);
该entries
变量将保存一个命令列表,每个命令对应一个章节,并且该base
变量保存当前引用的基本名称file
。
foreach (chapter: chapters) {
entries.add(getCommand(engine, '\\includeonly{' + chapter +
'}\\input{' + base + '}'));
}
请注意,它chapters
包含一个字符串列表,因此我们可以迭代这些值,并且对于每个值,我们都使用您之前提供的结构创建一个相应的命令(请注意,我必须转义反斜杠)并添加到列表中。
return entries;
}
}
现在我们只需返回命令列表并完成arara
剩下的工作。
检查参数的时间:
arguments:
我们走吧!
- identifier: engine
flag: >
@{
if ([ 'pdflatex', 'latex', 'xelatex',
'lualatex' ].contains(parameters.engine)) {
return parameters.engine;
}
else {
throwError('The provided engine is not valid');
}
}
default: xelatex
这里没有什么新内容,我只是添加了一个检查以确保该值在有效引擎名称列表中。
- identifier: compile
flag: >
@{
if ([ 'all', 'chapters' ].contains(parameters.compile)) {
return parameters.compile;
}
else {
throwError('I was expecting "all" or "chapters".');
}
}
default: 'all'
与前一个论点的想法相同,我检查compile
在指定时是否包含all
或chapters
。
- identifier: chapters
flag: >
@{
if (isList(parameters.chapters)) {
return parameters.chapters;
}
else {
throwError('I was expecting a list of chapters.');
}
}
最后,但并非最不重要的一点是,我们确保chapters
这是一份真实的清单。:)
让我们看看这个规则的实际作用(通过--dry-run
)。
标头:
% arara: makechapters: { chapters: [ foo, bar ], compile: 'chapters' }
输出:
[DR] (MakeChapters) Making chapters
-----------------------------------------------------------------
Authors: No authors provided
About to run: [ xelatex, \includeonly{foo}\input{foo} ]
[DR] (MakeChapters) Making chapters
-----------------------------------------------------------------
Authors: No authors provided
About to run: [ xelatex, \includeonly{bar}\input{bar} ]
标头:
% arara: makechapters: { engine: pdflatex }
输出:
[DR] (MakeChapters) Making chapters
-----------------------------------------------------------------
Authors: No authors provided
About to run: [ pdflatex, test.tex ]
希望对您有所帮助。:)
我不确定单独编译每个章节的技巧(说实话,我以前从未见过),但这就是我的想法。也许建议也-jobname
为底层引擎进行设置?