仅使第一个空间处于活动状态

仅使第一个空间处于活动状态

这是对上一个问题由于受到不公正对待,该账户已被关闭。

简要回顾:让\newcommand{\foo}{foo}.\foo在文本中像这样

test \foo bar

将省略后面的空格\foo,结果为test foobar,而

test {\foo} bar
test {\foo}.

生产test foo bartest foo.这正是我所需要的。


虽然在解析宏之前无法对其进行支撑,但有一种方法可以使空格成为活动字符。

这是解决方案经过埃格尔这很接近我想要的。但是它使用了额外的环境包装器。

我的问题是如何应用相同的技术来创建活动空间,但只在之后一次\foo?因此,它\foo需要一个参数,根据空格对其进行解析,并放入#1 foo文本中,如果存在空格则保留空格。

答案1

这是我能想到的一个解决方案,它只使用纯 TeX。

\def\checkspace{\catcode`\ =12\relax\futurelet\csps\checkspaceA}
\def\checkspaceA{\catcode`\ =10\relax\if\space\csps\ \afterassignment\ignorespaces\expandafter\let\expandafter\csps\fi}

\def\foo{foo\checkspace}

test \foo   bar

test foo bar

test \foo.

\bye

这个想法是这样的:\checkspace首先创建空格其他这样它们就不会被跳过并且可以被'd。然后我们使用\futurelet来检查下一个标记。 使空格再次成为空格标记,并且如果我们检查的标记是空格,则插入 a。\checkspaceA\futurelet\checkspaceA\

条件中的其余代码的目的\checkspaceA是确保 if\checkspace后面跟着多个空格,第一个空格后面的所有空格都将被忽略。首先,我将解释这个问题(就我的理解而言),以便更好地解释我的解决方案。

如果我们删除此代码\checkspaceA并执行以下测试:

\def\checkspaceA{\catcode`\ =10\relax\if\space\csps\ \fi}

test \foo bar

然后我们会得到test foo一个空格,然后是一个其他空格字符(看起来像 cmr 中的斜线),然后bar。问题是,一旦我们\futurelet\csps\checkspaceA在 中执行此操作\checkspace,后面的标记\foo就会被标记成其他空格标记,并留在流中,这就是创建奇怪的破折号字符的原因。

所以我们可以稍微修改一下代码来解决这个问题:

\def\checkspaceA{\catcode`\ =10\relax\if\space\csps\ \expandafter\let\expandafter\csps\fi}

test \foo  bar

但现在的问题是,由于后面有两个空格\foo,第一个空格被正确地转换为\by \checkspaceA。但下一个空格标记实际上跟在其他标记,因此不会被忽略。\afterassignment\ignorespaces在之前执行\let可确保它被忽略。


此解决方案不适用于 catcode 为 10 的任何字符,并且设置宏以使其适用于其他字符需要更改多个字符的 catcode 并嵌套\if

总的来说,我真没觉得这些宏有什么用处,我觉得在宏后面加上一个空组可能更简单。这样做几乎肯定不会遇到奇怪的意外副作用。

我不能 100% 确定我的宏是否一直有效,如果它们有问题,请随时告诉我,我很乐意尝试修复它们。

相关内容