I'm trying to produce a document to compare a bunch of fontfaces. I'd like to parse an array to load and try them all.

This is what I have done:

\documentclass{article}

\usepackage{lipsum}
\usepackage{pgffor}
\usepackage{fontspec}

\def\UseFont#1{\csname#1\endcsname}

\def\FontList{Charter,Lato,Linux Libertine O}

% these work just fine

% THIS DOES NOT WORK

\begin{document}
\foreach \FontName in \FontList {\UseFont\FontName\lipsum[1]}
\end{document}


While the cycle with \UseFont works fine, the one with \LoadFont does not. On its own, \LoadFont does what's expected.

I think this could be an expansion problem, but I'm not sure where it stands exactly; blind attempts led nowhere.

As already explained, the behaviour you observed comes from the established feature of \foreach to do its iterations inside scope-limiting groups.

Here is with \xintFor. I switched to another font, as I don't have Lato installed.

\documentclass{article}

\usepackage{lipsum}
\usepackage{xinttools}
\usepackage{fontspec}

\def\UseFont#1{\csname#1\endcsname}

% original
% \def\FontList{Charter,Lato,Linux Libertine O}
% as I don't have Lato:

\def\FontList {Charter, TeX Gyre Heros, Linux Libertine O}

\xintFor #1 in \FontList \do {\LoadFont {#1}}

\begin{document}

\xintFor #1 in \FontList \do {\UseFont {#1}\lipsum[1]}

\end{document}

% Local Variables:
% TeX-engine: xetex
% End:


• syntax xintFor #1 in {Charter, TeX Gyre Heros, Linux Libertine O} \do {\LoadFont {#1}} is also possible, but do not forget the braces around the comma separated values.The spaces around commas are silently removed.
– user4686
Feb 18, 2016 at 7:10

When you do

\foreach \FontName in \FontList {\LoadFont\FontName}


the \newfontface instruction is performed inside a group, so the definition of the font face is lost as soon as the group ends. This is a feature of \foreach.

Here's a set of macros in expl3 that can give you some ideas for extending them.

\documentclass{article}

\usepackage{fontspec}
\usepackage{lipsum}

\ExplSyntaxOn
{
\exp_args:Nc \newfontface { #1 } { #1 }
}
{
\clist_map_inline:nn { #1 }
{
}
}
\NewDocumentCommand{\UseFont}{m}
{
\use:c { #1 }
}
\NewDocumentCommand{\UseFonts}{m +m}
{
\clist_map_inline:nn { #1 }
{
\group_begin:
\UseFont{##1} ##1:~#2
\group_end:
}
}
\ExplSyntaxOff

\begin{document}

\UseFonts{Charter,Lato,Linux Libertine O}{\lipsum[2]}

\end{document}


Note that \exp_args:Nc \newfontface { #1 } { #1 } is essentially the same as

\expandafter\newfontface\csname #1\endcsname{#1}


If you want to use a symbolic name for a list, define a *-variant:

\documentclass{article}

\usepackage{fontspec}
\usepackage{lipsum}

\ExplSyntaxOn
{
\exp_args:Nc \newfontface { #1 } { #1 }
}
{
\IfBooleanTF{#1}
{ \clist_map_inline:Nn #2 }
{ \clist_map_inline:nn { #2 } }
{
}
}
\NewDocumentCommand{\UseFont}{m}
{
\use:c { #1 }
}
\NewDocumentCommand{\UseFonts}{s m +m}
{
\IfBooleanTF{#1}
{ \clist_map_inline:Nn #2 }
{ \clist_map_inline:nn { #2 } }
{
\group_begin:
\UseFont{##1} ##1:~#3
\group_end:
}
}
\ExplSyntaxOff

\newcommand\FontList{Charter,Lato,Linux Libertine O}

• Impeccable. I added a couple of commands to handle my specific situation. Also, thanks for giving me an excuse to study a bit of expl3. Feb 18, 2016 at 0:20
• @PaoloBrasolin Sorry, but there's a much better method. ;-) Feb 18, 2016 at 0:32