为什么表格环境在更新环境内部或外部的行为会有所不同(错误)?

为什么表格环境在更新环境内部或外部的行为会有所不同(错误)?

我正在重新定义description使用表格作为 CV 类的一部分。CV 的样式是一大长列表,包含垂直对齐的日期等,所以我认为我可以添加到\begin{tabular}{ l l }AtBeginDocument并以 结束AtEndDocument。然后只需将描述重新定义为透明,item然后之内描述为预期的表格行:

\renewenvironment{description}
   {
     \renewcommand{\item}[1][]{\textsc{##1} & }
   } {
   }

受到启发这篇博文

通过定义类似的内容section,我可以在我的简历中添加以下内容:

\section{A section}
\begin{description}
\item[2019] An event \\
\item[2021] A later event \\
\end{description}

我一直在较小的文件中测试我的想法。因此,总的 MWE 与我编译的完全一样:

\documentclass{article}

\renewenvironment{description}
   {
      \renewcommand{\item}[1][]{##1 & }
   } {
   }

\begin{document}
\begin{tabular}{ l l }   
\begin{description}

\item[2019] An event \\
\item[2021] A later event \\
          
\end{description}
\end{tabular}

\end{document}

这可以编译,但是它是错误的。它看起来像这样:

错误

为了使所有内容显示出来,我必须在定义中包含表格环境description

\documentclass{article}

\renewenvironment{description}
   {
     \renewcommand{\item}[1][]{##1 & }
     \begin{tabular}{ l l }   
   } {
     \end{tabular}
   }

\begin{document}
\begin{description}

\item[2019] An event \\
\item[2021] A later event \\
          
\end{description}

\end{document}

看起来正如预期的那样:

在此处输入图片描述

超过两个项目时也会发生这种情况。只有最上面的项目会完整显示,其他项目会被截断,如图所示。

我知道我可以只需将tabular环境保留在description定义中,但这似乎不整洁,并且更难维护(因为我需要在每一个我重新定义了环境和/或命令,以使所有内容正确排列。我最初将所有这些都硬编码在一个 LaTeX 文件中,在那里我使用一个表包装整个文件,这比使用许多单独的表要容易得多)。

那么,为什么会发生这种情况,以及如何使输出按预期出现,并且只有一个表,在环境定义之外?

答案1

随着description环境之内在中tabular,您对 的重新定义\item仅限于 中第一个单元格的范围tabular。超出此范围,\item将恢复为其原始定义,并且操作失败。您必须将赋值 ( \renewcommand{\item}) 设为全局赋值,以便将其扩展到重新定义的单元格之外。

当前设置的另一个问题是, 中的单元格(实际上是组)tabular现在具有一个description环境(另一个组),该环境从第一个单元格开始并在另一个单元格中关闭。该组必须在同一组内打开/关闭。解决此问题的一种方法是捕获此新定义的description环境的全部内容,并且仅将其设置为\end{description}。这可以通过以下方式实现environ

这是一个完整的最小示例,体现了上述想法:

在此处输入图片描述

\documentclass{article}

\usepackage{environ}

\newcommand{\itemwithoptarg}[1][]{#1 &}
\let\olditem\item% Capture current definition of \item
\newcommand{\restoreitem}{\global\let\item\olditem}
\RenewEnviron{description}{%
  \gdef\item{\itemwithoptarg}% Global redefinition of \item
  \global\let\BODY\BODY% Make \BODY global
  \aftergroup\BODY% Print \BODY after description environment closes
  \aftergroup\restoreitem% Restore original \item (if you use lists, for example)
}

\begin{document}

\begin{tabular}{ l l }   
  \begin{description}
    \item[2019] An event \\
    \item[2021] A later event \\
  \end{description}
\end{tabular}

\begin{itemize}
  \item First
  \item Second
\end{itemize}

\end{document}

答案2

任何错误甚至不会查看 PDF,除非作为可能的调试辅助,如果您选择滚动浏览错误,Tex 不会尝试合理的输出,它只会恢复足够的内容以尝试语法检查文档的其余部分。

您的代码产生

! Extra }, or forgotten \endgroup.

正如您\begin{description}在表格的第一个单元格中看到的,表格是一个组,因此一旦它看到&组结束但环境尚未完成。

基本上&就像}{结束一个组并开始另一个组,你会得到基本上相同的错误

 {  \begin{description}  }{ \end{description} }

我认为将表格放入定义中是正确的标记。(我个人会使用新名称而不是重新定义,description但这只是个人喜好的问题)

也就是说,如果你颠倒调用顺序,你就可以保留你的定义:

\documentclass{article}

\renewenvironment{description}
   {
      \renewcommand{\item}[1][]{##1 & }
   } {
   }

\begin{document}
\begin{description}
\begin{tabular}{ l l }   

\item[2019] An event \\
\item[2021] A later event \\
\end{tabular}
          
\end{description}

\end{document}

相关内容