我正在尝试将逐字文本写入 Plain TeX 文件中。在 LaTeX 中,我可以使用包。我的目标是在 Plain TeX 中使用 Asymptote。所以我需要一些像fromverbatim
一样的东西。\verbatim@start
verbatim.sty
梅威瑟:
% Plain LuaTeX
\catcode`@=11
% from latex.ltx
\long\def\@ifnextchar#1#2#3{%
\let\reserved@d=#1%
\def\reserved@a{#2}%
\def\reserved@b{#3}%
\futurelet\@let@token\@ifnch}
\def\@ifnch{%
\ifx\@let@token\@sptoken
\let\reserved@c\@xifnch
\else
\ifx\@let@token\reserved@d
\let\reserved@c\reserved@a
\else
\let\reserved@c\reserved@b
\fi
\fi
\reserved@c}
\def\:{\let\@sptoken= } \: % this makes \@sptoken a space token
\def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch}
\def\@makeother#1{\catcode`#1=12\relax}
Let's try to write.
\newwrite\file
\immediate\openout\file=temp.tmp\relax
\def\verbatimwrite{\begingroup\catcode`\^^M=12\relax
%\let\do\@makeother\dospecials%%%%%%% PROBLEM! (A)
\@verbatimwrite}
\begingroup
\catcode`\^^M=12 %
\gdef\@verbatimwrite#1^^M{% Every line must be written separately to save the line breaks.
\immediate\write\file{\unexpanded{#1}}%
\@ifnextchar\endverbatimwrite\endgroup\@verbatimwrite}% detect the end of verbatim (B)
\endgroup
\let\endverbatimwrite\relax
\verbatimwrite
123#;^{t}
äöüß
4567\undefined
\endverbatimwrite
\immediate\closeout\file
\bye
有2个问题(也作为代码中的注释):
- (A):我必须在哪里更改所有其他 catcode?例如,应该可以编写不平衡的括号。如果操作正确,我认为
\unexpanded
不再需要该命令。 - (B):您知道如何提高 的检测率吗
\endverbatimwrite
?我觉得我的方法真的很差。
谢谢。
答案1
你改变 catcode 的时机恰到好处。问题是,\let\do\@makeother \dospecials
guard后面\endverbatimwrite
不再是控制序列,而是反斜杠字符加上 16 个字母的序列。这导致你的代码失败,因为你的\@ifnextchar
测试寻找控制序列 \endverbatimwrite
,但从未被找到。
至于检测\endverbatimwrite
,您不需要在每一行之后搜索它(您可以,但您不必这样做)。最大的问题还是由于 catcode 的变化:您不再有 ,而是 ,\endverbatimwrite
这\
e
n
d
v
e
r
b
a
t
i
m
w
r
i
t
e
完全不同(并且更难找到\@ifnextchar
;您需要某种循环,或多或少像listings
检测环境的结束一样)。定义一个查找字符串的分隔宏要容易得多\endverbatimwrite
检测环境的结束一样)。定义一个分隔宏来查找具有正确 catcode 的
通常,逐字环境的算法(当然是简单的算法)是:1)获取参数(可选参数,要写入的文件名,或者在本例中是写入流);2)\begingroup
;3)\catcode
s;4)获取命令/环境的内容;5)\endgroup
并处理抓取的字符(最后两个的顺序可能有所不同)。
这是代码的修改版本(基于其中一些形式这里):
\catcode`@=11
\def\@makeother#1{\catcode`#112\relax}
\def\verbatimwrite#1{%
\begingroup
\catcode`\^^M=13
\newlinechar`\^^M
\let\do\@makeother \dospecials
\verbwrite@cleanup#1}
\begingroup
\lccode`\?=`\\
\lowercase{\endgroup% \
\def\verbwrite@other#1#2?endverbatimwrite{%
\immediate\write#1{\unexpanded\expandafter
{\verbwrite@strip@newline#2\relax}}%
\endgroup}}
\begingroup
\catcode`\^^M=13
\gdef\verbwrite@cleanup#1#2^^M{%
\if\relax\detokenize{#2}\relax
\else \errmessage{Wrong input `#2' discarded}%
\fi
\verbwrite@other#1}
\gdef\verbwrite@strip@newline#1^^M\relax{#1}
\endgroup
Let's try to write.
\newwrite\file
\immediate\openout\file=temp.tmp\relax
\verbatimwrite\file
123#;^{t}
äöüß}
4567\undefined{
\endverbatimwrite
\immediate\closeout\file
\bye
输出文件包含:
123#;^{t}
äöüß}
4567\undefined{