使用星号命令更改多列的列规范

使用星号命令更改多列的列规范

我正在尝试制作一个宏,如果将 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}

相关内容