传递 25 个参数时未定义控制序列

传递 25 个参数时未定义控制序列

在我开始提问之前,我想说的是,我很清楚以下内容可能是非标准的甚至是无意义的 LaTeX。我想改进它并愿意听取建议。

前段时间我写了这个绘制交换图的包。原因是我想使用语法

\begin{diagram}
  \twobytwo[wide]
    {A}{X}
    {B}{Y}
  \arrow{nw}{ne}{a}[above]
  \arrow{sw}{se}{b}[below]
  \arrow{nw}{sw}{f}[left]
  \arrow{ne}{se}{g}[right]
\end{diagram}

在我看来,它比木犀草素錄音或者计算机辅助设计。它的工作方式是我提供一个图表环境

\NewDocumentEnvironment{\diagram}{}{
  \tikzpicture[diagram]
}{
  \endtikzpicture
}

箭头命令

\NewDocumentCommand{\arrow}{ommmo}{
  \IfNoValueTF{#1}{
    \IfNoValueTF{#5}{
      \draw[->] (#2) edge[decorate] node[font=\footnotesize] {\ensuremath{#4}} (#3);
    }{
      \draw[->] (#2) edge[decorate] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
    }
  }{
    \IfNoValueTF{#5}{
      \draw[->,#1] (#2) edge[decorate,#1] node[font=\footnotesize] {\ensuremath{#4}} (#3);
    }{
      \draw[->,#1] (#2) edge[decorate,#1] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
    }
  }
}

以及网格命令,例如

\NewDocumentCommand{\twobytwo}{omomomomo}{
  \def\tempmatopt{\IfNoValueTF{#1}{}{#1}}
  \def\tempa{\IfNoValueTF{#2}{}{#2}}
  \def\tempaopt{\IfNoValueTF{#3}{}{#3}}
  \def\tempb{\IfNoValueTF{#4}{}{#4}}
  \def\tempbopt{\IfNoValueTF{#5}{}{#5}}
  \def\tempc{\IfNoValueTF{#6}{}{#6}}
  \def\tempcopt{\IfNoValueTF{#7}{}{#7}}
  \def\tempd{\IfNoValueTF{#8}{}{#8}}
  \def\tempdopt{\IfNoValueTF{#9}{}{#9}}
  \matrix[objects,\tempmatopt]{
    \node[\tempaopt] (nw) {\ensuremath{\tempa}};\&
    \node[\tempbopt] (ne) {\ensuremath{\tempb}};\\
    \node[\tempcopt] (sw) {\ensuremath{\tempc}};\&
    \node[\tempdopt] (se) {\ensuremath{\tempd}};\\
  };
}

正如你所见,即使是 2x2 的图也需要很多参数,所以我不得不想出一个解决方案来传递超过九个参数NewDocumentCommand允许的参数。我使用的 hack 对于大小为 2x3、2x4、3x4、4x4、5x4 的图表非常有效,但对于大小为 5x5 的图表突然中断。当我尝试命令时

\begin{diagram}
  \fivebyfive
    {A}{B}{C}{D}{E}
    {F}{G}{H}{I}{J}
    {K}{L}{M}{N}{O}
    {P}{Q}{R}{S}{T}
    {U}{V}{W}{X}{Y}
\end{diagram}

我得到了错误未定义控制序列。[{U}{V}{W}{X}{Y}]尽管图表几乎按预期呈现。我不明白为什么。此命令的代码如下:

% A B C D E
% F G H I J
% K L M N O
% P Q R S T
% U V W X Y
\makeatletter
\NewDocumentCommand{\fivebyfive}{omomomomo}{
    \def\tempmatopt{\IfNoValueTF{#1}{}{#1}}%
    \def\tempa{\IfNoValueTF{#2}{}{#2}}%
    \def\tempaopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempb{\IfNoValueTF{#4}{}{#4}}%
    \def\tempbopt{\IfNoValueTF{#5}{}{#5}}%
    \def\tempc{\IfNoValueTF{#6}{}{#6}}%
    \def\tempcopt{\IfNoValueTF{#7}{}{#7}}%
    \def\tempd{\IfNoValueTF{#8}{}{#8}}%
    \def\tempdopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecont%
}
\NewDocumentCommand{\@fivebyfivecont}{momomomom}{
    \def\tempe{\IfNoValueTF{#1}{}{#1}}%
    \def\tempeopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempf{\IfNoValueTF{#3}{}{#3}}%
    \def\tempfopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempg{\IfNoValueTF{#5}{}{#5}}%
    \def\tempgopt{\IfNoValueTF{#6}{}{#6}}%
    \def\temph{\IfNoValueTF{#7}{}{#7}}%
    \def\temphopt{\IfNoValueTF{#8}{}{#8}}%
    \def\tempi{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcont%
}
\NewDocumentCommand{\@fivebyfivecontcont}{omomomomo}{
    \def\tempiopt{\IfNoValueTF{#1}{}{#1}}%
    \def\tempj{\IfNoValueTF{#2}{}{#2}}%
    \def\tempjopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempk{\IfNoValueTF{#4}{}{#4}}%
    \def\tempkopt{\IfNoValueTF{#5}{}{#5}}%
    \def\templ{\IfNoValueTF{#6}{}{#6}}%
    \def\templopt{\IfNoValueTF{#7}{}{#7}}%
    \def\tempm{\IfNoValueTF{#8}{}{#8}}%
    \def\tempmopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcont}{momomomom}{
    \def\tempn{\IfNoValueTF{#1}{}{#1}}%
    \def\tempnopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempo{\IfNoValueTF{#3}{}{#3}}%
    \def\tempoopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempp{\IfNoValueTF{#5}{}{#5}}%
    \def\temppopt{\IfNoValueTF{#6}{}{#6}}%
    \def\tempq{\IfNoValueTF{#7}{}{#7}}%
    \def\tempqopt{\IfNoValueTF{#8}{}{#8}}%
    \def\tempr{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcont}{omomomomo}{
    \def\tempropt{\IfNoValueTF{#1}{}{#1}}%
    \def\temps{\IfNoValueTF{#2}{}{#2}}%
    \def\tempsopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempt{\IfNoValueTF{#4}{}{#4}}%
    \def\temptopt{\IfNoValueTF{#5}{}{#5}}%
    \def\tempu{\IfNoValueTF{#6}{}{#6}}%
    \def\tempuopt{\IfNoValueTF{#7}{}{#7}}%
    \def\temvt{\IfNoValueTF{#8}{}{#8}}%
    \def\temvtopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcontcont}{momomo}{
    \def\tempw{\IfNoValueTF{#1}{}{#1}}%
    \def\tempwopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempx{\IfNoValueTF{#3}{}{#3}}%
    \def\tempxopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempy{\IfNoValueTF{#5}{}{#5}}%
    \def\tempyopt{\IfNoValueTF{#6}{}{#6}}%
    \matrix[objects,\tempmatopt]{%
        \node[\tempaopt] (nnww) {\ensuremath{\tempa}};\&%
        \node[\tempbopt] (nnw) {\ensuremath{\tempb}};\&%
        \node[\tempcopt] (nn) {\ensuremath{\tempc}};\&%
        \node[\tempdopt] (nne) {\ensuremath{\tempd}};\&%
        \node[\tempeopt] (nnee) {\ensuremath{\tempe}};\\%
        \node[\tempfopt] (nww) {\ensuremath{\tempf}};\&%
        \node[\tempgopt] (nw) {\ensuremath{\tempg}};\&%
        \node[\temphopt] (n) {\ensuremath{\temph}};\&%
        \node[\tempiopt] (ne) {\ensuremath{\tempi}};\&%
        \node[\tempjopt] (nee) {\ensuremath{\tempj}};\\%
        \node[\tempkopt] (ww) {\ensuremath{\tempk}};\&%
        \node[\templopt] (w) {\ensuremath{\templ}};\&%
        \node[\tempmopt] (c) {\ensuremath{\tempm}};\&%
        \node[\tempnopt] (e) {\ensuremath{\tempn}};\&%
        \node[\tempoopt] (ee) {\ensuremath{\tempo}};\\%
        \node[\temppopt] (sww) {\ensuremath{\tempp}};\&%
        \node[\tempqopt] (sw) {\ensuremath{\tempq}};\&%
        \node[\tempropt] (s) {\ensuremath{\tempr}};\&%
        \node[\tempsopt] (se) {\ensuremath{\temps}};\&%
        \node[\temptopt] (see) {\ensuremath{\tempt}};\\%
        \node[\tempuopt] (ssww) {\ensuremath{\tempu}};\&%
        \node[\tempvopt] (ssw) {\ensuremath{\tempv}};\&%
        \node[\tempwopt] (ss) {\ensuremath{\tempw}};\&%
        \node[\tempxopt] (sse) {\ensuremath{\tempx}};\&%
        \node[\tempyopt] (ssee) {\ensuremath{\tempy}};\\%
    };
}
\makeatother

什么原因导致错误?

非常感谢您的宝贵时间!

附言:我知道不应该一次问多个问题。但考虑到这么多背景信息,我觉得不提一下我遇到的另外两个问题太可惜了。我不指望能得到任何答案(烦人的错误就是上面的问题),请原谅。

附加问题

  • 使用\tikzset命令我定义属性像\tikzset{epi/.append style={->>}}和像这样的东西\arrow[epi,gray]{nw}{se}{}工作得很好。但对于网格命令则不行。写入\twobytwo[wide,high]{}{}{}{}会抛出错误程序包 pgfkeys 错误:我不知道密钥“/tikz/wide,high”。 我该如何解决?

  • 如果起始节点的名称有问题,我的箭头在其源头处会多出一个意外的箭头尖(看起来像 >-->)。这是为什么?

最小(不)工作示例

\documentclass{article}

\usepackage{xparse} % better command definition
\usepackage{xstring} % strings
\usepackage{tikz}
    \usetikzlibrary{matrix} % node placement
    \usetikzlibrary{calc} % calculation
    \usetikzlibrary{decorations.pathmorphing} %snaked
    \usetikzlibrary{arrows} % right hook->
    \usetikzlibrary{arrows.meta} % -Implies

% --- tikz styles and commands
\tikzset{diagram/.append style={
    baseline={($(current bounding box.center) + (0pt,-0.15\baselineskip)$)}
}}

\tikzset{objects/.append style={
    matrix of nodes,
    ampersand replacement=\&, % replaces the column indicator from & to \&
    text height=1.75ex, text depth=0.5ex, % fixes some text alignment issues with nodes
    column sep={5em,between origins}, row sep={4.5em,between origins} % width of node does not influence column spacing
}}

\tikzset{wide/.append style={
    column sep={6em,between origins}
}}
\tikzset{high/.append style={
    row sep={5.5em,between origins}
}}

\tikzset{equals/.append style={
    -,
    double,
    double distance=0.2em
}}
\tikzset{incl/.append style={right hook->}}
\tikzset{epi/.append style={->>}}
\tikzset{mono/.append style={>->}}
\tikzset{mapsto/.append style={|->}}
\tikzset{implies/.append style={
    arrows={-Implies},
    double,
    double distance=0.2em
}}

\tikzset{snaked/.append style={
    decoration={
        snake,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{zigzaged/.append style={
    decoration={
        zigzag,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{higher/.append style={
    transform canvas={
        yshift=+.3ex
    }
}}
\tikzset{lower/.append style={
    transform canvas={
        yshift=-.3ex
    }
}}
\tikzset{righter/.append style={
    transform canvas={
        xshift=+.3ex
    }
}}
\tikzset{lefter/.append style={
    transform canvas={
        xshift=-.3ex
    }
}}
\tikzset{ontop/.append style={
    fill=white
}}

\NewDocumentEnvironment{diagram}{}{
    \tikzpicture[diagram]
}{
    \endtikzpicture
}

\NewDocumentCommand{\arrow}{ommmo}{
    \IfNoValueTF{#1}{
        \IfNoValueTF{#5}{
            \draw[->] (#2) edge[decorate] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->] (#2) edge[decorate] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }{
        \IfNoValueTF{#5}{
            \draw[->,#1] (#2) edge[decorate,#1] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->,#1] (#2) edge[decorate,#1] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }
}

% --- common diagram shapes

% A B
% C D
\makeatletter
\NewDocumentCommand{\twobytwo}{omomomomo}{
    \def\tempmatopt{\IfNoValueTF{#1}{}{#1}}
    \def\tempa{\IfNoValueTF{#2}{}{#2}}
    \def\tempaopt{\IfNoValueTF{#3}{}{#3}}
    \def\tempb{\IfNoValueTF{#4}{}{#4}}
    \def\tempbopt{\IfNoValueTF{#5}{}{#5}}
    \def\tempc{\IfNoValueTF{#6}{}{#6}}
    \def\tempcopt{\IfNoValueTF{#7}{}{#7}}
    \def\tempd{\IfNoValueTF{#8}{}{#8}}
    \def\tempdopt{\IfNoValueTF{#9}{}{#9}}
    \matrix[objects,\tempmatopt]{
        \node[\tempaopt] (nw) {\ensuremath{\tempa}};\&
        \node[\tempbopt] (ne) {\ensuremath{\tempb}};\\
        \node[\tempcopt] (sw) {\ensuremath{\tempc}};\&
        \node[\tempdopt] (se) {\ensuremath{\tempd}};\\
    };
}
\makeatother

% A B C D E
% F G H I J
% K L M N O
% P Q R S T
% U V W X Y
\makeatletter
\NewDocumentCommand{\fivebyfive}{omomomomo}{
    \def\tempmatopt{\IfNoValueTF{#1}{}{#1}}%
    \def\tempa{\IfNoValueTF{#2}{}{#2}}%
    \def\tempaopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempb{\IfNoValueTF{#4}{}{#4}}%
    \def\tempbopt{\IfNoValueTF{#5}{}{#5}}%
    \def\tempc{\IfNoValueTF{#6}{}{#6}}%
    \def\tempcopt{\IfNoValueTF{#7}{}{#7}}%
    \def\tempd{\IfNoValueTF{#8}{}{#8}}%
    \def\tempdopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecont%
}
\NewDocumentCommand{\@fivebyfivecont}{momomomom}{
    \def\tempe{\IfNoValueTF{#1}{}{#1}}%
    \def\tempeopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempf{\IfNoValueTF{#3}{}{#3}}%
    \def\tempfopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempg{\IfNoValueTF{#5}{}{#5}}%
    \def\tempgopt{\IfNoValueTF{#6}{}{#6}}%
    \def\temph{\IfNoValueTF{#7}{}{#7}}%
    \def\temphopt{\IfNoValueTF{#8}{}{#8}}%
    \def\tempi{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcont%
}
\NewDocumentCommand{\@fivebyfivecontcont}{omomomomo}{
    \def\tempiopt{\IfNoValueTF{#1}{}{#1}}%
    \def\tempj{\IfNoValueTF{#2}{}{#2}}%
    \def\tempjopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempk{\IfNoValueTF{#4}{}{#4}}%
    \def\tempkopt{\IfNoValueTF{#5}{}{#5}}%
    \def\templ{\IfNoValueTF{#6}{}{#6}}%
    \def\templopt{\IfNoValueTF{#7}{}{#7}}%
    \def\tempm{\IfNoValueTF{#8}{}{#8}}%
    \def\tempmopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcont}{momomomom}{
    \def\tempn{\IfNoValueTF{#1}{}{#1}}%
    \def\tempnopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempo{\IfNoValueTF{#3}{}{#3}}%
    \def\tempoopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempp{\IfNoValueTF{#5}{}{#5}}%
    \def\temppopt{\IfNoValueTF{#6}{}{#6}}%
    \def\tempq{\IfNoValueTF{#7}{}{#7}}%
    \def\tempqopt{\IfNoValueTF{#8}{}{#8}}%
    \def\tempr{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcont}{omomomomo}{
    \def\tempropt{\IfNoValueTF{#1}{}{#1}}%
    \def\temps{\IfNoValueTF{#2}{}{#2}}%
    \def\tempsopt{\IfNoValueTF{#3}{}{#3}}%
    \def\tempt{\IfNoValueTF{#4}{}{#4}}%
    \def\temptopt{\IfNoValueTF{#5}{}{#5}}%
    \def\tempu{\IfNoValueTF{#6}{}{#6}}%
    \def\tempuopt{\IfNoValueTF{#7}{}{#7}}%
    \def\temvt{\IfNoValueTF{#8}{}{#8}}%
    \def\temvtopt{\IfNoValueTF{#9}{}{#9}}%
    \@fivebyfivecontcontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcontcont}{momomo}{
    \def\tempw{\IfNoValueTF{#1}{}{#1}}%
    \def\tempwopt{\IfNoValueTF{#2}{}{#2}}%
    \def\tempx{\IfNoValueTF{#3}{}{#3}}%
    \def\tempxopt{\IfNoValueTF{#4}{}{#4}}%
    \def\tempy{\IfNoValueTF{#5}{}{#5}}%
    \def\tempyopt{\IfNoValueTF{#6}{}{#6}}%
    \matrix[objects,\tempmatopt]{%
        \node[\tempaopt] (nnww) {\ensuremath{\tempa}};\&%
        \node[\tempbopt] (nnw) {\ensuremath{\tempb}};\&%
        \node[\tempcopt] (nn) {\ensuremath{\tempc}};\&%
        \node[\tempdopt] (nne) {\ensuremath{\tempd}};\&%
        \node[\tempeopt] (nnee) {\ensuremath{\tempe}};\\%
        \node[\tempfopt] (nww) {\ensuremath{\tempf}};\&%
        \node[\tempgopt] (nw) {\ensuremath{\tempg}};\&%
        \node[\temphopt] (n) {\ensuremath{\temph}};\&%
        \node[\tempiopt] (ne) {\ensuremath{\tempi}};\&%
        \node[\tempjopt] (nee) {\ensuremath{\tempj}};\\%
        \node[\tempkopt] (ww) {\ensuremath{\tempk}};\&%
        \node[\templopt] (w) {\ensuremath{\templ}};\&%
        \node[\tempmopt] (c) {\ensuremath{\tempm}};\&%
        \node[\tempnopt] (e) {\ensuremath{\tempn}};\&%
        \node[\tempoopt] (ee) {\ensuremath{\tempo}};\\%
        \node[\temppopt] (sww) {\ensuremath{\tempp}};\&%
        \node[\tempqopt] (sw) {\ensuremath{\tempq}};\&%
        \node[\tempropt] (s) {\ensuremath{\tempr}};\&%
        \node[\tempsopt] (se) {\ensuremath{\temps}};\&%
        \node[\temptopt] (see) {\ensuremath{\tempt}};\\%
        \node[\tempuopt] (ssww) {\ensuremath{\tempu}};\&%
        \node[\tempvopt] (ssw) {\ensuremath{\tempv}};\&%
        \node[\tempwopt] (ss) {\ensuremath{\tempw}};\&%
        \node[\tempxopt] (sse) {\ensuremath{\tempx}};\&%
        \node[\tempyopt] (ssee) {\ensuremath{\tempy}};\\%
    };
}
\makeatother

\begin{document}
    \begin{diagram}
        \twobytwo[wide,high]
            {A}{B}
            {X}{Y}

        \arrow{nw}{ne}{a}[above]
        \arrow{sw}{se}{b}[below]
        \arrow{nw}{sw}{f}[left]
        \arrow{ne}{se}{g}[right]
    \end{diagram}

    \begin{diagram}
        \fivebyfive
            {A}{B}{C}{D}{E}
            {F}{G}{H}{I}{J}
            {K}{L}{M}{N}{O}
            {P}{Q}{R}{S}{T}
            {U}{V}{W}{X}{Y}
    \end{diagram}
\end{document}

答案1

我发现了两个问题。

David Carlisle 也发现了问题 1:

宏的定义\@fivebyfivecontcontcontcontcont包含

\def\temvt{\IfNoValueTF{#8}{}{#8}}%
\def\temvtopt{\IfNoValueTF{#9}{}{#9}}%

代替

\def\tempv{\IfNoValueTF{#8}{}{#8}}%
\def\tempvopt{\IfNoValueTF{#9}{}{#9}}%

问题 2:

我认为错误pgfkeys Error: I do not know the key '/tikz/wide,high'.是由于将宏\tempmatopt放入命令的可选参数中而导致的\matrix,而应该将宏\tempmatopt而不是形成其扩展的标记放在那里。

也许像这样的方法可以达到目的:

\documentclass{article}

\usepackage{xparse} % better command definition
\usepackage{xstring} % strings
\usepackage{tikz}
    \usetikzlibrary{matrix} % node placement
    \usetikzlibrary{calc} % calculation
    \usetikzlibrary{decorations.pathmorphing} %snaked
    \usetikzlibrary{arrows} % right hook->
    \usetikzlibrary{arrows.meta} % -Implies

% --- tikz styles and commands
\tikzset{diagram/.append style={
    baseline={($(current bounding box.center) + (0pt,-0.15\baselineskip)$)}
}}

\tikzset{objects/.append style={
    matrix of nodes,
    ampersand replacement=\&, % replaces the column indicator from & to \&
    text height=1.75ex, text depth=0.5ex, % fixes some text alignment issues with nodes
    column sep={5em,between origins}, row sep={4.5em,between origins} % width of node does not influence column spacing
}}

\tikzset{wide/.append style={
    column sep={6em,between origins}
}}
\tikzset{high/.append style={
    row sep={5.5em,between origins}
}}

\tikzset{equals/.append style={
    -,
    double,
    double distance=0.2em
}}
\tikzset{incl/.append style={right hook->}}
\tikzset{epi/.append style={->>}}
\tikzset{mono/.append style={>->}}
\tikzset{mapsto/.append style={|->}}
\tikzset{implies/.append style={
    arrows={-Implies},
    double,
    double distance=0.2em
}}

\tikzset{snaked/.append style={
    decoration={
        snake,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{zigzaged/.append style={
    decoration={
        zigzag,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{higher/.append style={
    transform canvas={
        yshift=+.3ex
    }
}}
\tikzset{lower/.append style={
    transform canvas={
        yshift=-.3ex
    }
}}
\tikzset{righter/.append style={
    transform canvas={
        xshift=+.3ex
    }
}}
\tikzset{lefter/.append style={
    transform canvas={
        xshift=-.3ex
    }
}}
\tikzset{ontop/.append style={
    fill=white
}}

\NewDocumentEnvironment{diagram}{}{
    \tikzpicture[diagram]
}{
    \endtikzpicture
}

\NewDocumentCommand{\arrow}{ommmo}{
    \IfNoValueTF{#1}{
        \IfNoValueTF{#5}{
            \draw[->] (#2) edge[decorate] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->] (#2) edge[decorate] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }{
        \IfNoValueTF{#5}{
            \draw[->,#1] (#2) edge[decorate,#1] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->,#1] (#2) edge[decorate,#1] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }
}

% --- common diagram shapes

% A B
% C D
\makeatletter
\newcommand\exchange[2]{#2#1}
\newcommand\DefineIfValue[2]{%
  \IfNoValueTF{#2}{\def#1{}}{\def#1{#2}}%
}%
\NewDocumentCommand{\twobytwo}{omomomomo}{
    \DefineIfValue\tempmatopt{#1}
    \DefineIfValue\tempa{#2}
    \DefineIfValue\tempaopt{#3}
    \DefineIfValue\tempb{#4}
    \DefineIfValue\tempbopt{#5}
    \DefineIfValue\tempc{#6}
    \DefineIfValue\tempcopt{#7}
    \DefineIfValue\tempd{#8}
    \DefineIfValue\tempdopt{#9}
    \expandafter\exchange\expandafter{\tempmatopt}{\matrix[objects,}]{
        \expandafter\node\expandafter[\tempaopt] (nw) {\ensuremath{\tempa}};\&
        \expandafter\node\expandafter[\tempbopt] (ne) {\ensuremath{\tempb}};\\
        \expandafter\node\expandafter[\tempcopt] (sw) {\ensuremath{\tempc}};\&
        \expandafter\node\expandafter[\tempdopt] (se) {\ensuremath{\tempd}};\\
    };
}
\makeatother

% A B C D E
% F G H I J
% K L M N O
% P Q R S T
% U V W X Y
\makeatletter
\NewDocumentCommand{\fivebyfive}{omomomomo}{
    \DefineIfValue\tempmatopt{#1}%
    \DefineIfValue\tempa{#2}%
    \DefineIfValue\tempaopt{#3}%
    \DefineIfValue\tempb{#4}%
    \DefineIfValue\tempbopt{#5}%
    \DefineIfValue\tempc{#6}%
    \DefineIfValue\tempcopt{#7}%
    \DefineIfValue\tempd{#8}%
    \DefineIfValue\tempdopt{#9}%
    \@fivebyfivecont%
}
\NewDocumentCommand{\@fivebyfivecont}{momomomom}{
    \DefineIfValue\tempe{#1}%
    \DefineIfValue\tempeopt{#2}%
    \DefineIfValue\tempf{#3}%
    \DefineIfValue\tempfopt{#4}%
    \DefineIfValue\tempg{#5}%
    \DefineIfValue\tempgopt{#6}%
    \DefineIfValue\temph{#7}%
    \DefineIfValue\temphopt{#8}%
    \DefineIfValue\tempi{#9}%
    \@fivebyfivecontcont%
}
\NewDocumentCommand{\@fivebyfivecontcont}{omomomomo}{
    \DefineIfValue\tempiopt{#1}%
    \DefineIfValue\tempj{#2}%
    \DefineIfValue\tempjopt{#3}%
    \DefineIfValue\tempk{#4}%
    \DefineIfValue\tempkopt{#5}%
    \DefineIfValue\templ{#6}%
    \DefineIfValue\templopt{#7}%
    \DefineIfValue\tempm{#8}%
    \DefineIfValue\tempmopt{#9}%
    \@fivebyfivecontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcont}{momomomom}{
    \DefineIfValue\tempn{#1}%
    \DefineIfValue\tempnopt{#2}%
    \DefineIfValue\tempo{#3}%
    \DefineIfValue\tempoopt{#4}%
    \DefineIfValue\tempp{#5}%
    \DefineIfValue\temppopt{#6}%
    \DefineIfValue\tempq{#7}%
    \DefineIfValue\tempqopt{#8}%
    \DefineIfValue\tempr{#9}%
    \@fivebyfivecontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcont}{omomomomo}{
    \DefineIfValue\tempropt{#1}%
    \DefineIfValue\temps{#2}%
    \DefineIfValue\tempsopt{#3}%
    \DefineIfValue\tempt{#4}%
    \DefineIfValue\temptopt{#5}%
    \DefineIfValue\tempu{#6}%
    \DefineIfValue\tempuopt{#7}%
%%
%    \def\temvt{\IfNoValueTF{#8}{}{#8}}%
%    \def\temvtopt{\IfNoValueTF{#9}{}{#9}}%
    \DefineIfValue\tempv{#8}%
    \DefineIfValue\tempvopt{#9}%
    \@fivebyfivecontcontcontcontcontcont%
}
\NewDocumentCommand{\@fivebyfivecontcontcontcontcontcont}{momomo}{
    \DefineIfValue\tempw{#1}%
    \DefineIfValue\tempwopt{#2}%
    \DefineIfValue\tempx{#3}%
    \DefineIfValue\tempxopt{#4}%
    \DefineIfValue\tempy{#5}%
    \DefineIfValue\tempyopt{#6}%
    \expandafter\exchange\expandafter{\tempmatopt}{\matrix[objects,}]{%
        \expandafter\node\expandafter[\tempaopt] (nnww) {\ensuremath{\tempa}};\&%
        \expandafter\node\expandafter[\tempbopt] (nnw) {\ensuremath{\tempb}};\&%
        \expandafter\node\expandafter[\tempcopt] (nn) {\ensuremath{\tempc}};\&%
        \expandafter\node\expandafter[\tempdopt] (nne) {\ensuremath{\tempd}};\&%
        \expandafter\node\expandafter[\tempeopt] (nnee) {\ensuremath{\tempe}};\\%
        \expandafter\node\expandafter[\tempfopt] (nww) {\ensuremath{\tempf}};\&%
        \expandafter\node\expandafter[\tempgopt] (nw) {\ensuremath{\tempg}};\&%
        \expandafter\node\expandafter[\temphopt] (n) {\ensuremath{\temph}};\&%
        \expandafter\node\expandafter[\tempiopt] (ne) {\ensuremath{\tempi}};\&%
        \expandafter\node\expandafter[\tempjopt] (nee) {\ensuremath{\tempj}};\\%
        \expandafter\node\expandafter[\tempkopt] (ww) {\ensuremath{\tempk}};\&%
        \expandafter\node\expandafter[\templopt] (w) {\ensuremath{\templ}};\&%
        \expandafter\node\expandafter[\tempmopt] (c) {\ensuremath{\tempm}};\&%
        \expandafter\node\expandafter[\tempnopt] (e) {\ensuremath{\tempn}};\&%
        \expandafter\node\expandafter[\tempoopt] (ee) {\ensuremath{\tempo}};\\%
        \expandafter\node\expandafter[\temppopt] (sww) {\ensuremath{\tempp}};\&%
        \expandafter\node\expandafter[\tempqopt] (sw) {\ensuremath{\tempq}};\&%
        \expandafter\node\expandafter[\tempropt] (s) {\ensuremath{\tempr}};\&%
        \expandafter\node\expandafter[\tempsopt] (se) {\ensuremath{\temps}};\&%
        \expandafter\node\expandafter[\temptopt] (see) {\ensuremath{\tempt}};\\%
        \expandafter\node\expandafter[\tempuopt] (ssww) {\ensuremath{\tempu}};\&%
        \expandafter\node\expandafter[\tempvopt] (ssw) {\ensuremath{\tempv}};\&%
        \expandafter\node\expandafter[\tempwopt] (ss) {\ensuremath{\tempw}};\&%
        \expandafter\node\expandafter[\tempxopt] (sse) {\ensuremath{\tempx}};\&%
        \expandafter\node\expandafter[\tempyopt] (ssee) {\ensuremath{\tempy}};\\%
    };
}
\makeatother

\begin{document}
    \begin{diagram}
        \twobytwo[wide,high]
            {A}{B}
            {X}{Y}

        \arrow{nw}{ne}{a}[above]
        \arrow{sw}{se}{b}[below]
        \arrow{nw}{sw}{f}[left]
        \arrow{ne}{se}{g}[right]
    \end{diagram}

    \begin{diagram}
        \fivebyfive
            {A}{B}{C}{D}{E}
            {F}{G}{H}{I}{J}
            {K}{L}{M}{N}{O}
            {P}{Q}{R}{S}{T}
            {U}{V}{W}{X}{Y}
    \end{diagram}
\end{document}

也许你可以定义一个循环,以尾部递归的方式抓取非可选参数和可选参数,直到得到模式为 { 的参数对列表⟨地点⟩}{⟨matrix-command (\\\&)⟩} 为空/空白:

\documentclass{article}

\usepackage{xparse} % better command definition
\usepackage{xstring} % strings
\usepackage{tikz}
    \usetikzlibrary{matrix} % node placement
    \usetikzlibrary{calc} % calculation
    \usetikzlibrary{decorations.pathmorphing} %snaked
    \usetikzlibrary{arrows} % right hook->
    \usetikzlibrary{arrows.meta} % -Implies

% --- tikz styles and commands
\tikzset{diagram/.append style={
    baseline={($(current bounding box.center) + (0pt,-0.15\baselineskip)$)}
}}

\tikzset{objects/.append style={
    matrix of nodes,
    ampersand replacement=\&, % replaces the column indicator from & to \&
    text height=1.75ex, text depth=0.5ex, % fixes some text alignment issues with nodes
    column sep={5em,between origins}, row sep={4.5em,between origins} % width of node does not influence column spacing
}}

\tikzset{wide/.append style={
    column sep={6em,between origins}
}}
\tikzset{high/.append style={
    row sep={5.5em,between origins}
}}

\tikzset{equals/.append style={
    -,
    double,
    double distance=0.2em
}}
\tikzset{incl/.append style={right hook->}}
\tikzset{epi/.append style={->>}}
\tikzset{mono/.append style={>->}}
\tikzset{mapsto/.append style={|->}}
\tikzset{implies/.append style={
    arrows={-Implies},
    double,
    double distance=0.2em
}}

\tikzset{snaked/.append style={
    decoration={
        snake,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{zigzaged/.append style={
    decoration={
        zigzag,
        amplitude=.4mm,
        segment length=2mm,
        pre length=1mm,
        post length=1mm
    }
}}
\tikzset{higher/.append style={
    transform canvas={
        yshift=+.3ex
    }
}}
\tikzset{lower/.append style={
    transform canvas={
        yshift=-.3ex
    }
}}
\tikzset{righter/.append style={
    transform canvas={
        xshift=+.3ex
    }
}}
\tikzset{lefter/.append style={
    transform canvas={
        xshift=-.3ex
    }
}}
\tikzset{ontop/.append style={
    fill=white
}}

\NewDocumentEnvironment{diagram}{}{
    \tikzpicture[diagram]
}{
    \endtikzpicture
}

\NewDocumentCommand{\arrow}{ommmo}{
    \IfNoValueTF{#1}{
        \IfNoValueTF{#5}{
            \draw[->] (#2) edge[decorate] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->] (#2) edge[decorate] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }{
        \IfNoValueTF{#5}{
            \draw[->,#1] (#2) edge[decorate,#1] node[font=\footnotesize] {\ensuremath{#4}} (#3);
        }{
            \draw[->,#1] (#2) edge[decorate,#1] node[#5,font=\footnotesize] {\ensuremath{#4}} (#3);
        }
    }
}

% --- common diagram shapes

\makeatletter
\@ifdefinable\NodeLoop{%
  \long\def\NodeLoop#1#2#3\DELIMITER{%
    % #1 nodes collected so far
    % #2 \matrix-command when loop terminates
    % #3 remaining locations/table-commands
    \ifcat$\detokenize\expandafter{\@firstoftwo#3{}{}}$%
      \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi  
    {#2{#1};}%
    {\LoopNode{#1}{#2}#3\DELIMITER}%
  }%
}%
\@ifdefinable\LoopNode{%
  \long\def\LoopNode#1#2#3#4#5\DELIMITER{%
    % #1 nodes collected so far
    % #2 \matrix-command when loop terminates
    % #3 location of this node
    % #4 table-command (\& or \\) of this node
    % #5 remaining locations/table-commands
    \LoopNodeArgs{#1}{#2}{#3}{#4}{#5}%
  }%
}%
\NewDocumentCommand\LoopNodeArgs{mmmmmmo}{%
  % #1 nodes collected so far
  % #2 \matrix-command when loop terminates
  % #3 location of this node
  % #4 table-command (\& or \\) of this node
  % #5 remaining locations/table-commands
  % #6 label of this node
  % #7 opt argument of this node
  \IfNoValueTF{#7}{%
     \NodeLoop{#1\node(#3){\ensuremath{#6}};#4}%
  }{%
     \NodeLoop{#1\node[{#7}](#3){\ensuremath{#6}};#4}%
  }%
  {#2}#5\DELIMITER
}%
\NewDocumentCommand{\twobytwo}{o}{%
  \IfNoValueTF{#1}{\NodeLoop{}{\matrix[objects]}}%
                  {\NodeLoop{}{\matrix[objects, #1]}}%
        {nw}{\&}
        {ne}{\\}
        {sw}{\&}
        {se}{\\}
        \DELIMITER 
}%
\NewDocumentCommand{\fivebyfive}{o}{%
  \IfNoValueTF{#1}{\NodeLoop{}{\matrix[objects]}}%
                  {\NodeLoop{}{\matrix[objects, #1]}}%
        {nnww}{\&}
        {nnw}{\&}
        {nn}{\&}
        {nne}{\&}
        {nnee}{\\}
        {nww}{\&}
        {nw}{\&}
        {n}{\&}
        {ne}{\&}
        {nee}{\\}
        {ww}{\&}
        {w}{\&}
        {c}{\&}
        {e}{\&}
        {ee}{\\}
        {sww}{\&}
        {sw}{\&}
        {s}{\&}
        {se}{\&}
        {see}{\\}
        {ssww}{\&}
        {ssw}{\&}
        {ss}{\&}
        {sse}{\&}
        {ssee}{\\}
        \DELIMITER 
}%
\makeatother

\begin{document}

    \begin{diagram}
        \twobytwo [column sep=2em, row sep=2em]
            {A}[green]{B}[brown]
            {C}[brown]{D}[green]

        \arrow{nw}{ne}{a}[above]
        \arrow{sw}{se}{b}[below]
        \arrow{nw}{sw}{f}[left]
        \arrow{ne}{se}{g}[right]
    \end{diagram}

    \noindent\hrule

     \begin{diagram}
        \fivebyfive [column sep=1em, row sep=1em]
            {A}[green]{B}[brown]{C}[green]{D}[brown]{E}[green]
            {F}[brown]{G}[green]{H}[brown]{I}[green]{J}[brown]
            {K}[green]{L}[brown]{M}[green]{N}[brown]{O}[green]
            {P}[brown]{Q}[green]{R}[brown]{S}[green]{T}[brown]
            {U}[green]{V}[brown]{W}[green]{X}[brown]{Y}[green]
    \end{diagram}

\end{document}

在此处输入图片描述

答案2

第一个错误是

! Package pgfkeys Error: I do not know the key '/tikz/wide,high

所以我刚刚用\twobytwo[wide]

未定义的命令是\tempvopt\tempv你没有定义,我认为是由于拼写错误,而你是故意的

    \def\temvt{\IfNoValueTF{#8}{}{#8}}%
    \def\temvtopt{\IfNoValueTF{#9}{}{#9}}%

你定义它但不要使用它

    \def\tempv{\IfNoValueTF{#8}{}{#8}}%
    \def\tempvopt{\IfNoValueTF{#9}{}{#9}}%

相关内容