我想写一个\unpar
宏来删除最后一个\par
。例如,TeX 代码
This is a \par \unpar paragraph
应该相当于
This is a paragraph
(请注意,等效并不意味着它必须完全生成最后一个标记列表:我的意思是它应该具有与我使用最后一个标记列表获得的输出相同的输出。)
解决方案可能是\par
按以下方式重新定义:
\let\oldpar\par
\def\unpar{}
\long\def\par#1{\ifx#1\unpar\else\oldpar#1\fi}
\bye
但如果前面有 ,则此方法不起作用\par
(我不知道为什么)。此外, 的重新定义\par
可能会破坏某些宏包。所以,我想知道:有没有一种方法可以定义\unpar
而不修改\par
?
\Unpar
那么如果宏不仅删除一个\par
,而且删除其前面的所有s ,那又怎么样呢\par
?
答案1
这不可能。
TeX 看到\par
。
此时,当前水平列表被拆分为水平框的垂直列表,必要时应用连字符,丢弃可丢弃的粘连并添加左右粘连。然后调用输出例程,该例程可能输出一页或多页,可能取出存储的插入和脚注,并将它们添加到页面中,然后以垂直模式将控制权返回到输入流。
\unpar
要取消这一切将会非常困难。
答案2
您可以尝试这样的操作:
\def\par{\futurelet\next\dopar}
\def\dopar{\let\doparA=\endgraf
\ifx\next\par \let\doparA\relax \fi
\ifx\next\unpar \let\doparA\relax \fi
\doparA}
\def\unpar{\donothing{unpar}} % any special macro with empty output
\def\donothing#1{}
This is paragraph.
Note more empty lines here:
\unpar
The paragraph is not finished.
\bye
当然,你必须重新定义\par
。没有其他的可能性(这是 David Carlisle 解释的)。
你的错误是:你试图通过#1
(宏参数)而不是 来扫描下一个标记,\futurelet
后者更加可靠。\outer
定义的宏(如\bye
)无法加载到#1
,但可以使用 进行测试\futurelet
。如果下一个标记是,{
那么#1
扫描的工作量比你需要做的要多得多。但\futurelet
保持{
不变。