在我开始提问之前,我想说的是,我很清楚以下内容可能是非标准的甚至是无意义的 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}}%