![如何重新定义 \end 以兼容表格环境?](https://linux22.com/image/423936/%E5%A6%82%E4%BD%95%E9%87%8D%E6%96%B0%E5%AE%9A%E4%B9%89%20%5Cend%20%E4%BB%A5%E5%85%BC%E5%AE%B9%E8%A1%A8%E6%A0%BC%E7%8E%AF%E5%A2%83%EF%BC%9F.png)
我该如何重新定义,\end
以便在表格环境中尽可能地保护它? 用 开始命令扩展是最好的选择吗\relax
?
假设我们对 有以下重新定义\end
,其行为应该尽可能与 的原始定义相似\end
。
\def\XXX{something}
\let\origEnd\end
\def\end#1{%
\def\tmp{#1}%
\ifx\tmp\XXX
\def\tmp{\origEnd{#1}}%
\else
\def\tmp{\origEnd{#1}}%
\fi
\tmp
}
它可以与标准tabular
列以及siunitx
使用时的列一起使用\relax
,但在终止后siunitx
没有的列会失败。\relax
\\
失败:siunitx 列以\\
无结尾\relax
\documentclass{article}
\def\XXX{something}
\let\origEnd\end
\def\end#1{%
\def\tmp{#1}%
\ifx\tmp\XXX
\def\tmp{\origEnd{#1}}%
\else
\def\tmp{\origEnd{#1}}%
\fi
\tmp
}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{S[table-format=2.3]}
1 \\
\end{tabular}
\end{document}
错误信息:
! Incomplete \ifx; all text was ignored after line 17.
<inserted text>
\fi
l.17 \end{tabular}
作品:siunitx 列\\
以\relax
\documentclass{article}
% ... preamble from above
\begin{document}
\begin{tabular}{S[table-format=2.3]}
1 \\\relax % \relax added
\end{tabular}
\end{document}
作品:标准tabular
列以\\
带/不带结尾\relax
\documentclass{article}
% ... preamble from above
\begin{document}
\begin{tabular}{r} % standard tabular column type
1 \\
\end{tabular}
\end{document}
它有什么好处:在subfiles
包中,需要进行设置\end
,使其跳过下一个\end{document}
而不触发任何钩子。上面的示例是代码的简化版本。
答案1
\end
是一个棘手的问题,因为表格,以及它们是如何实现来窥视内部的\end{env}
。如果你看看当前的定义,\end
你会发现它在某种程度上确保在\end{env}
精确地击中两次后,\expandafter
你会得到\endenv
。这
\expandafter\expandafter\expandafter\show\end{env}
说
> \endenv=\relax.
<recently read> \endenv
<*> ...after\expandafter\expandafter\show\end{env}
?
并且这种行为在重新定义后应该会保留。当然,对于\enddocument
(或\endsomething
在您的示例中)您想要执行其他操作,但所有其他环境都应该正常运行。
我建议您重新定义\end␣
而不是\end
(如果您想要向后兼容,请在检查旧版本的 LaTeX 之后),以便已经建立了正确扩展量的机制。然后,\end␣
您可以在里面使用\romannumeral
以保持扩展,并使用可扩展字符串比较(\str_if_eq:nnTF
例如)来检查所需的环境,然后返回\endenv
或对特殊情况执行所需的操作。
以下是实际示例:
\documentclass{article}
% % %
\ExplSyntaxOn
\cs_new_eq:NN \StrIfEqTF \str_if_eq:nnTF
\ExplSyntaxOff
\makeatletter
\expandafter\let\expandafter\origEnd\csname end \endcsname
\@namedef{end }#1{%
\romannumeral % keeps expansion going
\StrIfEqTF{#1}{something}% compares #1 with the special environment
{\subfiles@endsomething}% if so, do what you need here
{\expandafter\expandafter\expandafter\z@\origEnd}% otherwise pretend nothing happened
{#1}}
\def\subfiles@endsomething#1{\z@
\typeout{Ending special environment #1.}
((Special end))\par%
\origEnd{#1}}
\makeatother
% % %
\newenvironment{something}
{special env\par}
{end special env\par}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{S[table-format=2.3]}
1 \\
\end{tabular}
\begin{something}
1
\end{something}
\end{document}