修补原始定义

修补原始定义

表的列类型可以用 定义和覆盖\newcolumntype。我想知道是否已经定义了列类型,以便仅在定义了列类型的情况下执行示例。

编辑:与 egreg 的答案类似,我也创建了以下代码:

\newcommand\isColumntypeDefined[1]{%
  \providebool{\tpl@coltype@#1}
  \ifcsdef{NC@find@\string#1}{
    \setboolean{\tpl@coltype@#1}{true}%
  }{%
    \setboolean{\tpl@coltype@#1}{false}
  }%
  \boolean{\tpl@coltype@#1}%
}

但由于没有创建有效命令,因此失败\tpl@coltype@#1。此问题与latex @temps(wa) 命令。如果知道如何让这段代码可编译就太好了。

EDIT2:我将整个代码更改为 etoolbox 定义并最终以此结束

% Create list of predefined columntypes
\expandafter\let\csname columntype@l\endcsname\@empty
\expandafter\let\csname columntype@c\endcsname\@empty
\expandafter\let\csname columntype@r\endcsname\@empty
\expandafter\let\csname columntype@p\endcsname\@empty
\expandafter\let\csname columntype@m\endcsname\@empty
\expandafter\let\csname columntype@b\endcsname\@empty

\newcommand\CheckIfColumntypeDefined[1]{%
  \providebool{tpl@coltype@#1}
  \ifcsdef{NC@find@\string#1}%
    {\setbool{tpl@coltype@#1}{true}}%
    {\ifcsdef{columntype@\string#1}
      {\setbool{tpl@coltype@#1}{true}}%
      {\setbool{tpl@coltype@#1}{false}}%
    }%
}

\newcommand\isColumntypeDefined[1]{tpl@coltype@#1}

\newcommand\IfColumntypeDefined[3]{%
  \CheckIfColumntypeDefined{#1}
  \ifboolexpr{ bool{\isColumntypeDefined{#1}} }{#2}{#3}%
}

答案1

指令

\newcolumntype{N}{...}

定义命令\NC@find@N。你可以使用

\ifcsname NC@find@\string#1\endcsname

命令\safenewcolumntype可以定义为

\makeatletter
\newcommand\@gobbleoptandone[2][]{}
\expandafter\let\csname safenct@l\endcsname\@empty
\expandafter\let\csname safenct@c\endcsname\@empty
\expandafter\let\csname safenct@r\endcsname\@empty
\expandafter\let\csname safenct@p\endcsname\@empty
\expandafter\let\csname safenct@m\endcsname\@empty
\expandafter\let\csname safenct@b\endcsname\@empty
\expandafter\let\csname safenct@@\endcsname\@empty
\expandafter\let\csname safenct@!\endcsname\@empty
\expandafter\let\csname safenct@|\endcsname\@empty
\expandafter\let\csname safenct@<\endcsname\@empty
\expandafter\let\csname safenct@>\endcsname\@empty
\expandafter\let\csname safenct@=\endcsname\@empty
\def\safenct@error#1{\PackageError{mypackage}
    {Column type `\string#1' already defined}
    {The column type you're trying to define is already\MessageBreak
     existent; I'll ignore this new definition}}
\newcommand{\safenewcolumntype}[1]{%
  \@tempswafalse
  \ifcsname NC@find@\string#1\endcsname
    \safenct@error{#1}\@tempswatrue
  \fi
  \ifcsname safenct@#1\endcsname
    \safenct@error{#1}\@tempswatrue
  \fi
  \if@tempswa
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi{\@gobbleoptandone}{\newcolumntype{#1}}%
}
\makeatother

\@gobbleoptandone如果列类型已经定义,我们将把吞噬可选参数和强制参数的命令放在其余标记列表之前:\safenewcolumntype{l}[1]{...}将成为

\@gobbleoptandone[1]{...}

一切都很好。

否则我们将其放上去,\newcolumntype{#1}这样它就能完成任务了。当然,最好还是修补一下原来的\newcolumntype命令。

修补原始定义

\makeatletter使用和之间的代码\makeatother,我们重新定义了\newcolumntype命令,以便检查列类型是否已定义,在前一种情况下,它不允许重新定义列类型。也可以定义命令\renewcolumntype,但这似乎并不那么重要。

\documentclass{article}
\usepackage{array}

\makeatletter
\newcommand\@gobbleoptandone[2][]{}
\def\newcolumntype#1{%
  \@tempswafalse
  \edef\NC@char{\string#1}%
  \@ifundefined{NC@find@\NC@char}%
    {\@tfor\next:=<>clrmbp@!|\do
      {\if\next\NC@char
         \PackageError{safenct}{`\NC@char' is a primitive column type}
           {You're trying to redefine a primitive column type;\MessageBreak
            the redefinition will be ignored}%
         \global\@safenct@deftrue
       \fi}%
    \if@tempswa\else\NC@list\expandafter{\the\NC@list\NC@do#1}\fi}%
    {\PackageError{safenct}{Column `\NC@char' is already defined}
       {This column type is already defined;\MessageBreak
        the redefinition will be ignored}%
     \@tempswatrue}%
  \if@tempswa
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbleoptandone}
  {\@namedef{NC@find@\NC@char}##1#1{\NC@{##1}}%
   \@ifnextchar[{\newcol@{\NC@char}}{\newcol@{\NC@char}[0]}}
}

\makeatother

\newcolumntype{N}{>{Y}l<{Z}}
\newcolumntype{N}{r}
\newcolumntype{l}{r}

\begin{document}
\begin{tabular}{N}
xxxx\\
x\\
xx
\end{tabular}
\end{document}

\newcolumntype{x}扫描时,例程将暂存条件设置为 false,并检查是否x属于原始列类型,如果是,则发出错误消息并将临时条件设置为 true。然后,它检查是否x属于“派生”列类型,即通过\newcolumntype自身定义。如果是,则再次将暂存条件设置为 false。最后,如之前提供的代码一样,采取正确的操作:如果条件为 false,则代码的以下部分将被\newcolumntype吞噬,否则执行定义。

答案2

虽然这并没有直接回答你的问题,array包裹规定\showcols(根据array文档) 执行以下操作:

所有当前活动定义的列表\newcolumntype被发送到终端和.log文件。

例如,如果您的.tex文件包含:

\newcolumntype{X}{l}
\newcolumntype{Y}{@{}c<{\hspace{1ex}}@{\ }}
\showcols

您的.log文件将包含

Column X -> l
Column Y -> @{}c<{\hspace {1ex}}@{\ }

相关内容