# \newcommand: Combine (optional) star and optional parameter

How may I define a new command that admits starred and non-starred variants, and that also admits an optional argument?

I tried the following:

\documentclass{minimal}
\makeatletter
\newcommand\MyCommand[1][1]{%
\@ifstar{%
The starred variant with parameter: #1%
}{%
The non-starred variant with parameter: #1%
}
}
\makeatother
\begin{document}
\MyCommand    \\
\MyCommand*   \\
\MyCommand[2] \\
\MyCommand*[2]
\end{document}


But this gives:

The non-starred variant with parameter: 1
The starred variant with parameter: 1
The non-starred variant with parameter: 2
The starred variant with parameter: 1[2]

Yet, one can write \MyCommand[2]* to obtain "The starred variant with parameter: 2" but somehow I'd like the above version to work.

• Please, avoid using the minimal class; it is not meant for minimal examples. – egreg Mar 15 at 13:52
• I learned many things with this question, including the fact that the minimal class is not made for minimal examples! – Bruno Mar 15 at 14:27

With xparse it's very easy to play around with optional arguments and starred variants:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\MyCommand
{
s % optional *
O{1} % first optional argument (default = 1)
}
{%
\IfBooleanTF{#1}
{The starred variant with parameter: #2}
{The non-starred variant with parameter: #2}
}
\begin{document}
\noindent
\MyCommand   \\
\MyCommand*  \\
\MyCommand[2]\\
\MyCommand*[2]
\end{document}


With LaTeX's \newcommand it a little trickier. The \@ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:

\documentclass{article}
\makeatletter
\newcommand\MyCommand
{%
\@ifstar
{\MyCommand@star}
{\MyCommand@nostar}%
}
\newcommand\MyCommand@star[1][1]{%
The starred variant with parameter: #1%
}
\newcommand\MyCommand@nostar[1][1]{%
The non-starred variant with parameter: #1%
}
\makeatother
\begin{document}
\noindent
\MyCommand   \\
\MyCommand*  \\
\MyCommand[2]\\
\MyCommand*[2]
\end{document}


Both versions print:

Your code works, but not as you expect it to. The \MyCommand[1][1] looks for an optional argument “while expanding” \MyCommand, which then gives you:

\@ifstar{%
The starred variant with parameter: <optional argument or default>%
}{%
The non-starred variant with parameter: <optional argument or default>%
}


and only after that the \@ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:

\MyCommand[optional argument]<optional star>


Make \MyCommand take no parameters, but just figure out the star. Then fork from there.

\documentclass{minimal}
\makeatletter
\newcommand\MyCommand{%
\@ifstar{\mycommandstar}{\mycommandnostar}
}
\newcommand\mycommandstar[1][1]{The starred variant with parameter: #1}
\newcommand\mycommandnostar[1][1]{The non-starred variant with parameter: #1}
\makeatother
\begin{document}
\MyCommand    \\
\MyCommand*   \\
\MyCommand[2] \\
\MyCommand*[2]
\end{document}


• I'd add a % at the end of the definition of \MyCommand. It works without that because the definition of \@ifstar ignores space tokens by design, but... :) – Phelype Oleinik Mar 15 at 14:20