pdflatex --help 中的 ARGS 是什么意思?/ mylatexformat 的命令行调用如何工作?

pdflatex --help 中的 ARGS 是什么意思?/ mylatexformat 的命令行调用如何工作?

在研究预编译序言时,通常创建格式文件的命令如下

pdftex -ini -jobname="foo" "&pdflatex" mylatexformat.ltx foo.tex

阅读后pdftex --help,我了解到:

-jobname=STRING         set the job name to STRING
-ini                    be pdfinitex, for dumping formats; this is implicitly
                          true if the program name is `pdfinitex'

其余参数由以下行指定

   or: pdftex [OPTION]... &FMT ARGS

所以FMTpdflatex,并且ARGSmylatexformat.ltx foo.tex

问题:

  • 这里指定了什么ARGS
  • 为什么会导致生成前导码?
  • 另外,文档在哪里?
  • 为什么文档mylatexformat建议对该foo.tex部分使用三重引号?

答案1

命令行格式

tex &FMT ARGS

源自古代,当时 Unix 命令行并不像今天这样常用,并导致了经典的 TeX 行为:读取格式后&FMT,TeX 会扫描第一个字母;如果是,\则将命令行的其余部分解释为文档的第一行。这不完全是您的示例:第一个字母m在您的示例中,因此 TeX 将以下单词(没有空格)解释为文件名并执行\input mylatexformat.ltx。这是一种非常常见的情况;不常见的是,您使用的文件没有\end\dump原语(并且\end\dump原语不会从使用的宏中扩展)。这是 TeX 从命令行的其余部分然后从终端读取下一个数据的情况。文件mylatexformat以 结尾 \expandafter\input\endinput,因此\input调用命令,但其参数未在文件中给出mylatexformat.ltx,因此 TeX 尝试从命令行的其余部分读取参数,这意味着\input foo.tex完成。

关于引号。命令解释器会删除它们,并更详细地解释其中的文本。echo """hello"""例如,尝试 。它会打印hello。但我不知道为什么在文档中推荐它们。

答案2

看来我只需要更仔细地看一下文档。

Usage: pdftex [OPTION]... [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... \FIRST-LINE
   or: pdftex [OPTION]... &FMT ARGS

在 TEXNAME 上运行 pdfTeX,通常会创建 TEXNAME.pdf。在读取 TEXNAME 后,任何剩余的命令都将作为 pdfTeX 输入处理。如果 TEXNAME 的第一行是 %&FMT,并且 FMT 是一个现有的 .fmt 文件,则使用它。否则使用“NAME.fmt”,其中 NAME 是程序调用名称,最常见的是“pdftex”。

或者,如果第一个非选项参数以反斜杠开头,则将所有非选项参数解释为一行 pdfTeX 输入。

或者,如果第一个非选项参数以 & 开头,则下一个单词将作为要读取的 FMT,覆盖所有其他单词。 任何剩余的参数都按上述方式处理。

如果没有指定参数或选项,则提示输入。

换句话说,ARGS是“任何剩余的参数”,这意味着明确地写成

Usage: pdftex [OPTION]... [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... \FIRST-LINE
   or: pdftex [OPTION]... &FMT [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... &FMT \FIRST-LINE

也就是说mylatexformat.ltx变成了文件名[TEXNAME[.tex]],也foo.tex就是[COMMANDS]“作为 pdfTeX 输入处理”。


实验以推断确切的行为(仅限 Linux 上的 TeX Live)

(不参考源代码pdftex-changes.pdf

进行一些实验来了解“命令”如何工作:

echo '\edef\a{' > a.tex
pdftex a.tex 'bc}' </dev/null

出现“失控定义”错误。(这个很清楚:将 \everyeof 和 \endlinechar 与 \scantokens 结合使用

echo '\edef\a{\noexpand' > a.tex
pdftex a.tex 'bc}\message{|\a|}' </dev/null

显示\a已分配bc,这意味着在之后EOF,的命令被作为“TeX 代码行”放置,如下所述。

我们也\noexpand可以使用

echo '\endlinechar=`d\edef\a{' > a.tex
echo 'bc' >> a.tex
echo 'bc\noexpand%' >> a.tex
pdftex a.tex 'bc' '}\message{|\a|}\show' </dev/null

这将输出|⟨space⟩ bcdbcbc ⟨space⟩|,并且\show最后不会显示任何内容或给出任何错误。

如果有多个参数,则用空格连接它们,不是解释为多行 TeX 代码。

(以上相当于执行以下 TeX 代码

\endlinechar=`d\edef\a{ ■¹
bc ■²
bc\noexpand% ■³
⟨EOF⟩
bc ∘⁴ }message{|\a|}\show ■⁵

分析:(每一条代表一条endlinechar

  • ■¹ 已经固定为等同于读取第一行的字符 13。
  • ■² 变成字符d
  • ■³ 被注释掉。
  • ∘⁴ 是不是endlinechar,它只是一个空格。
  • 我们稍后会看看■⁵

我们可以进行更多的实验:

pdftex '\catcode13=12\def~{\show}~' </dev/null

结果是the character ^^M.

这意味着字符代码为 13 的“(未标记的)字符”附加在“伪线”之后。


代码备注mylatexformat.ltx

与之不同的是\edef,诸如\input(原始命令)这样的命令可以跨越 EOF 边界工作:

echo '\message{hello world!!!}' > "hello world.tex"
echo '\input' > a.tex
pdftex a.tex '"hello world.tex"' </dev/null

hello world.tex(这里输入打印消息的内容)

\endinput并且只要它已经位于文件末尾,那么(可扩展)实际上是无用的。


mylatexformat.ltx对文档中的注释进行备注

另一方面,我怀疑三引号的建议是因为 这是在 Windows 中转义命令引号的方法,尽管我还没有测试过。

因此执行的 TeX 代码如下所示

\input "file name.tex"

代替

\input file name.tex

显然后者是行不通的。

另外,正如评论中提到的mylatexformat.ltx

%% Trick lookahead to allow mylatex.ltx and the document filename to be
%% given on the same command line. (initex &latex mylatex.ltx {abc.tex})
\expandafter\input\endinput%
\endinput

因此,诸如

pdftex -ini -jobname="foo" "&pdflatex" mylatexformat.ltx "{foo.tex}"

也可以。


允许获取文件名而无需额外引用

附注:根据上述知识:

  • 在 TeX 代码中,无法区分用户编写的

    pdftex file.tex firstargument secondargument
    

    pdftex file.tex "firstargument" "secondargument"
    

    因为在这两种情况下,参数都与空格连接。

  • 我们可以设计一个函数,\input从命令行给出文件名,而不需要额外的引号,只要文件名是命令行上的完整内容。

    cat > a.tex << 'EOF'
    \catcode `\^^M 2 %
    \def \process {\catcode `\^^M 5 \input {\filename}}%
    \afterassignment \process %
    \edef \filename {\noexpand%
    EOF
    
    # alternatively:
    cat > a.tex << 'EOF'
    \catcode `\^^M 12 %
    \def \process #1^^M{\catcode `\^^M 5 \input {#1}}%
    \expandafter \process \noexpand%
    EOF
    
    # then these can be used (as mentioned above, they're equivalent and indistinguishable)
    pdftex a.tex hello world.tex </dev/null
    pdftex a.tex "hello world.tex" </dev/null
    

    如果需要,需要采取额外的预防措施来处理{}处理文件名(可能仅用于学术目的)。

相关内容