定义宏避免重复代码

定义宏避免重复代码

我正在使用宏来制作我的数字

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

并使用相同的宏来center代替,figure*因为在某些情况下我不想要浮点数。

我想避免重复代码,因为在现实世界中我有几个这样的用于图形的宏。

那么,有没有办法使用figure*center原型宏?

答案1

你可以通过宏来制作宏。我将修改你的模板宏,让第三个参数成为可选参数,这样你就可以调用,

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

或者

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

因此让我们调用我们的宏定义宏\newfigure,它将接受两个参数:要定义的宏的名称和环境的名称(顺便说一下,我xparse在这里假设。如果您的 LaTeX 是最新的,它将在内核中,但如果不是,您需要添加\usepackage{xparse}以加载它)。

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

\newfigure,反过来会执行其自己的\NewDocumentCommand定义新图形的命令:

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

嗯,我们如何让 LaTeX 知道在这个定义中的定义中,我们想要的是定义中的参数,而不是传递给的参数\newfigure?在本例中,我们将 翻倍,#让 LaTeX 知道这些属于内部定义。¹ , ² 因此我们可以将您的\ifx...重写\fi为:

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

并且您的标题和标签为

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

然后完成定义:

      \end{#2}
    }

  1. 如果在宏定义中再嵌套一个宏定义,那么你又会加倍—— ####1。我不确定这种疯狂的嵌套深度——我从未探究过,但浏览的内容tex-live/**我发现深度有 5 层(32#秒!)。我个人最喜欢的搜索字符串是\def####1########1##1########2它定义了一个双参数命令,使用第三级宏的第一个参数作为名称,使用第二级宏的第一个参数作为两个参数之间的分隔符。

  2. 这也适用于#内部原语\halign或的模板\valign。如果您不熟悉这些命令,请忽略此脚注。

答案2

如果环境的名称和生成标题的方式是宏之间唯一需要改变的东西,则使用原型宏时只需将参数上移两个,并将环境名称作为原型宏的第一个参数,将所需的\caption/ \captionof/\@gobble命令作为原型宏的第二个参数。

然后定义其他宏来调用原型宏,并提供第一个参数(环境名称)和第二个参数(\caption/ \captionof/ \@gobble-命令),这样原型宏的后续三个参数将不会来自其他宏的定义,而是在执行其他宏时收集。

\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产量:
\PrototypeThing{figure*}{\caption}

因此

\figureone{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}产量:。
\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}

\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}反过来得到:

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

\centerone产量:
\PrototypeThing{center}{\captionof{figure}}

因此

\centerone{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}产量:。
\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}

\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}{⟨width⟩}反过来得到:

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


使用 xparse 你可以⟨宽度⟩-参数可选:

\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产量:
\PrototypeThing{figure*}{\caption}

因此

\figureone{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]产量:。
\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]

\PrototypeThing{figure*}{\caption}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]反过来得到:

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

\centerone产量:
\PrototypeThing{center}{\captionof{figure}}

因此

\centerone{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]产量:。
\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]

\PrototypeThing{center}{\captionof{figure}}{⟨fileNlabel⟩}{⟨caption⟩}[⟨width⟩]反过来得到:

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

答案3

我不确定使用这种不灵活的方法是否能获得很多好处。例如,的可选参数怎么样\caption?其他选项怎么样\includegraphics(例如,考虑修剪)?

我们可以按如下方式避免大部分代码重复,同时支持我提到的选项。但我不认为这真的有用。

\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*}}%
}

完整示例

\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}

在此处输入图片描述

答案4

在您对我的第一个回答的评论中,您添加了一个应该在最初的问题中已经提到的方面:打破九个参数的限制:

[...] 问题是,我的一些现实世界的宏需要 4-5 个原型参数和 8 个或更多最终宏参数,所以我总共需要 9 个以上的参数,[...]

我不喜欢宏接受很多参数:参数越多,错误地按错误顺序输入参数的机会就越多。这对用户来说很不友好。

因此,我仅将此视为一件“学术”的事情——请求了解如何做这样的事情,只是为了获得知识和挑战,尽管人们不会在日常使用中实现这样的事情。

只要所有“参数”都是强制性的无界参数我提出两块“基石”:

积木1:

拥有\romannumeral扩张驱动的“宏观机制”

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

得出的结果是:

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

,即将 L 个未分隔参数序列包装成一个参数,然后该参数包含/由 L 个未分隔参数的列表组成。

(对于由扩展驱动的宏机制,\romannumeral您需要恰好两个扩展步骤/两次“命中”\expandafter才能获得结果。)

积木2:

拥有\romannumeral扩张驱动的“宏观机制”

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

其工作原理如下:

如果⟨无界参数列表⟩:
是否提供⟨如果未限定参数列表没有第 K 个参数,则使用 tokens⟩

如果⟨无界参数列表⟩
传递第 K 个参数,但删除了一层括号。

(对于由扩展驱动的宏机制,\romannumeral您需要恰好两个扩展步骤/两次“命中”\expandafter才能获得结果。)

你可以使用这两块“积木”用于定义一个通用宏机制,该机制处理一定数量的 L 个参数,其中 L>9 是可能的,这些 L 个参数中的第一个参数是那些需要为非通用宏/用户级宏更改默认值的参数:

通用宏机制由一个通用顶层宏组成,该宏通过\expandafter-trickery 调用\CollectLArgs传递给通用内部宏,该内部宏只处理一个参数,L 个参数转换为包含 L 个未限定参数列表的单个未限定参数。

这样,通用内部宏的参数就是 L 个未限定参数的列表,您可以通过从中提取您喜欢/需要的任何参数\ExtractKthArg


在下面的例子中,\ExtractKthArg需要两个扩展步骤/两次“命中”才能\expandafter产生结果。

假设您希望第 11 个参数 /元素采用打字机字体。

你可以做

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

这种方式 \texttt将开始发挥作用,并在此进行评估\ExtractKthArg...,进而实现交付11

或者你也可以这样做:

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

这样,\expandafter-chain 就会触发执行\ExtractKthArg \texttt开始工作,您将获得:

\texttt{11}%

对于这两个代码片段,扩展/执行顺序的差异并不重要——最终结果是相同的。
但通常扩展发生和获得令牌的时间顺序很重要。


让我们创建一个示例,其中实现并用于定义处理\PrototypeThing17 个参数的函数,前两个参数是默认值,将在用户级宏的定义文本中提供,后面 15 个参数由用户在调用用户级宏时提供 - 这样,用户级宏就需要 15 个参数:

语法是:

\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⟩}%

基于\PrototypeThing您可以轻松定义用户宏的定义模式

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

with 语法

⟨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⟩}%

开始了:

\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}

在此处输入图片描述

相关内容