数组:将 \newcolumntype 扩展为 \provide 等

数组:将 \newcolumntype 扩展为 \provide 等

考虑一下(愚蠢的)MWE:

\documentclass[]{article}
\usepackage{array, ragged2e}
% in a package
\newcolumntype{R}[1]{>{\raggedright\arraybackslash\hspace{0pt}}p{#1\linewidth}<{}}
% here
\newcolumntype{R}[1]{>{\RaggedRight\arraybackslash\hspace{0pt}}p{#1\linewidth}<{}}
\begin{document}
\begin{tabular}{R{0.3}c}
    Test & test
\end{tabular}
\end{document}

显然,会有一个警告:

Package array Warning: Column R is already defined on input line 6. 

现在,我明白了列类型重新定义(我不清楚),但是 --- 是否可以\newcolumnstyle以类似的方式扩展它xparse

我的意思是,拥有全套

  1. \newcolumntype:应该出错,说不要为了兼容性而改变当前行为
  2. \providecolumntype(若存在则不重新定义)
  3. \renewcolumntype(重新定义,如果存在则不发出警告)
  4. \definecolumntype(始终重新定义,无警告)

我尝试深入研究array.sty,但对我来说它太过 TeX 了……所以我想问问是否有人已经这样做过了…… ;-)。只要有一种等价的方法\providenewcolumn就好了。

另一种选择是使用类似

   \ifcolumndefined{R}{then}{else}% 

或类似...

顺便说一句:我知道我可以用

\usepackage{silence}
\WarningFilter{array}{Column R}

答案1

如果您想检查某个列类型是否存在,可以使用array.sty与以下相同的测试\newcolumntype

\newcommand\ifcolumndefined[1]{%
  \edef\NC@char{\string#1}%
  \@ifundefined{NC@find@\NC@char}%
    {\@tempswafalse
     \@tfor\next:=<>clrmbp@!|\do
       {\if\expandafter\noexpand\next\NC@char \@tempswatrue \fi}%
     \if@tempswa \expandafter\@firstoftwo
     \else \expandafter\@secondoftwo
     \fi}%
    {\@firstoftwo}}

NC@find@#1如果存在,或者#1为原始列类型之一,则为真<>clrmbp@!|。此测试不可扩展(您可能不需要它,但为了炫耀expl3),这是一个可扩展的版本:

\ExplSyntaxOn
\prg_new_conditional:Npnn \rmano_if_column_defined:n #1 { p, T, F, TF }
  {
    \cs_if_exist:cTF { NC@find@ \token_to_str:N #1 }
      { \prg_return_true: }
      {
        \exp_args:No \rmano_if_primitive_column:NTF { \token_to_str:N #1 }
          { \prg_return_true: }
          { \prg_return_false: }
      }
  }
\prg_new_conditional:Npnn \rmano_if_primitive_column:N #1 { p, T, F, TF }
  {
    \tl_map_tokens:nn { <>clrmbp@!| }
      { \__rmano_if_primitive_column:NN #1 }
    \prg_return_false:
  }
\cs_new:Npn \__rmano_if_primitive_column:NN #1 #2
  {
    \token_if_eq_charcode:NNT #1 #2
      { \tl_map_break:n { \use_i:nn \prg_return_true: } }
  }
\cs_set_eq:NN \ifcolumndefined \rmano_if_column_defined:nTF
\ExplSyntaxOff

\ifcolumndefined是 的副本\rmano_if_column_defined:nTF,但您也可以复制其他变体(:nT:nF)或 的副本\rmano_if_primitive_column:N(TF)。)

这是一个完整的例子:

在此处输入图片描述

\documentclass{article}
\usepackage{array}
% \makeatletter
% \newcommand\ifcolumndefined[1]{%
%   \edef\NC@char{\string#1}%
%   \@ifundefined{NC@find@\NC@char}%
%     {\@tempswafalse
%      \@tfor\next:=<>clrmbp@!|\do
%        {\if\expandafter\noexpand\next\NC@char \@tempswatrue \fi}%
%      \if@tempswa \expandafter\@firstoftwo
%      \else \expandafter\@secondoftwo
%      \fi}%
%     {\@firstoftwo}}
% \makeatother
\ExplSyntaxOn
\prg_new_conditional:Npnn \rmano_if_column_defined:n #1 { p, T, F, TF }
  {
    \cs_if_exist:cTF { NC@find@ \token_to_str:N #1 }
      { \prg_return_true: }
      {
        \exp_args:No \rmano_if_primitive_column:NTF { \token_to_str:N #1 }
          { \prg_return_true: }
          { \prg_return_false: }
      }
  }
\prg_new_conditional:Npnn \rmano_if_primitive_column:N #1 { p, T, F, TF }
  {
    \tl_map_tokens:nn { <>clrmbp@!| }
      { \__rmano_if_primitive_column:NN #1 }
    \prg_return_false:
  }
\cs_new:Npn \__rmano_if_primitive_column:NN #1 #2
  {
    \token_if_eq_charcode:NNT #1 #2
      { \tl_map_break:n { \use_i:nn \prg_return_true: } }
  }
\cs_set_eq:NN \ifcolumndefined \rmano_if_column_defined:nTF
\ExplSyntaxOff
\begin{document}
\ifcolumndefined{W}{W exists}{W doesn't exist}

\ifcolumndefined{R}{R exists}{R doesn't exist}

\ifcolumndefined{c}{c exists}{c doesn't exist}

\edef\x{\ifcolumndefined{|}{| exists}{| doesn't exist}}
\texttt{\meaning\x}
\end{document}

相关内容