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:

enter image description here


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}

enter image description here

Tags:

Xparse

Parbox