2

Another question gave me hope that there is an elegant way (without using additional packages) to refer to a comma separated argument in \newcommand, maybe something like (just a guess, not tested):

\newcommand*\myfigure[3]{
  \begin{figure}
    \includegraphics[width=#3]{#1}
    \caption[\getfirst#2]{\getsecond#2}
  \end{figure}
  \relax
}
\def\getfirst#1,#2\relax{{#1}}
\def\getsecond#1,#2\relax{{#2}}

that should allow to use a command such as:

\myfigure{imagefile}{short caption,long caption}{0.8\textwidth}

Unfortunately commas are often present in captions, so I would like to know if there is a way to obtain the desired result using another delimiter than comma.

Altough there are many similar question around, I did not find an elegant solution to my need.

UPDATE

Being a newbie, I discovered just now that I can use a custom delimiter in \def (any character rarely found in captions, such as §), so to avoid altogheter the comma issue. The guessed code does not work yet though, it seems that the second \def breaks it, with the error Argument of \getsfirst has an extra }. Does anybody know how to fix the code?

FINAL UPDATE

No wonder egreg knew how to fix the code (thanks!) which I report here (§ chosen as delimiter), should it be useful to somebody (even if egreg's own answer, using another approach, should fit better most of similar needs):

\def\getfirst#1§#2\relax{#1}
\def\getsecond#1§#2\relax{#2}

\newcommand\myfigure[3]{
  \begin{figure}
    \includegraphics[width=#3]{#1}
    \caption[\getfirst#2\relax]{\getsecond#2\relax}
    \label{fig:#1}
  \end{figure}
  \relax
}
  • What's the advantage of \myfigure over a figure environment? – egreg Sep 25 '15 at 9:20
  • @egreg The advantage is conciseness, a single line instead of a multiline command. I use the same approach to build figures with multiple images horizontally or vertically aligned, with single or multiple captions, using just a single line. – mmj Sep 25 '15 at 9:39
  • It is possible but I would suggest a different syntax. The standard latex syntax for positional arguments is {} so it should be {short caption}{long caption} or use named (key-val) argument as in \includegraphics so {shortc=short caption,longc=long caption} That way the short caption can be made optional. Also if you do define a command, don't forget % at the ends of lines!! – David Carlisle Sep 25 '15 at 9:46
2

You're missing the delimiter of the second argument:

\newcommand*\myfigure[3]{
  \begin{figure}
    \includegraphics[width=#3]{#1}
    \caption[\getfirst#2\relax]{\getsecond#2\relax}
  \end{figure}
}
\def\getfirst#1,#2\relax{{#1}}
\def\getsecond#1,#2\relax{{#2}}

However, I don't think you gain much with this syntax, over an explicit figure environment; for instance, you aren't providing for a \label to your figure.

I suggest a different syntax, using an optional argument for the short caption, which can be easily set up with xparse; the problem with separating the short caption from the long one with a comma is that frequently commas are in a caption, so you'd have to be very careful in bracing them and the advantage over two arguments would be lost.

\usepackage{xparse}
\NewDocumentCommand{\myfigure}{momm}{%
  \begin{figure}
  \centering
  \includegraphics[width=#4]{#1}
  \IfNoValueTF{#2}{\caption{#3}}{\caption[{#2}]{#3}}
  \end{figure}
}

You can call it as

\myfigure{imagefile}[short caption]{long caption}{0.8\textwidth}

when the short caption is necessary, or

\myfigure{imagefile}{long caption}{0.8\textwidth}

when there is no need for a short caption.

You may want to add an optional label:

\usepackage{xparse}
\NewDocumentCommand{\myfigure}{mommo}{%
  \begin{figure}
  \centering
  \includegraphics[width=#4]{#1}
  \IfNoValueTF{#2}{\caption{#3}}{\caption[{#2}]{#3}}
  \IfValueT{#5}{\label{#5}}
  \end{figure}
}

so the calls can be

\myfigure{imagefile}[short caption]{long caption}{0.8\textwidth}[label]

\myfigure{imagefile}{long caption}{0.8\textwidth}[label]

for providing also the (optional) label.


Without additional packages, you could do

\makeatletter
\newcommand{\myfigure}[1]{%
  \def\myfigure@file{#1}%
  \@dblarg\myfigure@caption
}
\def\myfigure@caption[#1]#2#3{%
  \begin{figure}
  \centering
  \includegraphics[width=#3]{\myfigure@file}
  \caption[{#1}]{#2}
  \end{figure}
}
\makeatother

With the optional trailing label:

\documentclass{article}
\usepackage{graphicx}

\makeatletter
\newcommand{\myfigure}[1]{%
  \begin{figure}
  \def\myfigure@file{#1}%
  \@dblarg\myfigure@caption
}
\def\myfigure@caption[#1]#2#3{%
  \def\myfigure@short{#1}%
  \def\myfigure@long{#2}%
  \def\myfigure@width{#3}%
  \@ifnextchar[{\myfigure@withlabel}{\myfigure@end}%
}
\def\myfigure@withlabel[#1]{%
  \def\myfigure@label{#1}%
  \myfigure@end
}
\def\myfigure@end{%
  \centering
  \includegraphics[width=\myfigure@width]{\myfigure@file}
  \caption[\myfigure@short]{\myfigure@long}
  \ifx\myfigure@label\@empty\else\label{\myfigure@label}\fi
  \end{figure}
}
\let\myfigure@label\@empty
\makeatother

\begin{document}

\listoffigures

\myfigure{example-image}[Short]{Long}{.8\textwidth}

\myfigure{example-image}{Long2}{.8\textwidth}[label]

\end{document}
  • It's not a direct solution to my question (I thought I could find a solution to my need in that way, my fault), but it actually suits perfectly my need, thanks! I'll test it right away. – mmj Sep 25 '15 at 10:12
  • @mmj I added the “classical” way to do it. One could add also the optional label, with some other trick. – egreg Sep 25 '15 at 10:14
  • By the way, from your answer I deduce that my orginal approach could work if I enclose non-delimiting commas in curly braces, isn't it? Can you take a look at my original guessed code? Looks like adding the last \def breaks the code(I get the error Argument of \getsfirst has an extra }.) , maybe I should move \relax somewhere else? – mmj Sep 25 '15 at 12:41
  • 1
    @mmj You're missing \relax: \caption[\getfirst#2\relax]{\getsecond#2\relax} – egreg Sep 25 '15 at 13:49
  • @mmj I edited my answer to add the information – egreg Sep 25 '15 at 13:54

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.