\newcommand: Combine estrela (opcional) e parâmetro opcional

\newcommand: Combine estrela (opcional) e parâmetro opcional

Como posso definir um novo comando que admite variantes com e sem estrela, e que também admite um argumento opcional?

Eu tentei o seguinte:

\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}

Mas isso dá:

A variante sem estrela com parâmetro: 1
A variante com estrela com parâmetro: 1
A variante sem estrela com parâmetro: 2
A variante com estrela com parâmetro: 1[2]

No entanto, pode-se escrever \MyCommand[2]*para obter "A variante estrelada com parâmetro: 2", mas de alguma forma eu gostaria que a versão acima funcionasse.

Responder1

É xparsemuito fácil brincar com argumentos opcionais e variantes marcadas com estrela:

\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}

Com o LaTeX é \newcommandum pouco mais complicado. A \@ifstarmacro olha para o próximo token depois que a macro é expandida e absorve seus argumentos, então você precisa primeiro verificar *e só então procurar o argumento opcional:

\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}

Ambas as versões imprimem:

insira a descrição da imagem aqui

Seu código funciona, mas não como você espera. O \MyCommand[1][1]procura por um argumento opcional “durante a expansão” \MyCommand, que fornece:

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

e somentedepois dissoo \@ifstarteste será expandido para procurar o opcional *e escolher o texto de acordo, então a sintaxe real do comando que você definiu é:

\MyCommand[optional argument]<optional star>

Responder2

Faça \MyCommandsem parâmetros, apenas descubra a estrela. Então bifurque a partir daí.

\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}

insira a descrição da imagem aqui

informação relacionada