\verb 如何检测不应该存在的空格

\verb 如何检测不应该存在的空格

考虑以下 MWE:

\documentclass{article}

\usepackage{listings}
\lstset{basicstyle=\ttfamily}

\begin{document}

\lstinline |asdf|asdf asdfasdf

\verb |asdf|asdf asdfasdf

\end{document} 

我对这里期望的内容的理解一直是如下(以下\cmd代表\verb或):\lstinline

  • 当 TeX 第一次对 进行标记时\cmd |,它会吞噬其后面的空间,只留下\cmd其“嘴里”的标记(以及|输入流中其后面的标记)。
  • 然后它扩展\cmd,这会导致一系列类别代码变化,基本上使每个特殊字符都变成other,然后是一些查看下一个标记的宏(在本例中为|)。
  • 然后,这个宏抓取该标记下次出现之前的所有内容(然后进行标记化),应用一些格式并将类别代码改回。

值得注意的是,\cmd在该控制序列的标记化过程中被吞噬,即任何类别代码都发生改变。

基于这种理解,我希望上面两行都排版

asdf已验证

但我得到以下输出:

MWE 输出

\lstinline行为符合预期,但\verb以某种方式知道其后面的空间。

怎么办?据我所知,令牌后面不应该有空格令牌\verb

答案1

一开始你就说:

当 TeX 首次被标记时\cmd |

但这是错误的。TeX 是一位举止得体的绅士,在知道应该做什么之前不会擅自扫描 a 和 a 。就 TeX 而言,空格和 the以及其他任何字符都可能意味着同一件事,并且含义可能会发生变化,因此预先扫描只会引起混乱。|\cmd|

当 TeX 看到 时\cmd,它对空格做的唯一“特殊”的事情就是设置state:=skip_blanks,以便在排版时,\TeX code会写出在此处输入图片描述,照常忽略控制序列后的空格。你可以自己检查一下:

\def\test{\catcode`\ =12 \testx}
\def\testx{\futurelet\token\testy}
\def\testy{\show\token\afterassignment\testx\let\token = }
\test     x

您会看到它the character在显示之前显示了 5 the letter x


现在回到手头的问题:更新你的 LaTeX :-)

的旧行为\verb是查看下一个标记(无论它是什么),并将其用作分隔符( 除外{)。现在已改为固定的适用于 2020-10-01 LaTeX 版本(来自LaTeX 新闻第 32 期):

避免在 \verb 后出现有问题的空格 如果用户错误地输入了 \verb␣!~!␣foo 而不是 \verb!~!␣foo,那么令人惊讶的是,结果却是“!~!foo”,没有任何警告或错误。发生的事情是,由于 \verb 执行了相当复杂的处理来逐字呈现,␣ 成为了参数分隔符。此问题已得到修复,现在命令 \verb 或 \verb* 后面的空格会像其他地方一样被忽略。(github 问题 327)

答案2

我认为事情会如下发生:

  • \verb首先被标记(空格字符,其 catcode 为 10\verb标记之前,其 catcode 为 10,标志着这个控制字的结束,但不是丢弃)。

  • TeX将要进入状态 S,因为\verb是一个控制字(其名称仅由“字母”组成的控制序列),但它没有跳过空白。

  • \verb被扩展,并执行其扩展中的代码。此代码首先为空格赋予 catcode 12(通过\let\do\@makeother \dospecials),这很重要。

  • 在 的替换文本的末尾\verb,有\@ifstar\@sverb\@verb。这\@ifstar会在输入中向前看,因此状态 S 开始。由于此时空格的 catcode 为 12,因此后面的空格字符\verb不是已跳过。它已用 catcode 12 进行标记。

  • 由于我们使用了无星号形式\verb并且\@verb定义为\def\@verb{\@vobeyspaces \frenchspacing \@sverb},所以空格现在处于活动状态,并且\@sverb被扩展(因此,结束分隔符将是 catcode-13 空格,而起始分隔符将是 catcode-12 空格)。

  • \@sverb抓取 catcode-12 空间标记作为其唯一参数,并将活动空间定义为\let-equal \verb@egroup(如果\verb*已使用,也\@sverb会这样做\@setupverbvisiblespace \@vobeyspaces;因此,空间在所有情况下都处于活动状态)。这就是逐字文本在非错误条件下的结束方式:\verb@egroup将产生\egroup,这将终止由 启动的组(在的替换文本中\verb有一个)。由于特殊的 catcode 设置已在此组内部本地完成,因此这将终止特殊的 catcode 设置。\bgroup\verb

因此,问题中的句子“这个宏然后抓取到该标记下一次出现之前的所有内容”并不正确:没有攫取\@sverb的逐字内容作为参数。开始和结束分隔符之间的标记仅作为 catcode-12 标记进行处理,但空格标记除外,正如我们所见,空格标记始终在 的末尾处于活动状态。

注:如 Phelype Oleinik 所言指出,从 2020-10-01 开始,LaTeX 格式的行为\verb发生了变化。我在这里的评论基于LaTeX2e <2020-02-02> patch level 5

相关内容