[Tex/LaTex] Using \ifstrequal in a fontspec macro

etoolboxfontspecmacros

Here is my Minimal Failing Example:

\documentclass{article}
\usepackage{fontspec,etoolbox}
\setmainfont{TeX Gyre Schola}

\begin{document}

\newcommand\Stretch[1]{
  \ifstrequal{#1}{narrow}{0.6}{}
  \ifstrequal{#1}{wide}{1.5}{}
}

Normal. {\addfontfeature{FakeStretch=\Stretch{narrow}} Narrow.} Normal.
Normal. {\addfontfeature{FakeStretch=\Stretch{wide}} Wide.} Normal.

\end{document}

(Xe)LaTeX fails with the message Missing \endcsname inserted because of the \ifstrequal macro. Can you explain me why? And how can I modify the \Stretch macro so that it works?

Best Answer

You need an expandable version of \Stretch. \ifstrequal contains definitions, thus \ifstrequal is not expandable.

Example for an expandable definition:

\documentclass{article}
\usepackage{fontspec,etoolbox}
\setmainfont{TeX Gyre Schola}

\begin{document}

\makeatletter
\newcommand*{\Stretch@narrow}{0.6}
\newcommand*{\Stretch@wide}{1.5}
\newcommand*{\Stretch}[1]{%
  \@ifundefined{Stretch@#1}{%
    \Stretch@UnknownArgument % throws error as undefined command
    1% error recovery
  }{%
    \@nameuse{Stretch@#1}%
  }
}
\makeatother

Normal. {\addfontfeature{FakeStretch=\Stretch{narrow}} Narrow.} Normal.

Normal. {\addfontfeature{FakeStretch=\Stretch{wide}} Wide.} Normal.

\end{document}

Result

The argument of \Stretch is taken to compose a macro \Stretch@<argument>, which expands to the number according to <argument>.

If the argument is not known, \Stretch@<argument> is undefined and behaves as \relax (side effect of \csname that is called by \@nameuse). This would trigger the error like before. As a normal error message will not work in this context, the above version of \Stretch uses an unknown command \Stretch@UnknownArgument to transport the cause of the error to the user. As error recovery the value 1 is returned.

Related Question