Is there a `for each` loop in primitive (La)TeX?
A more “primitive” way in LaTeX, that also avoids the issues with grouping one gets with \foreach
, would be
\makeatletter
\def\basiccolors{%
black,blue,brown,cyan,darkgray,gray,green,lightgray,lime,%
magenta,olive,orange,pink,purple,red,teal,violet,white,yellow%
}
\def\do@def#1{%
\expandafter\newcommand\csname command#1\endcsname{%
\textcolor{#1}{Some text including the string #1}%
}%
}
\@for\next:=\basiccolors\do{\expandafter\do@def\expandafter{\next}}
\makeatother
Note that no spaces are allowed in the list of items.
It's much easier with expl3
:
\usepackage{expl3}
\ExplSyntaxOn
\NewDocumentCommand{\makecommandsfromlist}{mm}
{
\clist_map_inline:nn { #1 }
{
\cs_new:cpn { command ##1 } { #2 }
}
}
\ExplSyntaxOff
\makecommandsfromlist{
black, blue, brown, cyan, darkgray, gray, green,
lightgray, lime, magenta, olive, orange, pink,
purple, red, teal, violet, white, yellow
}
{\textcolor{#1}{Some text including #1}}
You could use \@for
or an expl3
list but often a more convenient (and a lot more efficient in terms of expansions) technique is to use a different structure which allows you to execute the list with no separate loop macro, this is explained in appendix D of the texbook and used in several places in latex (look for \@elt
usage) I'll use \\
here.
\documentclass{article}
\def\thecolors{\\{black}\\{blue}\\{brown}\\{cyan}\\{darkgray}\\{gray}\\{green}\\{lightgray}\\{lime}\\{magenta}\\{olive}\\{orange}\\{pink}\\{purple}\\{red}\\{teal}\\{violet}\\{white}\\{yellow}}
\usepackage{xcolor}
\begin{document}
{%
\def\\#1{\expandafter\gdef\csname command#1\endcsname{%
\textcolor{#1}{Some text including the string #1.}}}%
\thecolors
}
\commandblue
\end{document}