Gostaria de definir uma macro que receba dois argumentos, um dos quais é opcional. Se não for fornecido, deverá considerar o outro como valor padrão.
Infelizmente,
\newcommand{\mycommand}[2][#1]{ ... }
não funciona, nem
\newcommand{\mycommand}[2][#2]{ ... }
Alguém sabe como fazer isto?
Responder1
Boas notícias: você pode fazer isso facilmente com 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}
O especificador de argumento O{...}
toma como argumento o que substituir como padrão quando o argumento em si não aparece no momento da chamada. Este pode muito bem ser um token de parâmetro referente a outro argumento.
Responder2
Você pode usarxparse
para condicionar facilmente se um argumento opcional estava presente ou não e fornecer a combinação apropriada para outra função (auxiliar). Aqui está um exemplo:
\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}
Uma versão ligeiramente diferente disso decorre do uso de \caption
, onde você pode fornecer um argumento opcional para o LoT/LoF, mas se não o fizer, os argumentos obrigatórios serão enviados (da mesma forma para unidades seccionais com argumentos opcionais destinados ao ToC ). Isso usa onúcleoé \@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}
Responder3
Esta é uma tentativa de adicionar proteção como acontece com outras macros que processam argumentos opcionais:
%%\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}