长命令(作为其潜在参数)如何处理空格标记和空行?

长命令(作为其潜在参数)如何处理空格标记和空行?

长命令(即不接受段落分隔符的命令)如何处理空格和空行?除了“ ”和空行之外,还有其他空格标记吗?看来空行恰好算作一个空参数:

\documentclass{article}

\newcommand{\oneArg}[1]{}
\newcommand{\twoArgs}[2]{}
\newcommand{\threeArgs}[3]{}

\begin{document}

\indent
A \oneArg

B

% output:
% A B


A \twoArgs

B

C

% output:
% A
% C

A \threeArgs

B

C

% output:
% A C

\end{document}

在这方面,关于数学模式有什么特别需要了解的吗?

一个提示:一些相关信息这个问题, 尤其\somecommand *这个关于合法 LaTeX 的讨论主题


附录:关于短宏(例如用 定义的宏\newcommand*)的一个有趣的细节:如果我添加\newcommand*{\noPar}[1]{#1}到我的源代码并尝试编译一个额外的代码块

\noPar{
A \threeArgs

B

C
}

编译器会抛出错误。因为这是语义上不是段落分隔符,命令之间的长短区别可能应该用空行来描述,而不是段落分隔符。还是不?

答案1

标题问题的答案是技术上“它们没有被处理”但我不认为这是你想要的答案。

如果你将定义修改为

\newcommand{\oneArg}[1]{\long\def\a{[#1]}\typeout{\meaning\a}}
\newcommand{\twoArgs}[2]{\long\def\a{[#1][#2]}\typeout{\meaning\a}}
\newcommand{\threeArgs}[3]{\long\def\a{[#1][#2][#3]}\typeout{\meaning\a}}

你会看见

\long macro:->[\par ]
\long macro:->[\par ][B]
\long macro:->[\par ][B][\par ]

假设正常的 catcode 有效,TeX 会将空白行转换为标记\par(实际上是命令名称标记,\par而不是原始段落结束函数)。它在字符被标记化的早期阶段执行此操作,因此在任何标记列表传递给宏之前。因此,宏永远不会在其参数中看到空白行。行为总是像您在\par输入文件中用 替换空白行一样。

在这个早期阶段,空格标记的处理方式类似。行尾和下一行开头的空格会被丢弃,并且根本不会被标记,因此宏没有它们的记录。(即使更改空格的 catcode,也无法阻止行尾空格被丢弃)并且空格字符的运行只会产生一个空格标记。传递给宏的是标记,而不是文件字符。

如果您有非分隔参数(如示例中所示),则在查找参数时会跳过任何空格标记,如果您希望使用空格您需要的参数{ }.\par如果宏是,则可以是无分隔符参数\long,否则可以是错误。

答案2

TeX 的标记化过程在这里很重要。当 (La)TeX 读取新队

some text
some more text

它将换行符转换为空格(忽略第二行开头的任何空格):。some text some more text但是,当 TeX 读取连续的换行符会转换为一个\par标记

some text

some more text

最终结果为some text \par some more text。(我假设\endlinechar这里的标准设置。)

参数的获取发生在这个过程发生之后,所以你不会看到“空行”被读为参数,而是被读为\par标记。这是\par 代币在命令的参数中,区分“短”命令和“长”命令,并且这些命令必须出现直接地在参数中使用“短”命令引发错误。

答案3

<end-of-line>(1)扫描参数时,不包含两个 s 的空格将被跳过。 (2)包含至少two<end-of-lines>被转换为\par并且可以作为参数传递。

另一方面,当 TeX 扫描不带\long、 和的命令定义时\par(如\par或如上面的 (2) 所示),它会抛出错误。这样您就可以更轻松地调试错误分组。(记住:\newcommand=> yes-\long\newcommand*=> no- \long。)


同样,\par在情况 (2) 中,它不仅可作为参数有效,还可作为参数分隔符有效。但是,该参数仍将包含终止空格标记:

\def\xy#1\par{x#1y}

Hello \xy World

How are you

\bye

输出(一行,记住我们“吃”了\par它作为参数分隔符):

你好 xWorld y你好吗


据我所知,这有时会在 ConTeXt 中使用,它允许您摆脱许多括号,例如考虑定义\def\Section#1\par{\section{#1}},您的代码将是:

\Section Your well-being

How are you?

输出:

您的健康

你好吗?

相关内容