在 Knuthian-TeX 中,我想要一个宏,它可以切换到 verbatim-category-code-régime,然后调用另一个宏,该宏逐个处理当前输入文件中的字符,直到到达当前输入文件的末尾。
就像是:
\def\initprocessloop
{%
\begingroup
\catcode`\\=12 \catcode`\{=12 \catcode`\}=12 \catcode`\$=12 %
\catcode`\&=12 \catcode`\#=12 \catcode`\^=12 \catcode`\^^M=12 %
\catcode`\^^I=12 \catcode`\_=12 \catcode`\^^A=12 \catcode`\%=12 %
\catcode`\~=12 \catcode`\ =12 \processloop
}
\def\processloop #1%
{%
There is the character ``\string#1.''
\if⟨end of current input-file is not reached⟩%
\expandafter\processloop\else\expandafter\endgroup\fi
}
问题:
是否有可能在 Knuthian-TeX 中实现测试?\if⟨end of current input-file is not reached⟩..\else..\fi
我思考在 eTeX 中我可以使用\everyeof
这个,但我明确要求使用 Knuthian-TeX。
我不想使用它,\read
因为\read
它会连续读取尽可能少的括号平衡行集,并且每当读取这样的集合时就会定义一个宏,而我并不真正需要它,因此认为这是浪费内存。
答案1
由于文件的结尾是\outer
(grrr),你不能用宏参数绕过它,但你可以使用它\let
,通过一些未记录的限制,你可以报告文件
abc
123
\hbox{123}
作为
the letter a
the letter b
the letter c
the character ^^M
the character 1
the character 2
the character 3
the character ^^M
the character \
the letter h
the letter b
the letter o
the letter x
the character {
the character 1
the character 2
the character 3
the character }
the character ^^M
使用
\def\zz{\afterassignment\zzz\let\tmp= }
\def\zzz{\ifx\tmp\endgroup\endgroup\else\zzzz\expandafter\zz\fi}
\def\zzzz{\immediate\write20{\meaning\tmp}}
\def\setup#1{%
\begingroup
\catcode`\^^M=12 %
\catcode`\\=12 %
\catcode`\{=12 %
\catcode`\}=12 %
\catcode`\ =12 %
\catcode`\%=12 %
\expandafter\zz\input #1 %
\endgroup
}
\setup{\jobname.txt}
\bye
答案2
您希望宏检测文件的结尾\input
?
TeXbook,第 20 章:定义(也称为宏),说:
[...] 当宏定义前面带有 时
\outer
,相应的控制序列将不允许出现在任何正在高速吸收令牌的地方。宏\outer
不能出现在参数 [...] 中,也不能出现在定义的参数文本或替换文本中,也不能出现在对齐的前言中,也不能出现在被跳过的条件文本中。
如果\outer
宏确实出现在这些地方,TeX 会停止正在执行的操作并报告“失控”情况或“不完整”条件。输入文件的结尾或对齐模板也被认为是\outer
这个意义的;[...]
\if..
我怀疑在 Knuthian-TeX 中仅通过纯可扩展例程(例如,完全可扩展的宏或条件)来检测输入文件的结尾是可能的。
我建议使用一个可以利用 ε-TeX 扩展的引擎,并且\everyeof
可以用它来放入绝对不是逐字逐句的标记,因此可以被生成出来。
我认为按字符处理大型输入文件可能需要一些时间。
从 TeXbook 第 20 章中可以推断出 - 与 TeX 抓取宏参数/定义的参数文本/定义的替换文本/对齐的前言/要跳过的条件文本的机制不同 - TeX 的分配机制\futurelet
不会干扰文件结尾的事实\outer
。
因此,人们可以\futurelet
在使用宏抓取参数之前,滥用这种方法来摆脱文件的结尾。
当然,这意味着\futurelet
在每次获取参数的迭代中都有一个-assignment,所以这可能不是您想要的,但是为了完整性而提出这个技巧。
示例文件样本通过以下方式逐字处理\input
:
abc
123
\hbox{123}
\input
处理-file verbatim的代码:
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\initprocessloop#1%
{%
\begingroup
\catcode`\\=12 \catcode`\{=12 \catcode`\}=12 \catcode`\$=12 %
\catcode`\&=12 \catcode`\#=12 \catcode`\^=12 \catcode`\^^M=12 %
\catcode`\^^I=12 \catcode`\_=12 \catcode`\^^A=12 \catcode`\%=12 %
\catcode`\~=12 \catcode`\ =12 %
\expandafter\futurelet\expandafter\scratchy\expandafter\processloop\input"#1"\relax
}%
\begingroup
\endlinechar=-1 % <- ends of lines will not yield spaces with this setting.
\catcode`\^^M=12 \catcode`\^^I=12 \catcode`\^^A=12 %
\firstoftwo{
\endgroup
\def\processloop#1
{
\ifx\relax#1\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\endgroup}{
\par There is the %
\if\string#1^^Mreturn character\else
\if\string#1^^Ihorizontal tab character\else
\if\string#1^^Astart of heading character\else
character ``{\tt\string#1}''
\fi
\fi
\fi
.
\futurelet\scratchy\processloop
}
}
}{}%
%%
\initprocessloop{sample.tex}
\bye
pdf 输出: