colortbl:新环境以及如何应用 \expandafter

colortbl:新环境以及如何应用 \expandafter

这是来自安德鲁·霍华德 (Andrew Howard) 提出的问题。经过一番讨论,很明显colortbl存在一些与 相关的名称问题\newcolumntype。讨论的结果离题太远,似乎可能会提出一个新的、更普遍的问题。

假设我们想定义新列而不使用\newcolumntype,这有限制,因为名称只能是一个字符。tabular环境可以接受更复杂的输入。例如,在不定义 的情况下,\newcolumntype我们可以这样做

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}

\begin{document}
\begin{tabular}{|>{\columncolor{blue!10}}c|>{\columncolor{red!10}}c|}
Something  & Something else\\
\end{tabular}
\end{document}

这不是特别可重复使用。我们不能做的是

\newcommand{\colone}{>{\columncolor{blue!10}}c}
\newcommand{\coltwo}{>{\columncolor{red!10}}c}

\begin{tabular}{|\colone|\coltwo|}
Something  & Something else\\
\end{tabular}

array软件包提供了\newcolumntype解决这个问题的方法,但只允许使用单个字符的名称,这不是很令人满意。

我如何才能强制 LaTeX 扩展\colone\coltwo在 tabular 获取它们之前?定义一个新的环境就可以了。一般来说,如何使用以特定顺序强制扩展new environment

答案1

值得一提的是,大多数方法\newcolumntype实际上并不要求列名称为单个字符,而只是要求它是一个标记。例如,这是可行的

\newcolumntype{\fooa}[1]{>{\color{#1}}c}
\newcolumntype{\foob}{|l|}
\begin{tabular}{\fooa{red}\fooa{blue}\foob}
a b c & a b c & a b c \\
1&2&3
\end{tabular}

但它实际上并没有得到支持,并且\showcols在这种用法下会失败,尽管这个问题大概可以被修复,但坚持使用单个字母可能更简单,即使在避免了特殊字符之后,8 位 TeX 中也有超过 200 个特殊字符,这应该是足够的列类型了。:-)

答案2

贾斯汀想法的改进:

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}
\newenvironment{tabularex}[2][c]
  {\begingroup\edef\x{\endgroup\noexpand\tabular[#1]{#2}}\x}
  {\endtabular}
\newcommand{\newcolumntypeex}[2]{\newcommand#1{\unexpanded{#2}}}
\newcolumntypeex{\colone}{>{\columncolor{blue!10}}c}
\newcolumntypeex{\coltwo}{>{\columncolor{red!10}}c}

\begin{document}

\begin{tabularex}{\colone\coltwo}
Something & else\\
\end{tabularex}
\end{document}

它相对于通常的tabular环境有很多限制:例如,像 这样的操作>{\raggedright}p{3cm}将不起作用(这正是array的参数中不扩展标记的原因tabular)。必须\protect在每个此类标记前面放置 。

总的来说,我认为它不是特别有用。手头的问题可以通过以下方法解决:

\newcolumntype{Z}[1]{>{\columncolor{#1}}c}

\begin{tabular}{Z{blue!10}Z{red!10}}

回想一下,执行的定义\newcolumntype是局部的,因此在table环境内部给出的定义将在它之后消失。

答案3

下面的定义tabularex适用于一列,并且可以推广到以 分隔的任意数量的列|。它不适用于任何环境,但适用于tabular

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}
\def\tabularex#1{\toks0=\expandafter{#1}%%
  \edef\go{\toks2={\noexpand\begin{tabular}{\the\toks0}}}%%
  \go\the\toks2}

\begin{document}
\newcommand{\colone}{>{\columncolor{blue!10}}c}
\newcommand{\coltwo}{>{\columncolor{red!10}}c}

\tabularex{\colone}
Something \\
\end{tabular}
\end{document}

\expandafter关键元素是在标记赋值中使用: \toks0=\expandafter{#1}。由于colone不带参数,因此这只进行一级扩展。我从 TeXBook 中学到了这一技巧 - 练习 20.15 的答案向您展示了如何编写一个只扩展另一个一级的宏,\asts附录 D(“肮脏的技巧”)开头对宏的讨论展示了如何\expandafter与标记赋值一起使用。

相关内容