\node 中 foreach 的问题,带有矩形分割

\node 中 foreach 的问题,带有矩形分割

我正在尝试使用rectangle split parts循环自动使用foreach。在以下 MWE 中,手动使用\nodepart工作正常。\foreach循环失败,并显示

./makebox-mwe.tex:71: Extra }, or forgotten \endgroup.
\pgfutil@reserved@c ->\egroup 
                              \relax 
l.71 \end{outerenv}

代码:

\documentclass{article}

\usepackage{tikz}
\usepackage{xparse}
\usepackage{etoolbox}
\usetikzlibrary{shapes.multipart}

%% Thanks to egreg, make lrbox* global (requires etoolbox.sty):
\cslet{glrbox}\lrbox
\expandafter\patchcmd\csname glrbox\endcsname{\setbox}{\global\setbox}{}{}
\cslet{endglrbox}\endlrbox

\newsavebox{\myboxi}    
\newsavebox{\myboxii}   
\newsavebox{\myboxiii}
\newsavebox{\myboxiv}   
\newsavebox{\myboxv}

\newcounter{myboxes}

\def\numname#1{%
  \ifcase#1\or one\or two\or three\or four\or five\or six\or seven\or eight\or nine\or ten\or eleven \or twelve\or thirteen\or fourteen\or fifteen\or sixteen\or seventeen\or eighteen\or nineteen\or twenty\fi%
}

\NewDocumentEnvironment{outerenv}{}{%
    \setcounter{myboxes}{0}%
}{%
    \tikz \node[draw,rectangle split,rectangle split parts=5,rectangle split ignore empty parts]
    {%
        %% This does NOT work:
        \foreach \nn in {1,...,\themyboxes}{%
        \edef\tmpname{\csname mybox\romannumeral\nn\endcsname}\typeout{\tmpname}%
        \def\tmpnum{\numname{\nn}}\typeout{\tmpnum}%
        \nodepart{\tmpnum}\usebox{\tmpname}%
        }%
        %%%
        %% This works:
%       \nodepart{one}{\usebox{\myboxi}}
%       \nodepart{two}{\usebox{\myboxii}}
%       \nodepart{three}{\usebox{\myboxiii}}
%       \nodepart{four}{\usebox{\myboxiv}}
%       \nodepart{five}{\usebox{\myboxv}}%
    };%
}

\NewDocumentEnvironment{innerenv}{}{%
    \stepcounter{myboxes}%
    \edef\tmpname{\csname mybox\romannumeral\themyboxes\endcsname}%\typeout{\tmpname}%
    \begin{glrbox}{\tmpname}
        \begin{minipage}[t]{2in}
}{%
        \end{minipage}%
    \end{glrbox}%
}

\begin{document}

\begin{outerenv}

\begin{innerenv}
First
\end{innerenv}

\begin{innerenv}
Second
\end{innerenv}

\begin{innerenv}
Third
\end{innerenv}

\end{outerenv}

\end{document}

笔记:我知道可能有上百万(千亿?)种其他方法可以做到这一点。但我的好奇心在于,为什么这种看似简单的尝试会失败。

答案1

似乎不能\nodepart{..}在组内使用(例如{\nodepart{...}}或在 LaTeX 环境内)。

另一种方法是使用一些不使用组的循环。例如\pgfplotsforeachungrouped\pgfplotsinvokeforeachpgfplots

作为一个穷人的替代品,你有一个xinttools提供\xintFor*循环的轻量级包:

\documentclass{article}

\usepackage{tikz}
\usepackage{xparse}
\usepackage{etoolbox}
\usetikzlibrary{shapes.multipart}

%% Thanks to egreg, make lrbox* global (requires etoolbox.sty):
\cslet{glrbox}\lrbox
\expandafter\patchcmd\csname glrbox\endcsname{\setbox}{\global\setbox}{}{}
\cslet{endglrbox}\endlrbox

\newsavebox{\myboxi}    
\newsavebox{\myboxii}   
\newsavebox{\myboxiii}
\newsavebox{\myboxiv}   
\newsavebox{\myboxv}

\newcounter{myboxes}

\def\numname#1{%
  \ifcase#1 \or one\or two\or three\or four\or five\or six\or seven\or eight\or nine\or ten\or eleven \or twelve\or thirteen\or fourteen\or fifteen\or sixteen\or seventeen\or eighteen\or nineteen\or twenty\fi%
}

\usepackage{xinttools}% for \xintFor/\xintFor* loops

\NewDocumentEnvironment{outerenv}{}{%
    \setcounter{myboxes}{0}%
}{%
    \tikz \node[draw,rectangle split,rectangle split parts=5,rectangle split ignore empty parts]
    {%
%        \foreach\nn in {1, ..., \themyboxes}
% xinttools manual says to use "\do" but we can use any token, such as ":"
        \xintFor* ##1 in {\xintSeq{1}{\value{myboxes}}}:
        {%
%        \edef\tmpname{\csname mybox\romannumeral##1\endcsname}%
%        \def\tmpnum{\numname{##1}}%
%        \nodepart{\tmpnum}\usebox{\tmpname}%
%        \nodepart{\numname{\nn}}\usebox{\csname mybox\romannumeral\nn\endcsname}%
        %\begingroup% just testing to confirm with it same error as in OP
        \nodepart{\numname{##1}}%
        %\endgroup % bien sûr \nodepart n'aime pas cela...
        \usebox{\csname mybox\romannumeral##1\endcsname}%
        }%
        %%%
        %% This works:
      % \nodepart{one}{\usebox{\myboxi}}
      % \nodepart{two}{\usebox{\myboxii}}
      % \nodepart{three}{\usebox{\myboxiii}}
      % \nodepart{four}{\usebox{\myboxiv}}
      % \nodepart{five}{\usebox{\myboxv}}%
    };%
}

\NewDocumentEnvironment{innerenv}{}{%
    \stepcounter{myboxes}%
    \edef\tmpname{\csname mybox\romannumeral\themyboxes\endcsname}%
    \begin{glrbox}{\tmpname}
        \begin{minipage}[t]{2in}
}{%
        \end{minipage}%
    \end{glrbox}%
}

\begin{document}

\begin{outerenv}

\begin{innerenv}
First
\end{innerenv}

\begin{innerenv}
Second
\end{innerenv}

\begin{innerenv}
Third
\end{innerenv}

\end{outerenv}

\end{document}

相关内容