我正在尝试制作一个宏,如果将 a传递给我的宏,它将包装\multicolumn
命令的列规范。我可以在下面的第一个定义中实现我想要的行为,但我试图找出如何以“更聪明”的方式做到这一点,就像在第二个定义中尝试的那样,但它会引发错误。为什么?@{}
*
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{xparse}
%%% this gets me what I want
\NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }{%
\IfBooleanTF#1{%
\multicolumn{#3}{#2}{#4}%
}{%
\multicolumn{#3}{@{}#2@{}}{#4}%
}%
}
%%% but I am trying to learn how to do it like this
\NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }{%
\IfBooleanTF#1{\def\colspec{#2}}{\def\colspec{@{}#2@{}}}
\multicolumn{#3}{\colspec}{#4}%
}
\begin{document}
% this is the behaviour I want
\begin{tabular}{ll}\toprule
\sCell{Hello}\\%
\sCell*{Hello}\\%
\end{tabular}
\end{document}
答案1
\multicolumn
建立在名为 的 TeX 基元之上\omit
,如果\omit
在表格单元格中使用,它必须是表格单元格中第一个不可扩展的东西(除了\omit
/\hline
)。 \def
是不可扩展的,因此在使用之前在命令中使用它将\multicolumn
不起作用,因为\def
将告诉 TeX 它不必再寻找了\omit
,然后你稍后给它一个\omit
并且 TeX 会抱怨。
该问题的一个更简单的例子:
\documentclass{article}
\begin{document}
\begin{tabular}{c}
% Any of these will cause the error.
% \def\x{y}
% \relax
% a
\multicolumn{1}{l}{error}
\end{tabular}
\end{document}
话虽如此,您似乎想在不重复的情况下编写命令\multicolumn
,因此这里有两个选项:
第一种,使用辅助。不是\colspec
使用适当的参数进行定义,而是将其传递给辅助宏,然后辅助宏将在 中使用它\multicolumn
。这种方法之所以有效,是因为它除了\IfBooleanTF
可扩展的 之外,还使用了一个根据定义可扩展的宏:
\NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }{%
\IfBooleanTF{#1}%
{\sCellaux{#2}}%
{\sCellaux{@{}#2@{}}}%
{#3}{#4}} % #3 and #4 outside the conditional because they are the same
\newcommand\sCellaux[3]{%
\multicolumn{#2}{#1}{#3}}
第二种选择是使用一些expl3
辅助函数,强制扩展\IfBooleanTF
,然后稍微调整一下以使第二个参数处于正确的位置。这是有效的,因为它使用一些可扩展的原语来触发扩展,并使用宏来交换参数:
\ExplSyntaxOn
\NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }
{
\exp_args:Nf \use_ii_i:nn
{ \IfBooleanTF {#1} { {#2} } { {@{}#2@{}} } }
{ \multicolumn {#3} } {#4}
}
\ExplSyntaxOff
这是一个可编译的示例:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{booktabs}
\usepackage{xparse}
%%% this gets me what I want
\ExplSyntaxOn
\NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }
{
\exp_args:Nf \use_ii_i:nn
{ \IfBooleanTF {#1} { {#2} } { {@{}#2@{}} } }
{ \multicolumn {#3} } {#4}
}
\ExplSyntaxOff
%%% this gets me what I want
% \NewExpandableDocumentCommand{\sCell}{s O{l} D(){1} m }{%
% \IfBooleanTF{#1}%
% {\sCellaux{#2}}%
% {\sCellaux{@{}#2@{}}}%
% {#3}{#4}}
% \newcommand\sCellaux[3]{%
% \multicolumn{#2}{#1}{#3}}
\begin{document}
% this is the behaviour I want
\begin{tabular}{ll}
\sCell{Hello}\\%
\sCell*{Hello}\\%
\end{tabular}
\end{document}