Why does parameter double when used in caption?

I wrote some commands, recently adding some convenience command \FS to add figure sources:

\newcommand{\FS}[1]{%
\protect\\{\protect\scriptsize{}Bildquelle: #1}}


I don't know whether this is correct (all those \protect), but it seems to work inside \caption. Unfortunately I tried to improve the command, adding an optional parameter:

\newcommand{\FS}[2][Bildquelle]{%
\protect\ifthenelse{\equal{#1}{}}%
\protect\\{\protect\scriptsize{}#2}
\protect\\{\protect\scriptsize{}#1: #2}}


When using the variant with no optional parameter specified, the effect is that expanded #2 is output, followed by expanded Bildquelle: #2 (Actually even when specifying the optional parameter the output is duplicated as described). For example:

I'm not deep enough into TeX to to able to fix the problem myself, even after reading those answers on \protect. How should the command be written?

• Try \newcommand{\FS}[2][Bildquelle]{% \protect\ifthenelse{\equal{#1}{}}{% \protect\\{\protect\scriptsize{}#2}}{% \protect\\{\protect\scriptsize{}#1: #2}}}. – user194703 Nov 29 '19 at 23:33
• One pair of braces to rule them all ;-) That did it, thanks! – U. Windl Nov 29 '19 at 23:40
• Is \DeclareRobustCommand available in all environments, or do I need spacial packages for it? My LaTeX knowledge is a bit outdated... – U. Windl Nov 30 '19 at 1:31
• @U.Windl I just deleted my answer (which also cancelled any reputation-gainings) as it is obsolete: As I overlooked and as egreg pointed out in a comment to my answer, commands defined in terms of \newcommand are already made robust in case of having an optional argument. Thus all the \DeclareRobustCommand-thingies shown in my (now deleted) answer aren't needed at all. Sorry for the noise. – Ulrich Diez Nov 30 '19 at 9:06

1 Answer

Note that \ifthenelse{<condition>}{<true>}{<false>} requires <true> and <false> to be grouped. If not, the two tokens following the <condition> are assumed to denote <true> and <false>. In your setup, <true> is \protect and \\ is <false>. You were probably looking for something like

\newcommand{\FS}[2][Bildquelle]{%
\protect\ifthenelse{\equal{#1}{}}%
{\protect\\{\protect\scriptsize{}#2}}
{\protect\\{\protect\scriptsize{}#1: #2}}}


Using the conditional test in How to check if a macro value is empty or will not create text with plain TeX conditionals?, you can instead define \FS to be

\newcommand{\FS}[2][Bildquelle]{%
\\
\scriptsize
\if\relax\detokenize{#1}\relax\else
#1:
\fi
#2%
}


Here's a complete minimal example of the use:

\documentclass{article}

\usepackage{caption}

\newcommand{\FS}[2][Bildquelle]{%
\\
\scriptsize
\if\relax\detokenize{#1}\relax\else
#1:
\fi
#2%
}

\begin{document}

\begin{figure}
\caption{Some caption. \FS{abc}}
\caption{Another caption. \FS[abc]{def}}
\caption{Final caption. \FS[]{ghi}}
\end{figure}

\end{document}