4

I have defined 2 Boxes:

\documentclass{article}
\usepackage[most]{tcolorbox}

\newtcolorbox{one}{}
\newtcolorbox{two}{}

\begin{document}

\begin{one}
The new command works fine
\end{one}

\begin{two}
The new command works fine
\end{two}

\end{document}

But with \foreach result error:

\foreach \i in {one,two}{
\newtcolorbox{\i}{}
}

Approach:

\foreach \i in {one,two}{
\expandafter\newtcolorbox{\csname\i\endcsname}{ }}

Any hint would be appreciated.

0

3 Answers 3

6

Every cycle in a \foreach loop is done inside a group, so the \newtcolorbox declaration is lost as soon as the group ends.

You may appreciate a general loop that doesn't need groups:

\documentclass{article}
\usepackage{tcolorbox}

\ExplSyntaxOn

\NewDocumentCommand{\lforeach}{mm}
 {% #1 = list, #2 = template
  \cs_set:Nn \__lforeach_temp:n { #2 }
  \clist_map_function:nN { #1 } \__lforeach_temp:n
 }

\ExplSyntaxOff

\lforeach{one,two}{\newtcolorbox{#1}{}}

\begin{document}

\begin{one}
The new command works fine
\end{one}

\begin{two}
The new command works fine
\end{two}

\end{document}

If you're running LaTeX with a release date prior to 2020-10-01, you also need \usepackage{xparse}.

The idea is the same as with \foreach, but you don't need to use a scratch macro such as \i to denote the current item (which is the main reason why \foreach uses grouping), using instead #1.

You can use this loop in various contexts.

4
  • Notice that the /.list key handler does not group the cycles either (as I wrote clearly in my post), and it understands things like something/.list={1,3,...,11}, which this construction does not.
    – user238301
    Apr 5, 2021 at 20:37
  • Also, the /.list hander works right out of the box, there is absolutely no need to add a command of the above type unless one is keen in duplicating the repertoire unnecessarily.
    – user238301
    Apr 5, 2021 at 20:39
  • @user238301 I don't understand the point of your comments. I just presented a different solution that can be used in several situations. Others may be good in different ones.
    – egreg
    Apr 5, 2021 at 20:39
  • Thank you egreg for your answer, it works fine with auto counter.
    – felipeuni
    Apr 6, 2021 at 17:14
5

\foreach creates groups and I am not sure what the \csname...\endcsname is for, but the following works.

\documentclass{article}

\usepackage[most]{tcolorbox}
\pgfkeys{new tcolorbox/.code=\newtcolorbox{#1}{},
new tcolorbox/.list={one,two}}

\begin{document}

\begin{one} The new command works fine \end{one}

\begin{two} The new command works fine \end{two}

\end{document}
2
  • Thank you user238301 for your solution, it works fine.
    – felipeuni
    Apr 5, 2021 at 18:32
  • @felipeuni Consider accepting the answer if it worked. Apr 5, 2021 at 21:17
1

An approach using only \expandafters. It helps to define \addto and \xaddto. Here, the \foreach just strings together the future commands into the global \tmp, which is executed after the group is exited.

\documentclass{article}
\usepackage[most]{tcolorbox}

\def\addto#1#2{\expandafter\gdef\expandafter#1\expandafter{\tmp#2}}
\def\xaddto#1#2{\expandafter\addto\expandafter#1\expandafter{#2}}
\def\tmp{}
\foreach \i in {one,two}{
  \addto\tmp{\newtcolorbox}
  \xaddto\tmp{\expandafter{\i}{}}
}\tmp
\begin{document}

\begin{one}
The new command works fine
\end{one}

\begin{two}
The new command works fine
\end{two}

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .