这个问题的答案应该很简单,但我似乎找不到如何做。我试图使用\afterassignment
make 语法来制作节标题,然后使用 TeX 的词法分析来\input
包含该文件
\def\section#1;{
\noindent{\bf #1}\par
\afterassignment\xsection
\input
}
\def\xsection{
this text should appear after example.tex's
}
\section SECTION NAME;example
这不起作用,因为分配时,文本 from\xsection
出现在 's 之前。我尝试使用宏来切换两者,其中s 和sexample.tex
混乱不堪。实现此目的的最简洁方法是什么(仅使用原语,或者,如果需要,使用 Plain TeX)?\expandafter
\noexpand
答案1
\input
不执行分配,因此您无法保证何时\afterassignment
插入标记。使用 ε-TeX,您可以使用\everyeof
在输入文件末尾添加标记:
% Example file:
\newwrite\temp
\immediate\openout\temp=example.tex
\immediate\write\temp{Some text\par}
\immediate\closeout\temp
\def\section#1;{%
\noindent{\bf #1}\par
\everyeof{\xsection}%
\input
}
\def\xsection{%
\everyeof{}%
this text should appear after example.tex's%
}
\section SECTION NAME;example
\bye
但是,此代码无法处理嵌套的s ,文件内的\section
任何 s (any ) 都不会触发要插入的标记。如果您使用 like ,那么会容易得多,然后文件名将被抓取为参数,并且您可以更好地控制它。\input
\section
\input
\everyeof
\section SECTION NAME;{example}
回复您的评论,是的,用空格分隔参数有一些缺陷。如果您作为命令的用户表现良好,那么您的空格分隔方法可能在大多数情况下都会有效。但用户不守规矩,这是事实 ;-)
例如,执行 之后\def\ample{ample.tex }
,命令\input ex\ample
将执行您期望的操作,但将其作为空格分隔的参数抓取取决于您在 之后输入的内容\ample
。另一个问题是,某些 TeX 发行版(至少据我所知,TeXLive 和 MiKTeX)允许您输入带空格的文件名,如果您将名称括在引号中,例如\input "example file.tex"
(该实现还允许您\input example" "file.tex
或\input "e"x"a"m"p"l"e "f"i"l"e"."t"e"x"
,并且都输入同一个文件,这有点奇怪)。您的空格分隔方法也不会接受带引号的文件名。
如果您不介意多写几行代码,这里有一种方法(据我测试)几乎 完全模拟了 TeX 的文件名扫描器1。\scanfilename{<code>}<filename>
我定义了一个宏,它<filename>
遵循 TeX 的文件名扫描规则(扩展可扩展标记,在两个 之间的空格处停止"
,忽略所有"
),然后运行<code>
,其中文件名可用作#1
,因此您的定义变得容易得多,因为您可以在抓取文件名后进行控制。另外,它在 Knuth TeX 中有效 :-)
另外,使用这个你可以嵌套多个\section
s 和\input
。
% Example file:
\newwrite\temp
\immediate\openout\temp="example file.tex"
\immediate\write\temp{Some text\par
\noexpand\section Another section;"another example.tex"\par
Yet more text\par}
\immediate\closeout\temp
\immediate\openout\temp="another example.tex"
\immediate\write\temp{More text\par}
\immediate\closeout\temp
\catcode`\@=11
\def\@firstoftwo#1#2{#1}
\def\@secondoftwo#1#2{#2}
\def\bool@flip#1{\ifodd#1\chardef#1=0 \else\chardef#1=1 \fi\relax}
\def\bool@false#1{\chardef#1=0\relax}
\def\bool@true#1{\chardef#1=1\relax}
\def\scanfilename#1{%
\def\filename@action##1{#1}%
\begingroup
\def\curfile{}%
\bool@false\in@quote@bool
\scan@file@name@peek}
\def\file@name@end{%
\edef\file@temp{%
\endgroup
\noexpand\filename@action{\curfile}}\file@temp}
\def\more@name#1{%
\edef\space@action##1{%
\ifodd\in@quote@bool
\noexpand\add@token{##1}%
\else \noexpand\file@name@end
\fi}%
\if\noexpand"\noexpand#1%
\expandafter\@firstoftwo
\else \expandafter\@secondoftwo
\fi
{\bool@flip\in@quote@bool
\add@token{}}%
{\if\space\noexpand#1%
\expandafter\space@action
\else \expandafter\add@token
\fi{#1}}}
\def\add@token#1{%
\toks@\expandafter{\curfile}%
\edef\curfile{\the\toks@#1}%
\afterassignment\scan@file@name@peek
\let\scratch@token= }
\def\scan@file@name@peek{%
\futurelet\peek@token\scan@file@name@next}
\def\q@nil{\q@nil}
\def\scan@file@name@next{%
\token@if@expandable\peek@token
{\expandafter\scan@file@name@peek}
{\edef\sctratch@token{%
\noexpand\dissect@meaning
\meaning\peek@token\space\space\space
\noexpand\q@nil\noexpand\q@stop}%
\sctratch@token}}
\def\token@if@expandable#1{%
\expandafter\ifx\noexpand#1#1%
\expandafter\@secondoftwo
\else \expandafter\@firstoftwo
\fi}
\def\dissect@meaning#1 #2 #3 #4#5\q@stop{%
\pm@strcmp{#2}{}{\unexp@end@name}{}%
\pm@strcmp{#2}{letter}{\add@char@token{#3}}{}%
\pm@strcmp{#2}{character}{\add@char@token{#3}}{}%
\pm@strcmp{#2}{space}{\add@char@token{ }}{}%
\pm@strcmp{#3}{character}{\add@char@token{#4}}{}%
\wrong@char}
\def\wrong@char{\errmessage{Wrong character in file name...}}
\def\unexp@end@name#1\wrong@char{\file@name@end}
\def\add@char@token#1#2\wrong@char{\more@name{#1}}
\def\pm@detokenize#1#2{\def#1{#2}%
\edef#1{\expandafter\strip@prefix\meaning#1}}
\def\strip@prefix#1>{}
\def\pm@strcmp#1#2{%
{\pm@detokenize\tmpa{#1}%
\pm@detokenize\tmpb{#2}%
\expandafter}%
\ifx\tmpa\tmpb
\expandafter\@firstoftwo
\else \expandafter\@secondoftwo
\fi}
\catcode`\@=12
\def\section#1;{%
\noindent{\bf #1}\par
\scanfilename{%
\input "##1"\expandafter\relax
\xsection}%
}
\def\xsection{this text should appear after example.tex's}
\section SECTION NAME;"example file.tex"
\bye
(代码最初是用 编写的expl3
,因此它短得多;ε-TeX 使生活变得轻松得多;-)
[1] TeX 知道行尾,因此:
\input "example
file.tex"
将输入example.tex
然后排版file.tex"
,而:
\scanfilename{\input"#1" }"example
file.tex"
将输入,example file.tex
因为\endlinechar
变成了空格。