我正在尝试使用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
或\pgfplotsinvokeforeach
pgfplots
。
作为一个穷人的替代品,你有一个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}