# How to define a function with optional key-value arguments [duplicate]

I have setup a function called quickfigure which has the purpose of inserting a centered image with a one-line command:

\newcommand{\quickfigure}[2] {
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{#1}
\caption{#2}
\end{figure}
}


This function is used as follows;

\quickfigure{img/testImage.png}{Test image}


I would like this function to accept optional arguments to define width and height of the image, as well as a label. The syntax is desired to be something like;

\quickfigure[width=0.6, label=img:test]{img/testImage.png}{Test image}


How would I go about setting this up? I need a push in the right direction. Thanks!

Edit: Thanks everyone for the ideas, this is my solution;

\includepackage{keyval}
\includepackage{ifthen}

\newlength{\qf@width}
\define@key{quickfigure}{width}{\setlength\qf@width{#1}}
\define@key{quickfigure}{label}{\def\qf@label{#1}}

\newcommand{\quickfigure}[3][] {
\setkeys{quickfigure}{width=0.6\linewidth,label=\@empty}
\setkeys{quickfigure}{#1}
\begin{figure}[H]
\centering
\includegraphics[width=\qf@width]{#2}
\caption{#3}
\ifthenelse{\equal{\qf@label}{}}{}{\label{\qf@label}}
\end{figure}
}

-

## marked as duplicate by cfr, Peter Jansson, ChrisS, Jubobs, Martin SchröderMar 3 at 23:31

Related/duplicate: How to create a command with key values? –  Werner Mar 3 at 21:43
@Werner This is a case where the optional argument seems to be passed directly to \includegraphics –  egreg Mar 3 at 22:25
I'm not sure you gain anything by hiding the document's structure into a macro. –  egreg Mar 3 at 22:25
@egreg: Just partially, since label doesn't exist for \includegraphics. It would have to be managed differently. And true, it was a mild approach at pushing towards a solution. –  Werner Mar 3 at 22:53
@Wilco: You could combine your \setkeys as \setkeys{quickfigure}{width=.6\linewidth,label=\@empty,#1}. Note that you are required to use a \makeatletter...\makeatother pair with your current definition. –  Werner Mar 3 at 23:07

Or you could always do something like this:

\documentclass{article}

\usepackage{graphicx,xparse}

\NewDocumentCommand\quickfigure{O{width=0.6\linewidth} m o m}{%
\begin{figure}[H]
\centering
\includegraphics[#1]{#2}
\caption{#4}\IfNoValueTF{#3}{\relax}{\label{#3}}%
\end{figure}}

\begin{document}

\quickfigure{example-image-a}{Test image}

\quickfigure[width=20pt, height=100pt]{example-image-a}[img:test]{Test image}

\end{document}


-
You can also simply say \IfValueT{#3}{\label{#3}} or, equivalently, \IfNoValueF{#3}{\label{#3}} –  egreg Mar 3 at 22:27
@egreg Interesting. Thank you. Is that documented elsewhere? The xparse documentation I have only mentions \IfValueTF{}{}{} and \IfNoValueTF{}{}{}. –  cfr Mar 3 at 22:29
It is documented, albeit in a perhaps cryptic form; if you look closely, you'll see that TF in \IfNoValueTF (in the margin) are in italics and underlined in red. This is a shorthand for saying that either letter (and the corresponding argument) can be removed. The convention is described in the LaTeX3 interface documentation; it should probably be added also in the documentation of xparse. –  egreg Mar 3 at 22:37
@cfr Thank you for this suggestion! This is a very nice solution. Is it possible to have the optional label argument in the first parameter and extract it before passing it to \includegraphics? –  Wilco Mar 3 at 23:06
@Wilco Possible, yes. But I would use the link Werner provided in that case since there is no point in reinventing the wheel. That is, if you want to set it up to parse key-value pairs, you are best off using a tool designed for that. You could, of course, combine one of those solutions with the solution here. Just drop the second optional argument and run the first one through the tool of your choice. –  cfr Mar 3 at 23:32