编译此代码时:
\documentclass{article}
\usepackage{testPackage}
\usepackage{xparse}
\NewDocumentCommand{\foo}{mm}{#1_{#2}}
\begin{document}
$\foo A i$, $\fooT A i$
\end{document}
其中testPackage
包括定义:
\usepackage{xparse}
...
\ExplSyntaxOn
...
\NewDocumentCommand{\fooT}{mm}{#1_{#2}}
...
\ExplSyntaxOff
我得到输出:
尽管两个命令执行相同的操作,但为什么在第二个版本中下标排版不正确?
答案1
我假设 OP 已经将\ExplSyntaxOn...\ExplSyntaxOff
定义为包装器\fooT
。这当然会改变 catcodes,并且_
会以不同的方式进行解释。
如果不需要任何语法expl3
(例如 think of\cs_new:N
等),请不要使用\ExplSyntax...
。 就\NewDocumentCommand
足够了!
\documentclass{article}
%\usepackage{testPackage}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\fooT}{mm}{#1_{#2}}
\ExplSyntaxOff
\NewDocumentCommand{\fooother}{mm}{#1_{#2}}
\NewDocumentCommand{\foo}{mm}{#1_{#2}}
\begin{document}
$\foo{A}{i}$, $\fooT{A}{i}$, $\fooother{A}{i}$
\end{document}
答案2
\ExplSyntaxOn
和之间的惯例\ExplSyntaxOff
基本上是:
空格和行尾会被忽略(当然,在控制序列名称的中间不会被忽略)
_
并且:
可以(并且应该)成为控制序列名称的一部分,因此它们具有类别代码 11(字母)~
与普通的太空令牌相同
这样做的结果是_
不能在数学模式下使用 来引入下标。原因很常见:如果你这样做
\ExplSyntaxOn
\NewDocumentCommand{\fooT}{mm}{#1_{#2}}
\ExplSyntaxOff
当 为字母时,的替换文本\fooT
会被标记化,因此每次调用_
时都会如此。\fooT
为了解决这个问题,expl3
内核提供了
\c_math_subscript_token
_
因此,当定义主体中需要 8 时,您应该使用它,无论是引入下标还是进行\peek_...
测试检查。
使用\sb
也是可能的,这在上面的代码中可能更有吸引力;所以
\ExplSyntaxOn
\NewDocumentCommand{\fooA}{mm}{#1\c_math_subscript_token{#2}}
\ExplSyntaxOff
或者
\ExplSyntaxOn
\NewDocumentCommand{\fooA}{mm}{#1\sb{#2}}
\ExplSyntaxOff
是等效的。前一种语法最好在纯expl3
上下文中使用。
答案3
如果由于某种原因需要在 expl3 语法中使用下标,则可以随时使用\sb
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\fooT}{mm}{#1\sb{#2}}
\ExplSyntaxOff