Argumento opcional vazio ou Não fornece nenhum argumento opcional?

Argumento opcional vazio ou Não fornece nenhum argumento opcional?

Aprendi que \parboxtem cinco argumentos, ou seja: \parbox[<align>][<height>][<inner-align>]{<width>}{<text>}. Então eu construo meu próprio \myparbox no qual adiciono \sloppy\setlength\parfillskip{0pt}antes do número 5. Mas falha. Qual é o motivo e como redefinir \myparbox?

MWE:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\myparbox}{ooomm}{%
  \parbox[#1][#2][#3]{#4}{\sloppy\setlength\parfillskip{0pt}#5}
}
\begin{document}
AAA\fbox{\parbox[][][]{4em}{aa bb cc dd ee ff}}AAA\\% parbox typesets nothing. why?
BBB\fbox{\myparbox{4em}{aa bb cc dd ee ff}}BBB% This fails to compile
\end{document}

EDITAR:

\documentclass{article}
\usepackage{xparse}
\let\oldparbox\parbox
\RenewDocumentCommand{\parbox}{sO{c}oO{t}mm}{%
  \IfBooleanTF{#1}
    {%
      \IfNoValueTF{#3}
        {\oldparbox[#2]{#5}{\sloppy\setlength\parfillskip{0pt}#6}}
        {\oldparbox[#2][#3][#4]{#5}{\sloppy\setlength\parfillskip{0pt}#6}}
    }
    {%
      \IfNoValueTF{#3}
        {\oldparbox[#2]{#5}{#6}}
        {\oldparbox[#2][#3][#4]{#5}{#6}}
    } 
}
\begin{document}\the\fboxsep
AAA\fbox{\parbox[t]{8em}{aa bb cc dd ee ff gg hh ii}}AAA\\% parbox typesets nothing why?.
BBB\fbox{\parbox*{6em}{aa bb cc dd ee ff}}BBB% This fails to compile
\end{document}

Responder1

Conforme observado nos comentários, um argumento opcional vazio []não precisa ser equivalente a não fornecer nenhum argumento opcional. Se não fornecer o argumento equivale a passar um valor específico, deve ser verificado com a documentação ou implementação do comando.

No exemplo, as coisas pioram porque xparseo argumento opcional de ona verdade contém o valor marcado especial -NoValue-se o argumento opcional correspondente não for fornecido. Você pode e deve testar a presença de um valor com \IfNoValueTF(como sugerido pordaleifcomentário).

Essa é uma solução muito viável quando você tem apenas um argumento opcional para lidar, mas fica confuso se o número de argumentos aumentar.

Caso \parboxvocê possa descobrir que os argumentos padrão são c, \relaxcomo marcador especial e squando você procura a definição em sourc2e.pdf.

Então você poderia tentar

\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}

Normalmente eu tentaria contornar problemas como esse que exigem que eu conheça os valores/comportamento dos argumentos opcionais padrão e/ou precise de um grande número de \IfNoValueTFtestes para acertar os argumentos, pois o primeiro método parece frágil e o segundo muito detalhado e repetitivo. Uma abordagem semelhante aA resposta de Marijnpode ser uma alternativa, mas pelo menos neste caso também requer conhecimento íntimo da definição de \parbox.


editar: Acabei de ver a nova versão da pergunta. \letnão é suficiente para comandos robustos com argumentos opcionais:Quando usar \LetLtxMacro?. Eu também sugeriria fortemente não redefinir comandos fundamentais, como \parboxmesmo que a implementação possa ser compatível com versões anteriores. Um novo nome é muito mais seguro.

Responder2

Alternativamente, você pode xpatchinserir o código extra no lugar certo do comando, sem a necessidade de passar variáveis. O \parboxcomando chama o \@iiiparboxcomando interno que processa o conteúdo real, portanto este comando interno é aquele que deve ser corrigido. 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}

Observe que isso altera o comportamento de todos os parboxes. Se você deseja um comando personalizado com alinhamento justificado e também manter o comando regular, então você pode definir o comando personalizado usando uma cópia do \@iiiparboxcomando e corrigir a cópia em vez do 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}

Resultado:

insira a descrição da imagem aqui

Responder3

Os argumentos opcionais devem \parboxconter tokens específicos, se presentes. O valor padrão para o primeiro é c, portanto podemos poupar algumas verificações quanto à presença dos argumentos opcionais. É preciso começar do último.

O primeiro argumento opcional deve ser c(padrão) tou b; o segundo deve ter comprimento; o último deve ser c, t, bou s(se não for fornecido, o primeiro será usado).

Observe que o último argumento \myparboxdeve ser denotado por +m, para poder inserir parágrafos diferentes. A \deliverparboxmacro é usada para minimizar a duplicação de código.

\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}

insira a descrição da imagem aqui

informação relacionada