Ich möchte ein Makro definieren, das zwei Argumente annimmt, von denen eines optional ist. Wenn es nicht angegeben ist, soll das andere als Standardwert verwendet werden.
Bedauerlicherweise,
\newcommand{\mycommand}[2][#1]{ ... }
funktioniert nicht, auch nicht
\newcommand{\mycommand}[2][#2]{ ... }
Weiß jemand, wie das geht?
Antwort1
Die gute Nachricht ist, dass dies ganz einfach ist mit xparse
:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\foo}{O{#2}m}{%
Optional=``#1'', mandatory=``#2''\par
}
\NewDocumentCommand{\oof}{mO{#1}}{%
Mandatory=``#1'', optional=``#2''\par
}
\begin{document}
\foo{x}
\foo[y]{x}
\oof{x}
\oof{x}[y]
\end{document}
Der Argumentspezifizierer O{...}
verwendet als Argument, was als Standard ersetzt werden soll, wenn das Argument selbst zum Aufrufzeitpunkt nicht erscheint. Dies kann durchaus ein Parametertoken sein, das auf ein anderes Argument verweist.
Antwort2
Sie könnenxparse
um einfach davon abhängig zu machen, ob ein optionales Argument vorhanden war oder nicht, und die entsprechende Kombination einer anderen (Hilfs-)Funktion zu übergeben. Hier ist ein Beispiel:
\documentclass{article}
\usepackage{xparse}
\newcommand{\printthis}[2]{%
Optional: #1; Mandatory: #2%
}
\NewDocumentCommand{\mycommand}{o m}{%
\IfValueTF{#1}
{\printthis{#1}{#2}}% \mycommand[..]{...}
{\printthis{#2}{#2}}% \mycommand{...}
}
\begin{document}
\mycommand{first}
\mycommand[first]{second}
\end{document}
Eine leicht abgewandelte Version davon ergibt sich aus der Verwendung von \caption
, wobei Sie ein optionales Argument für das LoT/LoF angeben können, aber wenn Sie dies nicht tun, werden stattdessen die obligatorischen Argumente gesendet (ähnlich für Sektionseinheiten mit optionalen Argumenten, die für das ToC bestimmt sind). Dies verwendet dasKernel'S \@dblarg
:
\documentclass{article}
\newcommand{\printthis}[2][]{%
Optional: #1; Mandatory: #2%
}
\makeatletter
\newcommand{\mycommand}{%
\@dblarg\printthis
}
\makeatother
\begin{document}
\mycommand{first}
\mycommand[first]{second}
\end{document}
Antwort3
Dies ist ein Versuch, Schutz hinzuzufügen, wie bei anderen Makros, die optionale Argumente verarbeiten:
%%\errorcontextlines=1000
\documentclass[a4paper]{article}
\makeatletter
\newcommand\makefirstmandatorytheoptional[1]{%
\expandafter\innermakefirstmandatorytheoptional
\expandafter{\csname\string#1\endcsname}{#1}%
}%
\newcommand\innermakefirstmandatorytheoptional[2]{%
\def#2{%
\ifx\protect\@typeset@protect
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\kernel@ifnextchar[{#1}{\@dblarg{#1}}}%
{\protect#2}%
}%
}%
\newcommand\mycommand[2][dummyoptional]{%
This is taken for the optional argument: #1.\\
This is taken for the mandatory argument: #2.
}%
\makefirstmandatorytheoptional{\mycommand}%
\makeatother
\parindent=0ex
\parskip=\medskipamount
\begin{document}
No optional argument given---\verb|\mycommand{A}|:
\mycommand{A}
Optional argument "B" given---\verb|\mycommand[B]{A}|:
\mycommand[B]{A}
\end{document}