如何重新定义 \end 以兼容表格环境?

如何重新定义 \end 以兼容表格环境?

我该如何重新定义,\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}

相关内容