Me gustaría definir una macro que tome dos argumentos, uno de los cuales es opcional. Si no se proporciona, entonces debería tomar el otro como valor predeterminado.
Desafortunadamente,
\newcommand{\mycommand}[2][#1]{ ... }
no funciona, tampoco
\newcommand{\mycommand}[2][#2]{ ... }
¿Alguien sabe cómo hacer esto?
Respuesta1
Buenas noticias: puedes hacerlo muy fácilmente con 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}
El especificador de argumento O{...}
toma como argumento qué sustituir de forma predeterminada cuando el argumento en sí no aparece en el momento de la llamada. Bien puede ser un token de parámetro que hace referencia a otro argumento.
Respuesta2
Puedes usarxparse
condicionar fácilmente si un argumento opcional estaba presente o no, y proporcionar la combinación adecuada a otra función (auxiliar). He aquí un ejemplo:
\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}
Una versión ligeramente diferente de esto surge del uso de \caption
, donde puede proporcionar un argumento opcional para LoT/LoF, pero si no lo hace, se envían los argumentos obligatorios (de manera similar para unidades seccionales con argumentos opcionales destinados a ToC). ). Esto utiliza elnúcleo'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}
Respuesta3
Este es un intento de agregar protección como ocurre con otras macros que procesan argumentos opcionales:
%%\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}