2

I'm using a macro for my figures

\newcommand{\figureone}[3]{%
\begin{figure*}%
\centering
\ifx&#3&\includegraphics{#1}\else\includegraphics[width=#3\textwidth]{#1}\fi
\caption{#2}
\label{fig:#1}
\end{figure*}
}

and the same macro with center in place of figure* because in some cases I don't want floats.

I'd like to avoid duplicating code, because in my real world I have several of such macros for figures.

So, is there a way to define two macros using figure* or center starting from a prototype macro?

mmj
  • 1,702

4 Answers4

5

You can make macros to make macros. I'm going to modify your template macro to have the third argument be an optional argument, so you'd call,

\figureone{file.png}{This is the caption}[0.3]

or

\figureone{file.png}{This is the caption}

So let's call our macro-defining macro \newfigure and it will take two arguments: the name of the macro to define and the name of the environment (as an aside, I’m assuming xparse here. If your LaTeX is current, it will be in the kernel, but if not you'll need to add \usepackage{xparse} to load it).

\NewDocumentCommand{\newfigure}{ m m }{%

\newfigure, in turn will do its own \NewDocumentCommand to define your new figure command:

   \NewDocumentCommand{#1}{ m m o }{%
      \begin{#2}%
        \centering

Hmm, how do we let LaTeX know in this definition within a definition that we want the arguments to what we're defining and not the arguments that we've passed to \newfigure? In this instance, we double the # to let LaTeX know that these belong to the inner definition.¹,² so we can rewrite your \ifx\fi as:

        \IfNoValueTF {##3}
          {\includegraphics{##1}}
          {\includegraphics[width=##3\textwidth]{#1}}

and your caption and label as

        \caption{##2}
        \label{fig:##1}

And then finish off the definition:

      \end{#2}
    }

  1. If you had a macro definition inside a macro definition inside a macro definition, you would double again—####1. I'm not sure how deeply the madness can be nested—I've never probed, but looking through the contents of tex-live/** I see as deep as 5 levels (32 #s!). My personal favorite string from this search was \def####1########1##1########2 Which defines a two-argument command using a third-level macro's first argument for the name and a second-level macro's first argument as the delimiter between the two arguments.

  2. This also would apply to the # for templates of an inner primitive \halign or \valign. If you aren't familiar with those commands, just ignore this footnote.

Don Hosek
  • 14,078
2

In case the name of the environment and the way captions are to be generated are the only things to change from macro to macro, with a prototype-macro just shift arguments up by two and as the prototype-macro's first argument use the name of the environment and as the prototype-macro's second argument use the desired \caption/\captionof/\@gobble-command.

Then define the other macros to call the prototype-macro with the first argument (environment-name) and the second argument (\caption/\captionof/\@gobble-command) provided so that the prototype-macro's subsequent three arguments will not come from the other macros' definitions but will be gathered at the time of carrying out the other macros.

\documentclass{article}
\usepackage{graphicx}
\usepackage{capt-of}

\newcommand{\PrototypeThing}[5]{% \begin{#1}% \centering \ifx&#5&\includegraphics{#3}\else\includegraphics[{width=#5\textwidth}]{#3}\fi #2{#4}% \label{fig:#3}% \end{#1}% }%

\newcommand{\figureone}{\PrototypeThing{figure}{\caption}} \newcommand*{\centerone}{\PrototypeThing{center}{\captionof{figure}}}

\begin{document}

\listoffigures

\figureone{example-image-a.jpg}{caption}{1}

\centerone{example-image-b.jpg}{caption}{.3}

\end{document}

\figureone yields:
\PrototypeThing{figure*}{\caption}.

Thus

\figureone{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩} yields:
\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}.

\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩} in turn yields:

\begin{figure*}%
\centering
\ifx&⟨width⟩&\includegraphics{⟨fileNlabel⟩}\else\includegraphics[{width=⟨width⟩\textwidth}]{⟨fileNlabel⟩}\fi
\caption{⟨caption⟩}%
\label{fig:⟨fileNlabel⟩}%
\end{figure*}%

\centerone yields:
\PrototypeThing{center}{\captionof{figure}}.

Thus

\centerone{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩} yields:
\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}.

\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩} in turn yields:

\begin{center}%
\centering
\ifx&⟨width⟩&\includegraphics{⟨fileNlabel⟩}\else\includegraphics[{width=#5\textwidth}]{⟨fileNlabel⟩}\fi
\captionof{figure}{⟨caption⟩}%
\label{fig:⟨fileNlabel⟩}%
\end{center}%


Using xparse you can make the ⟨width⟩-argument optional:

\documentclass{article}
\usepackage{graphicx}
\usepackage{capt-of}

\NewDocumentCommand{\PrototypeThing}{mmmmo}{% \begin{#1}% \centering \IfNoValueTF{#5}{\includegraphics}{\includegraphics[{width=#5\textwidth}]}{#3}% #2{#4}% \label{fig:#3}% \end{#1}% }%

\newcommand{\figureone}{\PrototypeThing{figure}{\caption}} \newcommand*{\centerone}{\PrototypeThing{center}{\captionof{figure}}}

\begin{document}

\listoffigures

\noindent\figureone{example-image-a.jpg}{figureonecaption}[1]

\noindent\centerone{example-image-b.jpg}{centeronecaption}[.3]

\end{document}

\figureone yields:
\PrototypeThing{figure*}{\caption}.

Thus

\figureone{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩] yields:
\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩].

\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩] in turn yields:

\begin{figure*}%
\centering
\IfNoValueTF{⟨width⟩}{\includegraphics}{\includegraphics[{width=⟨width⟩\textwidth}]}{⟨fileNlabel⟩}%
\caption{⟨caption⟩}%
\label{fig:⟨fileNlabel⟩}%
\end{figure*}%

\centerone yields:
\PrototypeThing{center}{\captionof{figure}}.

Thus

\centerone{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩] yields:
\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩].

\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩] in turn yields:

\begin{center}%
\centering
\IfNoValueTF{⟨width⟩}{\includegraphics}{\includegraphics[{width=⟨width⟩\textwidth}]}{⟨fileNlabel⟩}%
\captionof{figure}{⟨caption⟩}%
\label{fig:⟨fileNlabel⟩}%
\end{center}%
Ulrich Diez
  • 28,770
1

I'm not sure you gain very much using this inflexible approach. For instance, what about the optional argument to \caption? What about other options to \includegraphics (think to trimming, for instance)?

We can avoid most code duplication as follows, also supporting the options I mentioned. But I don't believe this is really useful.

\NewDocumentCommand{\figureone}{sO{}mO{#5}mo}{%
  % start: if *-version, center
  \IfBooleanTF{#1}{\begin{center}}{\begin{figure*}\centering}%
  \IfValueTF{#6}{%
    % a fraction is specified
    \includegraphics[width=#6\textwidth,#2]{#3}%
  }{%
    \includegraphics[#2]{#3}%
  }%
  \IfBooleanTF{#1}{\captionof{figure}}{\caption}[#4]{#5}%
  \label{#3}%
  \IfBooleanTF{#1}{\end{center}}{\end{figure*}}%
}

Complete example

\documentclass[twocolumn]{article}
\usepackage{graphicx,capt-of}

\usepackage{lipsum}

\NewDocumentCommand{\figureone}{sO{}mO{#5}mo}{% % start: if -version, center \IfBooleanTF{#1}{\begin{center}}{\begin{figure}\centering}% \IfValueTF{#6}{% % a fraction is specified \includegraphics[width=#6\textwidth,#2]{#3}% }{% \includegraphics[#2]{#3}% }% \IfBooleanTF{#1}{\captionof{figure}}{\caption}[#4]{#5}% \label{#3}% \IfBooleanTF{#1}{\end{center}}{\end{figure*}}% }

\begin{document}

\listoffigures

\lipsum[1][1-2]

\figureone*{example-image}{Figure in the column}[0.4]

\lipsum[1][1-2]

\figureone*{example-image-a}[Short caption]{Long caption}[0.4]

\lipsum[1][1-2]

\figureone*[trim=20 20 20 20,clip]{example-image-b}{Trimmed}[0.4]

\lipsum[1][1-2]

\figureone{example-image-c}{Figure in the column}

\lipsum[1][1-2]

\figureone{example-image-16x9}[Short caption]{Long caption}[0.8]

\lipsum[1][1-2]

\figureone[trim=20 20 20 20,clip]{example-image-1x1}{Trimmed}[0.8]

\lipsum[1][1-2]

\end{document}

enter image description here

egreg
  • 1,121,712
  • Why you say this is not really useful? What would be your general approach? Consider I've many macros building figures either with 2, 3 or 4 images, side by side, one over the other or mixed, with single or multiple captions, with or without subcaptions, automatically resizing multiple images by height or by area. – mmj Jun 10 '21 at 09:55
  • 1
    @mmj My approach would be to use the proper environments. – egreg Jun 10 '21 at 09:57
1

In your comment to my first answer you added an aspect which should have been mentioned in the initial question already: Breaking the nine-argument-limit:

[...] the problem is that some of my real world macros need 4-5 parameters for the prototype and 8 or more parameters for the final macro, so I need more than 9 parameters overall, [...]

I am not fond of macros taking many arguments: The more arguments, the more opportunities to erroneously put arguments in wrong order. This is not user-friendly.

Therefore I take this for an "academical" thing only—a request to see how such a thing can be done, just for the knowledge and the challenge, although one would not implement such a thing for daily usage.

As long as all "parameters" are mandatory undelimited arguments I propose two "building bricks":

Building brick 1:

Have a \romannumeral-expansion-driven "macro-mechanism"

\CollectLArgs{⟨TeX-⟨number⟩-quantity of value L⟩}{⟨Argument 1⟩}{⟨Argument 2⟩}...{⟨Argument L⟩}

which yields:

{{⟨Argument 1⟩}{⟨Argument 2⟩}...{⟨Argument L⟩}}

, i.e., which wraps a sequence of L undelimited arguments into a single argument which then contains/consists of a list of L undelimited arguments.

(With macro-mechanisms that are driven by \romannumeral-expansion you need exactly two expansion-steps/two "hits" by \expandafter for obtaining the result.)

Building brick 2:

Have a \romannumeral-expansion-driven "macro-mechanism"

\ExtractKthArg{⟨TeX-⟨number⟩-quantity of value K⟩}%
              {⟨tokens in case list of undelimited arguments doesn't have a Kth argument⟩}%
              {⟨list of undelimited arguments⟩}%

which works as follows:

In case there is no Kth argument in the ⟨list of undelimited arguments⟩:
Does deliver ⟨tokens in case list of undelimited arguments doesn't have a Kth argument⟩.

In case there is a Kth argument in the ⟨list of undelimited arguments⟩:
Does deliver that Kth argument with one level of braces removed.

(With macro-mechanisms that are driven by \romannumeral-expansion you need exactly two expansion-steps/two "hits" by \expandafter for obtaining the result.)

You can use the two "building bricks" for defining a generic macro-mechanism which processes an amount of L arguments, whereby L>9 is possible, the first ones of these L arguments being those whose defaults are to be changed for the non-generic macros/user-level-macros:

The generic macro-mechanism consists of a generic toplevel-macro which via \expandafter-trickery calls \CollectLArgs to deliver to a generic internal-macro, which processes exactly one argument, the L arguments turned into a single undelimited argument containing a list of L undelimited arguments.

This way the generic internal-macro's argument is a list of L undelimited arguments from which you can have extracted whichever you like/need by means of \ExtractKthArg.


In the example below \ExtractKthArg requires two expansion-steps/two "hits" by \expandafter to deliver the result.

Assume you want the 11th argument/element to be in typewriter-font.

You can do

\texttt{%
  \ExtractKthArg{11}%
                {}%
                {{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}}%
}%

This way \texttt will start working and hereby also evaluate \ExtractKthArg..., which in turn delivers 11.

Alternatively you can do:

\expandafter\expandafter\expandafter\texttt
\expandafter\expandafter\expandafter{%
  \ExtractKthArg{11}%
                {}%
                {{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}}%
}%

This way the \expandafter-chain triggers carrying out \ExtractKthArg before \texttt comes to start working and you get:

\texttt{11}%

With these two snippets the differences in the order in time of expansion/carrying things out doesn't matter—the result in the end is the same.
But often the order in time in which expansion takes place and tokens are obtained does matter.


Let's create an example where the two mentioned "building-bricks" are implemented and used for defining both a \PrototypeThing which processes 17 arguments, the first two arguments being defaults that are to be provided within the definition-text of the user-level-macros, the following 15 to be provided by the user when calling the user-level-macros—so that the user-level-macros take 15 arguments:

Syntax is:

\PrototypeThing{⟨environment-name⟩}%
               {⟨caption-command⟩}%
               {⟨fileNlabel⟩}%
               {⟨caption-text⟩}%
               {⟨width⟩}%
               {⟨Dummy-Argument 1⟩}%
               {⟨Dummy-Argument 2⟩}%
               {⟨Dummy-Argument 3⟩}%
               {⟨Dummy-Argument 4⟩}%
               {⟨Dummy-Argument 5⟩}%
               {⟨Dummy-Argument 6⟩}%
               {⟨Dummy-Argument 7⟩}%
               {⟨Dummy-Argument 8⟩}%
               {⟨Dummy-Argument 9⟩}%
               {⟨Dummy-Argument 10⟩}%
               {⟨Dummy-Argument 11⟩}%
               {⟨Dummy-Argument 12⟩}%

Based on \PrototypeThing you can easily define user-macros of definition-pattern

\newcommand⟨Cs-token⟩{%
  \PrototypeThing{⟨environment-name⟩}%
                 {⟨caption-command⟩}%
}%

with syntax

⟨Cs-token⟩{⟨fileNlabel⟩}%
          {⟨caption-text⟩}%
          {⟨width⟩}%
          {⟨Dummy-Argument 1⟩}%
          {⟨Dummy-Argument 2⟩}%
          {⟨Dummy-Argument 3⟩}%
          {⟨Dummy-Argument 4⟩}%
          {⟨Dummy-Argument 5⟩}%
          {⟨Dummy-Argument 6⟩}%
          {⟨Dummy-Argument 7⟩}%
          {⟨Dummy-Argument 8⟩}%
          {⟨Dummy-Argument 9⟩}%
          {⟨Dummy-Argument 10⟩}%
          {⟨Dummy-Argument 11⟩}%
          {⟨Dummy-Argument 12⟩}%

Here we go:

\makeatletter
%%=============================================================================
%% PARAPHERNALIA:
%%\UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%%\UD@stopromannumeral, \UD@CheckWhetherNull
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% BUILDING-BRICK 1: \CollectLArgs
%%=============================================================================
%%  \CollectLArgs{<TeX-<number>-quantity of value L>}%
%%               {<Argument 1>}{<Argument 2>}...{<Argument L>}%
%%
%% yields:
%%
%% {{<Argument 1>}{<Argument 2>}...{<Argument L>}}
%%
%% Due to \romannumeral-expansion the result is delivered after two 
%% expansion-steps / by "hitting" \CollectLArgs with \expandafter twice.
%%
%%.............................................................................
\newcommand\CollectLArgs[1]{%
  \romannumeral
  \expandafter\UD@CollectLArgs\expandafter{\romannumeral\number\number#1 000}{}%
}%
\newcommand\UD@CollectLArgs[2]{%
  \UD@CheckWhetherNull{#1}{\UD@stopromannumeral{#2}}{\UD@@CollectLArgs{#1}{#2}}%
}%
\newcommand\UD@@CollectLArgs[3]{%
  \expandafter\UD@CollectLArgs\expandafter{\UD@firstoftwo{}#1}{#2{#3}}%
}%
%%=============================================================================
%% BUILDING-BRICK 2: \ExtractKthArg
%%=============================================================================
%% \ExtractKthArg{<TeX-<number>-quantity of value K>}%
%%               {<tokens in case list of undelimited args doesn't have a k-th argumnent>}%
%%               {<list of undelimited args>} %
%% 
%% In case there is no K-th argument in <list of undelimited args> : 
%%   Does deliver <tokens in case list of undelimited args doesn't have a k-th argumnent.
%% In case there is a K-th argument in <list of undelimited args> : 
%%   Does deliver that K-th argument with one level of braces removed.
%%
%% Due to \romannumeral-expansion the result is delivered after two 
%% expansion-steps / by "hitting" \ExtractKthArg with \expandafter twice.
%%
%% Examples:
%%
%%   \ExtractKthArg{0}{not available}{ABCDE} yields: not available
%%
%%   \ExtractKthArg{3}{not available}{ABCDE} yields:  C
%%
%%   \ExtractKthArg{3}{not available}{AB{CD}E} yields:  CD
%%
%%   \ExtractKthArg{4}{not available}{{001}{002}{003}{004}{005}} yields: 004
%%
%%   \ExtractKthArg{6}{not available}{{001}{002}{003}} yields: not available 
%%=============================================================================
\newcommand\ExtractKthArg[2]{%
  \romannumeral
  % #1: <integer number K>
  % #2: <action if there is no K-th argument>
  \expandafter\UD@ExtractKthArgCheck
  \expandafter{\romannumeral\number\number#1 000}{#2}%
}%
\newcommand\UD@ExtractKthArgCheck[3]{%
  \UD@CheckWhetherNull{#1}{\UD@stopromannumeral#2}{% empty
    \expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
  }%
}%
\begingroup
\def\UD@ExtractFirstArgLoop#1{%
  \endgroup
  \@ifdefinable\UD@RemoveTillFrozenrelax{%
    \long\def\UD@RemoveTillFrozenrelax##1##2#1{{##1}}%
  }%
  \newcommand\UD@ExtractKthArgLoop[3]{%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo##3{}.}{\UD@stopromannumeral##2}{%
      \UD@CheckWhetherNull{##1}{%
        \UD@ExtractFirstArgLoop{##3#1}%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}##3}%
        {\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}##1}{##2}}%
      }%
    }%
  }%
}%
\expandafter\expandafter\expandafter\UD@ExtractFirstArgLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}%
%% Usage of frozen-\relax as delimiter is for speeding things up by reducing the
%% amount of iterations needed. I chose frozen-\relax because David Carlisle 
%% pointed out in   <https://tex.stackexchange.com/a/578877>
%% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be
%% affected by \uppercase/\lowercase.
%%
%% \UD@ExtractFirstArg's argument may contain frozen-\relax:
%% The only effect is that internally more iterations are needed for
%% obtaining the result.
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\expandafter\UD@stopromannumeral\UD@firstoftwo#1{}}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
%%=============================================================================
\makeatother

\documentclass{article}

\usepackage{graphicx} \usepackage{capt-of}

\makeatletter \newcommand{\PrototypeThing}{% \expandafter\expandafter\expandafter\InternalPrototypeThing\CollectLArgs{17}% }% \newcommand{\InternalPrototypeThing}[1]{% \begin{\ExtractKthArg{1}{}{#1}}% \par\noindent\hrulefill \par\noindent User macro's 1st argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{3}{}{#1}}% \par\noindent User macro's 2nd argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{4}{}{#1}}% \par\noindent User macro's 3rd argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{5}{}{#1}}% \par\noindent User macro's 4th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{6}{}{#1}}% \par\noindent User macro's 5th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{7}{}{#1}}% \par\noindent User macro's 6th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{8}{}{#1}}% \par\noindent User macro's 7th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{9}{}{#1}}% \par\noindent User macro's 8th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{10}{}{#1}}% \par\noindent User macro's 9th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{11}{}{#1}}% \par\noindent User macro's 10th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{12}{}{#1}}% \par\noindent User macro's 11th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{13}{}{#1}}% \par\noindent User macro's 12th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{14}{}{#1}}% \par\noindent User macro's 13th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{15}{}{#1}}% \par\noindent User macro's 14th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{16}{}{#1}}% \par\noindent User macro's 15th argument: \detokenize\expandafter\expandafter\expandafter{\ExtractKthArg{17}{}{#1}}% \par\noindent\hrulefill \bigskip \par \centering \expandafter\expandafter\expandafter\UD@CheckWhetherNull \expandafter\expandafter\expandafter{\ExtractKthArg{5}{}{#1}}{% \includegraphics }{% \includegraphics[{width=\ExtractKthArg{5}{}{#1}\textwidth}]% }{\ExtractKthArg{3}{}{#1}}% \ExtractKthArg{2}{}{#1}{\ExtractKthArg{4}{}{#1}}% \label{fig:\ExtractKthArg{3}{}{#1}}% \par\noindent\hrulefill \end{\ExtractKthArg{1}{}{#1}}% }% \makeatother

\newcommand{\figureone}{\PrototypeThing{figure}{\caption}} \newcommand*{\centerone}{\PrototypeThing{center}{\captionof{figure}}}

\begin{document}

\listoffigures

\newpage

\null

\figureone{example-image-a.jpg}{caption}{.3}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}{L}

\newpage

\centerone{example-image-b.jpg}{caption}{1}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}{L}

\end{document}

enter image description here

Ulrich Diez
  • 28,770