我想创建一个基本上像amsmath
(v. 2.13)环境一样运行的环境,即可使用align
行号、、、\label
...。\tag
\intertext
因为我不想重新发明轮子,所以我天真地以为我可以使用修改后的版本\align@preamble
(第 2075 行及以下amsmath.sty
)。但是,如果我尝试使用单元格内容作为命令的参数,这将不起作用。
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\def\mytest#1{#1}
% when defined without argument there's no problem:
% \def\mytest{\bfseries}
% this is my modified version of \align@preamble
\def\my@align@preamble{%
&\hfil
\strut@
\setboxz@h{\@lign\mytest{##}}% this line causes trouble
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign{}##}%
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}
\newenvironment{test}{%
\let\align@preamble\my@align@preamble
\align}{%
\endalign}
\makeatother
\begin{document}
\begin{test}
a & b \\
c & d
\end{test}
\end{document}
上面的代码会抛出错误
! Misplaced alignment tab character &.
\@tempa ->\endgroup &
&
l.31 \end{test}
这让我猜想——但我可能大错特错——该命令以某种方式关闭了由\halign\bgroup
(在\align@
(第 1546 行以下)\align@preamble
使用 where 打开的组)但我无法弄清楚在哪里和/或为什么会发生这种情况。不幸的是,遵循 的代码并不那么容易amsmath.sty
,至少对我来说不是……
有人能给我指明正确的方向吗?或者有其他方法可以将宏应用到每个单元格吗?
答案1
在这个答案的原始版本中,我写道
你不能轻易做到
\mytest{##}
在 halign 前导中,基本上直到看到单元格末尾才会插入右括号&
,这意味着宏参数未被正确解析。
@egreg 指出,这并非事实,因为您可以在原始 halign 语法中将宏调用放在模板周围。(事实上,您的 MWE 已经有了这样的例子)。事实是这样的,但我只记得一半,使用 LaTeX 语法表很难做到这一点,因为(本质上)插入\mytest{
在单元格的开头,但}
只有在看到单元格的结尾时才插入。这适用于单元格不是在最后一列,&
即使 TeX 正在搜索参数,原语也会结束单元格,\mytest
但在最后一列既\\
不会\end{align}
触发单元格模板的结束,因为它们需要扩展才能被识别为单元格构造的结束,并且 Tex 在扫描宏参数时不会扩展。
所以......一般方法几乎不可能与正常的 LaTeX 语法一起工作(blockarray
几年前我规定最后一行以 结尾\\
并在本地以结尾,\let
\\
以便\cr
它是一个原始的单元格结尾)。
但是您的 MWE 只需要访问第一列,所以事情就简单多了。问题在于对齐有一个隐藏的最后一行,其中包含内部代码(实际上是两个不同的最后一行,因为出于测量原因,整个对齐设置了两次)。应用\mytest
该内部代码会有些混乱。
因此,这采用了两阶段方法,它检查下一个标记是否为\global
或\@empty
它假设是来自最后两行的内部代码,在这种情况下,它只是重新插入标记,而不是用 包围它\mytest
。为了使事情更直观,\mytest
定义为使用\fbox
。
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\def\xmytest#1{%
\def\mytest@a{#1}%
\ifx\mytest@a\mytest@aa
\expandafter\@firstofone
\else
\ifx\mytest@a\mytest@aaa
\expandafter\expandafter\expandafter\@firstofone
\else
\expandafter\expandafter\expandafter\mytest
\fi
\fi
{#1}}
\def\mytest#1\@empty{%
\fbox{#1}}
\def\mytest@aa{\global}
\def\mytest@aaa{\@empty}
% when defined without argument there's no problem:
%
% this is my modified version of \align@preamble
\def\my@align@preamble{%
&\hfil
\strut@
\setboxz@h{\@lign
\xmytest##\@empty
}% this line causes trouble
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign{}##}%
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}
\newenvironment{test}{%
\let\align@preamble\my@align@preamble
\align}{\endalign}
\makeatother
\begin{document}
\begin{test}
a & b \\
c & d
\end{test}
\end{document}