\newcommand: Combinar estrella (opcional) y parámetro opcional

\newcommand: Combinar estrella (opcional) y parámetro opcional

¿Cómo puedo definir un nuevo comando que admita variantes destacadas y no destacadas, y que también admita un argumento opcional?

Intenté lo siguiente:

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

Pero esto da:

La variante sin estrella con parámetro: 1
La variante con estrella con parámetro: 1
La variante sin estrella con parámetro: 2
La variante con estrella con parámetro: 1[2]

Sin embargo, se puede escribir \MyCommand[2]*para obtener "La variante destacada con parámetro: 2", pero de alguna manera me gustaría que funcione la versión anterior.

Respuesta1

Es xparsemuy fácil jugar con argumentos opcionales y variantes destacadas:

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

Con LaTeX \newcommandes un poco más complicado. La \@ifstarmacro mira el siguiente token después de expandirse y haber absorbido sus argumentos, por lo que primero debe verificar el *argumento opcional y solo luego buscarlo:

\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 versiones imprimen:

ingrese la descripción de la imagen aquí

Su código funciona, pero no como esperaba. Busca \MyCommand[1][1]un argumento opcional "mientras se expande" \MyCommand, que luego le proporciona:

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

y solodespuésla \@ifstarprueba se expandirá para buscar el opcional *y elegir el texto en consecuencia, por lo que la sintaxis real para el comando que definiste es:

\MyCommand[optional argument]<optional star>

Respuesta2

No tomes \MyCommandparámetros, solo calcula la estrella. Luego bifurca desde allí.

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

ingrese la descripción de la imagen aquí

información relacionada