![…的参数有一个额外的},递归宏](https://linux22.com/image/351884/%E2%80%A6%E7%9A%84%E5%8F%82%E6%95%B0%E6%9C%89%E4%B8%80%E4%B8%AA%E9%A2%9D%E5%A4%96%E7%9A%84%7D%EF%BC%8C%E9%80%92%E5%BD%92%E5%AE%8F.png)
注意:这(不幸的是)不是一个简单的“修复匹配的括号”问题,请阅读整个问题。
我正在编写一个命令来修复间距\vec
——默认情况下间距太小,导致与箭头和以下字形发生冲突,例如(\vec p)
。但是,只需重新定义命令,如
\makeatletter
\let\oldvec\vec
\def\vec#1{\oldvec{#1}\@ifnextchar{^}{\kern 1pt}{}}
\makeatother
在向量同时具有上标的情况下不起作用和下标。因此,需要一个递归处理即将到来的上标和下标的命令。
目前,我正在使用以下解决方案(针对 Stix/Times 进行了优化,因此在 Computer Modern 中可能看起来不太好)。但是,包含单个命令(该命令带有一个参数)的下标将失败,除非原子被括在括号中(例如\vec a_\textup{max}
不起作用,\vec a_{\textup{max}}
并且\vec a_\pi
起作用)。
梅威瑟:
\documentclass{article}
\makeatletter
\let\oldvec\vec
\def\vec#1{\oldvec{#1}\vec@}
\def\vec@{%
\@ifnextchar{_}{\vec@sub}{%
\@ifnextchar{^}{\vec@sup}{{\kern 0.5pt}}}%
}%
\def\vec@sub#1#2{_{\kern -0.75pt #2}\vec@}
\def\vec@sup#1#2{^{\kern 2pt #2}\vec@}
\makeatother
\begin{document}
% works
\[ \vec s_{\textrm{max}} \]
% doesn't work
\[ \vec s_\textrm{max} \]
\end{document}
错误代码:
! Argument of \textrm has an extra }.
<inserted text>
\par
l.16 \[ \vec s_\textrm
{max} \]
\vec@sub
我认为这与在给出参数之前结束一个组的and命令有关\vec@sup
(以便解析器看到{\vec{a}_\textrm}{a}
或出现某些情况并感到恐慌),但我不完全确定如何解决这个问题。
全面披露:此代码是“改编的”(即几乎完全复制)这个答案@siracusa 撰写,它涉及的 TeX 代码肯定比我通常的技能水平要高一些。我读过我能找到的等等\@ifnextchar
,但我对这里涉及的所有元素并不是 100% 确定。
感谢您帮助解决这个奇怪的问题!
答案1
使用原始下标的工作方式_\textrm{a}
是原始行为的一个不幸的副作用。使用宏参数很难支持这一点,而且无论如何都是不正确的 latex 语法,因此最好只是记录它不受支持,就像这里使用宏的其他包一样,例如 breqn 或 tex4ht 等。
事实上,它之所以能起作用,是因为它是一个 tex 基元而不是宏,还取决于和类似命令(扩展为单个括号组)_
的内部细节。例如,外表相似的构造不起作用,并且需要。\textrm
x_\fbox{a}
x_{\fbox{a}}
如果_
将其制成宏,那么它(很可能)会失去查找隐藏在宏内的括号的能力。如果_
使用而不是\fbox\textrm{x}
,那么您将获得与所示基本相同的错误,因为\fbox
会得到只是 \textrm
作为参数。正确的标记是\fbox{\textrm{a}}