我目前有用 Plain TeX 编写的以下代码:
\loadtoks\END
int main(void)
{
printf("Hello World! %!@#$%&*&^\n");
}
\END
{\tt\the\toks0}
\bye
这个宏\loadtoks
是我自己写的。它将每个 ASCII 字符的 catcode 设置为 12,这样特殊字符现在就只是普通字符了,然后它会向前扫描以查找给定的 \END 标记。在扫描过程中,它会将找到的每个标记附加到 \toks0 寄存器中。例如,也可以执行 ,\loadtoks+Hello World+
在这种情况下,结束标记将是+
。它的内部情况比这更复杂一些,但这基本上就是它的要点。
现在,我需要做的是:
\loadtoks\END
\input file.txt
\END
{\tt\the\toks0}
\bye
当然,这只是简单地排版单词“\input file.txt”,而不是读入文件。但自然而然,我需要它做的是实际读入文件,并表现得好像文件的内容实际上已经直接输入到 TeX 源文件中(如第一个示例中所示)。
我已经为此绞尽脑汁一段时间了,但似乎无法弄清楚。请注意,我知道 LaTeX 的 \verb,但我严格使用 Plain TeX,我很想找到一种仅使用 TeX 的纯宏和原始宏的解决方案。
答案1
我将尝试回答这个长期未回答的问题。这个问题的问题是宏\loadtoks
未显示。这让我们想起了本网站经常提到的 MWE。
我尝试估算你的神秘且未公开的宏\loadtoks
。我的意思是,你将所有 catcode 设置为 12(其他),并且第一个参数(\END
在示例中)由处理\string
并作为分隔符。这意味着:
\newcount\tmpnum
\def\loadtoks#1{\bgroup \tmpnum=32
\loop\advance\tmpnum by1 \ifnum\tmpnum<128 \catcode\tmpnum=12 \repeat
\obeylines \obeyspaces
\expandafter\def\expandafter
\loadtoksA\expandafter##\expandafter1\string#1{\egroup\toks0={##1}}%
\loadtoksA
}
{\obeyspaces\global\let =\ }
\loadtoks\END
int main(void)
{
printf("Hello World! %!@#$%&*&^\n");
}
\END
{\tt\the\toks0}
\bye
有效。现在,您的问题是关于读取外部文件。首先,恕我直言,在传统 TeX 中通过扫描整个文件内容作为参数来做到这一点是不可能的。File ended while scanning
出现错误,并且无法在文件末尾放置某些内容作为分隔符。如果您坚持使用传统 TeX,则需要使用带有\read
原语的循环,并且必须使用测试逐行读取文件\ifeof
。
但是,如果您使用的是 eTeX,那么您可以通过 tokens 寄存器将 tokens 放在文件末尾之后\everyeof
。因此,您需要做的就是处理分隔符\string
并\everyeof
写入一些\expandafter
s:
\everyeof \expandafter{\string\END}
\expandafter\loadtoks\expandafter\END
\input file.txt
{\tt\the\toks0}
\bye
编辑:\expandafter
删除一个多余的。
答案2
借助 包,可以将文件内容加载到宏中catchfile
。由于 ,该包需要 e-TeX \everyeof
。
具有可见空间的示例:
\input catchfile.sty\relax
\CatchFileDef\MyFileContents{file.txt}{%
\def\do#1{\catcode`#1=12 }%
\dospecials
\obeylines
}
{\tt\MyFileContents}
\bye
不可见空格的示例:
\input catchfile.sty\relax
\CatchFileDef\MyFileContents{file.txt}{%
\def\do#1{\catcode`#1=12 }%
\dospecials
\obeylines
\obeyspaces
}
\begingroup
\def\temp#1{\endgroup
\def\DefActiveSpace{\def#1}%
}%
\catcode`\ =\active
\temp{ }
{\tt\DefActiveSpace{\ }\MyFileContents}
\bye