13

Suppose I have a macro that automagically adds a bunch of figures to a document:

\automagic{<figure-list>}{<caption-template>}

This macro would cycle through the comma-separated list <figure-list>, add them, and then put a caption based on the <caption-template>.

Consider now this example:

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}

\makeatletter
\newcommand{\automagic}[2]{%
\def\imglist{#1}% Trick to make it work
\begin{figure}
  \@for\im:=#1\do{%
    \begin{subfigure}[t]{0.33\textwidth}
      \includegraphics[width=\textwidth]{example-image-\im}
      \caption{#2}
    \end{subfigure}%
  }%
\end{figure}
}
\makeatother

\begin{document}

\automagic{a,b,c}{Figure \im\ from the set: ``\imglist''}

% \automagic{a,b,c}{Figure \im\ from the set: ``#1''}

\end{document}

For me to create a caption of the format above, I have to define a macro \imglist inside the \automagic macro that will hold the argument #1 for me to use on the call to the macro.

Is it possible to, instead of the \def\imglist{#1} trick, use the actual argument number #1 in the call to the macro? Something like the commented line.

I search around and didn't find anything similar, so I wouldn't be surprised if that is not possible.

  • You're not okay with \imglist, but you're fine with \im? – Werner Jan 17 '18 at 23:51
  • @Werner Go figure, people these days are hard to understand...:). I already solved my problem with the \imglist thing. But the possibility to use a #1 made me curious. – Phelype Oleinik Jan 18 '18 at 0:02
  • You should note that \im is defined local to the figure environment, and will be undefined (or revert to it's previous definition) afterword. It may even be local to the \do{...} macro. – John Kormylo Jan 18 '18 at 5:10
  • @JohnKormylo Well pointed, thanks! Since I'll keep the usage of \im to the figure caption, that shouldn't be a problem. Otherwise a global redefinition of \im would do the job. – Phelype Oleinik Jan 18 '18 at 11:15
14

You certainly can: the trick is to define a temporary macro.

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}

\makeatletter
\newcommand{\automagic}[2]{%
\def\temp##1{\caption{#2}}%
\begin{figure}
  \@for\im:=#1\do{%
    \begin{subfigure}[t]{0.33\textwidth}
      \includegraphics[width=\textwidth]{example-image-\im}
      \temp{#1}%
    \end{subfigure}%
  }%
\end{figure}
}
\makeatother

\begin{document}

\automagic{a,b,c}{Figure \im\ from the set: ``#1''}

\end{document}

The trick works because the #1 in the second argument becomes ##1 when the argument is absorbed. So adding \show\temp after its definition will yield

> \temp=macro:
#1->\caption {Figure \im \ from the set: ``#1''}.

as expected.

As an exercise, you may want to look at

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\automagic}{mm}
 {
  \begin{figure}
  \clist_map_inline:nn { #1 }
   {
    \cs_set:Nn \__oleinik_automagic_temp:n { \caption { #2 } }
    \begin{subfigure}[t]{0.33\textwidth}
    \includegraphics[width=\textwidth]{example-image-##1}
    \__oleinik_automagic_temp:n { #1 }
    \end{subfigure}
   }
  \end{figure}
 }
\ExplSyntaxOff

\begin{document}

\automagic{a,b,c}{Figure #1 from the set: ``##1''}

\end{document}

which is a bit trickier. ;-)

  • The first one I could understand, but the second one will take a little while to sink in :) Thanks! – Phelype Oleinik Jan 18 '18 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.