使用 arara 为每个章节渲染单独的 PDF

使用 arara 为每个章节渲染单独的 PDF

我有一个memoir包含我博士论文的文档。我想自动为每一章创建一个单独的 PDF,以及一个主 PDF。我发现 arara规则,这似乎正是我想要的。但是,格式与arara4.0 不兼容。主要问题似乎是可以将其用作items参数,然后会自动进行迭代(?)。 arara4.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在指定时是否包含allchapters

- 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为底层引擎进行设置?

相关内容