\xappto 生成的代码在 \foreach 中生成时不可用

\xappto 生成的代码在 \foreach 中生成时不可用

目标是从字符串生成 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}

相关内容