7

I am trying to iterate over the list of all basic colours:

\def\thecolors{black, blue, brown, cyan, darkgray, gray, green, lightgray, lime, magenta, olive, orange, pink, purple, red, teal, violet, white, yellow}

I want to define a command for each of them with some kind of for each loop, more or less as follows:

\foreach \x in \thecolors%
  {\newcommand{\csname command\x\endcsname}
    {\textcolor{\x}{Some text including the string \x.}}

I know this is more or less the way to do it with pgf/tikz, but I was wondering whether there is a way to do it only with (La)TeX primitive commands.

Thanks in advance for any answer.

PS: Do I need to explicitly define \thecolors or are LaTeX basic colours already stored in some command?

EDIT

I don't think this is a duplicate of (1) since it explicitly asks for a (La)TeX primitive method.

lfba
  • 731
  • 4
  • 13
  • 2
    You could try to use something like the \loop command but as far as I am aware there is no TeX primitive for dealing with comma separated lists, so you would have to implement this first. Easier alternatives would be to use pgf, as you suggest, or \docsvlist from etoolbox package, or \clist_use:Nn from LaTeX3, or ... –  Sep 30 '19 at 08:07
  • 1
    Btw, there is no list (or even definition) of the "basic" colours but, for example, if you look at the manual for the xcolor you'll find related lists and ways of listing colour tables. –  Sep 30 '19 at 08:12
  • 2
    There is no primitive in TeX for this, but in the LaTeX2e kernel there is the \@for macro. – Skillmon Sep 30 '19 at 08:12

2 Answers2

7

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}}
egreg
  • 1,121,712
4

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.

enter image description 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}
David Carlisle
  • 757,742