Empty optional argument or Not giving optional argument at all?
As noted in the comments, an empty optional argument []
need not be equivalent to giving no optional argument at all. Whether not giving the argument is equivalent to passing a particular value must be checked with the documentation or implementation of the command.
In the example things get worse because xparse
's optional o
argument actually contain the special marked value -NoValue-
if the corresponding optional argument was not given. You can and should test for presence of a value with \IfNoValueTF
(as suggested by daleif's comment).
That is a very viable solution when you have only one optional argument to deal with, but it gets messy if the number of arguments increases.
In case of \parbox
you can find out that the default arguments are c
, \relax
as special marker and s
when you look up the definition in sourc2e.pdf
.
So you could try
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\myparbox}{O{c}O{\relax}O{s}mm}{%
\parbox[#1][#2][#3]{#4}{\sloppy\setlength\parfillskip{0pt}#5}%
}
\begin{document}
BBB\fbox{\parbox{4em}{\sloppy\setlength\parfillskip{0pt}aa bb cc dd ee ff}}BBB
BBB\fbox{\myparbox{4em}{aa bb cc dd ee ff}}BBB
\end{document}
Normally I would try to work around issues like this that require me to know the default optional argument values/behaviour and or need a great number of \IfNoValueTF
tests to get the arguments right as the first method seems fragile and the second very verbose and repetitive. An approach similar to Marijn's answer might be an alternative, but at least in this case also requires intimate knowledge of the definition of \parbox
.
edit: I only just saw the new version of the question. \let
is not enough for robust commands with optional arguments: When to use \LetLtxMacro?. I would also strongly suggest not to redefine fundamental commands such as \parbox
even if the implementation might be backwards compatible. A new name is much safer.
Alternatively, you can use xpatch
to insert the extra code at the right place in the command, without the need to pass variables around. The \parbox
command calls the internal \@iiiparbox
command which processes the actual contents, so this internal command is the one that should be patched. MWE:
\documentclass{article}
\usepackage{xpatch}
\begin{document}
\makeatletter
\xpatchcmd{\@iiiparbox}{#5}{\sloppy\setlength\parfillskip{0pt}#5}{}{}
\makeatother
AAA\fbox{\parbox{4em}{aa bb cc dd ee ff}}AAA
\end{document}
Note that this changes the behavior of all parboxes. If you want a custom command with the justified alignment and also keep the regular command, then you can define the custom command using a copy of the \@iiiparbox
command and patch the copy instead of the original. MWE:
\documentclass{article}
\usepackage{xpatch}
\begin{document}
\makeatletter
\def\myparbox{\@ifnextchar [\@iparbox {\myiiiparbox c\relax [s]}}
\let\myiiiparbox\@iiiparbox
\xpatchcmd{\myiiiparbox}{#5}{\sloppy\setlength\parfillskip{0pt}#5}{}{}
\makeatother
AAA\fbox{\parbox{4em}{aa bb cc dd ee ff}}AAA
BBB\fbox{\myparbox{4em}{aa bb cc dd ee ff}}BBB
\end{document}
Result:
The optional arguments to \parbox
must contain specific tokens, if present. The default value for the first is c
, so we can spare some checks for the presence of the optional arguments. One needs to start from the last one.
The first optional argument should be c
(default), t
or b
; the second one should be a length; the last one should be c
, t
, b
or s
(if not given, the first one is used).
Note that the last argument to \myparbox
should by denoted by +m
, in order to be able to input different paragraphs. The \deliverparbox
macro is used in order to minimize code duplication.
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\myparbox}{O{c}oom+m}{%
\IfNoValueTF{#3}
{%
\IfNoValueTF{#2}
{%
\parbox[#1]{#4}{\deliverparbox{#5}}%
}%
{%
\parbox[#1][#2]{#4}{\deliverparbox{#5}}%
}%
}%
{%
\parbox[#1][#2][#3]{#4}{\deliverparbox{#5}}%
}
}
\NewDocumentCommand{\deliverparbox}{+m}{%
\sloppy\setlength\parfillskip{0pt}#1%
}
\begin{document}
AAA\fbox{\parbox{4em}{aa bb cc dd ee ff}}AAA
BBB\fbox{\myparbox{4em}{aa bb cc dd ee ff}}BBB
BBB\fbox{\myparbox[t][12ex][s]{4em}{aa bb cc dd ee ff\par\vfil aa bb}}BBB
\end{document}