Knowing that every command declaration with conditionally optional arguments, as \foo{...}
expanding into \foo[default]{...}
can be defined by \newcommand\foo[1][default]{...}
or the safer version of:
\newcommand\foo{\@ifnextchar[{\@foo}{\@foo[default]}}
\def\@foo[#1]#2{do something with #1 and #2}
this kind of "test" however fails if the optional argument is declared after the mandatory one. Therefore (knowing that the order of argument declaration of \@foo
cannot be changed):
\newcommand\foo{\@ifnextchar[{\@foo}{\@foo{}[default]}}
\def\@foo#1[#2]{do something with #1 and #2}
will generate errors.
More generally, if \@bar
is defined such that has to contain two (or more, but the general case is left aside) arguments, but only the optional #2
that doesn't appear just after the control sequence name:
\def\@bar#1[#2]{#1 and #2}
then, how is it possible to define \bar
such that this condition:
\bar{a}[b] % returns "a and b"
\bar{a} % returns "a and default"
will be met? In this case an internal command inside the definition of \bar
would scan all of the argument tokens of \bar
until it finds a [
; if it doesn't find any, then it'll just declare \@bar#1[default]
.
This behaviour should be similar to \@ifnextchar
(say \@iftoksexist
) with the difference that it will be sufficient for char
to just exist as argument token:
\documentclass{article}
\makeatletter
\def\@iftoksexist#1#2#3{...} %
\def\mybar{%
\@iftoksexist{[} % or \@iftoksexist[{...}{...}
{
%use "\@mybar#1[#2]"
}
{
%use "\@mybar#1[default]"
}%
}
\def\@mybar#1[#2]{#1 and #2\par}
\makeatother
%
\begin{document}
%
\mybar{lorem}[ipsum]
\mybar{dolor}
\mybar{sit}[amet]
%
\end{document}
In this case, \@iftoksexist
will search for [
inside every \mybar...
, yielding this output:
Yet again, after a sufficient number of trials, and looking this and that, I haven't had much success.
xparse