14

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.

4
  • You're not okay with \imglist, but you're fine with \im?
    – Werner
    Jan 17, 2018 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. Jan 18, 2018 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. Jan 18, 2018 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. Jan 18, 2018 at 11:15

1 Answer 1

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. ;-)

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .