目标是从字符串生成 TikZ 矩阵的行。
在下面的示例中,\drawpodpair{NAME:TYPE}{SCOPE}
生成一个矩阵行。我想\foreach
调用以下形式的字符串来获取 NAME:TYPE 对。我知道在矩阵中N1:T1,N2:T2,...
无法做到这一点,所以我使用它来组装矩阵主体。\foreach
\xappto
如果\xappto
一次明确给出一个调用,则它可以工作,但如果\xappto
在内部使用则不行\foreach
:
\documentclass[tikz,border=10pt,a4paper]{standalone}
\usepackage[english]{babel}
\usepackage{etoolbox}
\usetikzlibrary{arrows,intersections,shapes,backgrounds,scopes,positioning,fit,matrix}
\tikzset{varname/.style={rectangle,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{vartype/.style={rectangle,text=red,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{struct/.style={matrix of nodes,draw,column 1/.style={anchor=base west},column 2/.style={anchor=base west}}}
\newcommand\drawpodpair[2]{\drawpodpairdoit#2:#1\relax}
\def\drawpodpairdoit#1:#2:#3\relax%
{%
\node[varname] (#1-#2) {#2}; \pgfmatrixnextcell \node[vartype] (#1-#3) {#3}; \\%
}
\begin{document}
\begin{tikzpicture}
\let\mymatrixcontent\empty
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x1:a11}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x2:a12}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x3:a13}{x}}}
\foreach \p in {a:int,b:char *,c:bool}
{
%\xappto\mymatrixcontent{\expandonce{\drawpodpair{\p}{x}}} <<< ------ UNCOMMENT THIS
}
\matrix (foo) [struct]
{
\mymatrixcontent <<< ------ TO CAUSE AN ERROR HERE
};
\end{tikzpicture}
\end{document}
我希望注释掉的行能够工作,但是当矩阵尝试包含\mymatrixcontent
Undefined control sequence.
<argument> x-\p
\relax \drawpodpairdoit x
l.33 \mymatrixconten
答案1
你可以避免每一个\expandafter
:
\documentclass[tikz,border=10pt,a4paper]{standalone}
\usepackage[english]{babel}
\usepackage{xparse}
\usetikzlibrary{arrows,intersections,shapes,backgrounds,scopes,positioning,fit,matrix}
\tikzset{
varname/.style={
rectangle,
thin,
inner sep=0.3ex,
font=\ttfamily,
text height=1.5ex,
text depth=0.35ex,
},
vartype/.style={
rectangle,
text=red,
thin,
inner sep=0.3ex,
font=\ttfamily,
text height=1.5ex,
text depth=0.35ex,
},
struct/.style={
matrix of nodes,
draw,
column 1/.style={anchor=base west},
column 2/.style={anchor=base west},
},
}
\newcommand\drawpodpair[2]{\drawpodpairdoit#2:#1\relax}
\def\drawpodpairdoit#1:#2:#3\relax{%
\node[varname] (#1-#2) {#2}; \pgfmatrixnextcell \node[vartype] (#1-#3) {#3}; \\
}
\ExplSyntaxOn
\NewDocumentCommand{\appendto}{mm}
{
\tl_put_right:Nn #1 { #2 }
}
\NewDocumentCommand{\clear}{m}
{
\tl_clear_new:N #1
}
\NewDocumentCommand{\cycle}{mm}
{
\clist_map_inline:nn { #1 } { #2 }
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\clear\mymatrixcontent
\cycle{x1:a11,x2:a12,x3:a13,a:int,b:char *,c:bool}
{
\appendto\mymatrixcontent{\drawpodpair{#1}{x}}
}
\matrix (foo) [struct]
{
\mymatrixcontent
};
\end{tikzpicture}
\end{document}
答案2
我只是\expandafter
想\p
\documentclass[tikz,border=10pt,a4paper]{standalone}
\usepackage[english]{babel}
\usepackage{etoolbox}
\usetikzlibrary{arrows,intersections,shapes,backgrounds,scopes,positioning,fit,matrix}
\tikzset{varname/.style={rectangle,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{vartype/.style={rectangle,text=red,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{struct/.style={matrix of nodes,draw,column 1/.style={anchor=base west},column 2/.style={anchor=base west}}}
\newcommand\drawpodpair[2]{\drawpodpairdoit#2:#1\relax}
\def\drawpodpairdoit#1:#2:#3\relax%
{%
\node[varname] (#1-#2) {#2}; \pgfmatrixnextcell \node[vartype] (#1-#3) {#3}; \\%
}
\begin{document}
\begin{tikzpicture}
\let\mymatrixcontent\empty
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x1:a11}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x2:a12}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x3:a13}{x}}}
\foreach \p in {a:int,b:char *,c:bool}
{
\expandafter\xappto\expandafter\mymatrixcontent\expandafter{%
\expandafter\expandonce\expandafter{\expandafter\drawpodpair%
\expandafter{\p}{x}}} %<<< ------ UNCOMMENT THIS
}
\matrix (foo) [struct]
{
\mymatrixcontent% <<< ------ TO CAUSE AN ERROR HERE
};
\end{tikzpicture}
\end{document}
答案3
扩展\p
时间的一种方法是
\documentclass[tikz,border=10pt,a4paper]{standalone}
\usepackage[english]{babel}
\usepackage{etoolbox}
\usetikzlibrary{arrows,intersections,shapes,backgrounds,scopes,positioning,fit,matrix}
\tikzset{varname/.style={rectangle,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{vartype/.style={rectangle,text=red,thin,inner sep=0.3ex,font=\ttfamily,text height=1.5ex,text depth=0.35ex}}
\tikzset{struct/.style={matrix of nodes,draw,column 1/.style={anchor=base west},column 2/.style={anchor=base west}}}
\newcommand\drawpodpair[2]{\drawpodpairdoit#2:#1\relax}
\def\drawpodpairdoit#1:#2:#3\relax%
{%
\node[varname] (#1-#2) {#2}; \pgfmatrixnextcell \node[vartype] (#1-#3) {#3}; \\%
}
\begin{document}
\begin{tikzpicture}
\let\mymatrixcontent\empty
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x1:a11}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x2:a12}{x}}}
\xappto\mymatrixcontent{\expandonce{\drawpodpair{x3:a13}{x}}}
\foreach \p in {a:int,b:char *,c:bool}
{
\xappto\mymatrixcontent{\expandafter\noexpand\drawpodpair{\p}{x}}
}
\matrix (foo) [struct]
{
\mymatrixcontent % <<< ------ TO CAUSE AN ERROR HERE
};
\end{tikzpicture}
\end{document}