访问 amsmath 对齐环境的每个单元

访问 amsmath 对齐环境的每个单元

我想创建一个基本上像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}

相关内容