¿Argumento opcional vacío o no dar ningún argumento opcional?

¿Argumento opcional vacío o no dar ningún argumento opcional?

Aprendí que \parboxtiene cinco argumentos, es decir: \parbox[<align>][<height>][<inner-align>]{<width>}{<text>}. Entonces construí mi propio \myparbox en el que agrego \sloppy\setlength\parfillskip{0pt}antes del n.° 5. Pero falla. ¿Cuál es el motivo y cómo 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}

Respuesta1

Como se indicó en los comentarios, un argumento opcional vacío []no tiene por qué ser equivalente a no dar ningún argumento opcional. Si no dar el argumento equivale a pasar un valor particular se debe verificar con la documentación o implementación del comando.

En el ejemplo, las cosas empeoran porque xparseel argumento opcional de oen realidad contiene el valor marcado especial -NoValue-si no se proporcionó el argumento opcional correspondiente. Puede y debe probar la presencia de un valor con \IfNoValueTF(como lo sugieredaleifcomentario de).

Esta es una solución muy viable cuando solo tienes que tratar con un argumento opcional, pero se vuelve complicada si aumenta el número de argumentos.

En el caso de \parboxpuede descubrir que los argumentos predeterminados son c, \relaxcomo marcador especial y scuando busca la definición en sourc2e.pdf.

Así que podrías intentarlo

\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, intentaría solucionar problemas como este que requieren que conozca los valores/comportamiento de los argumentos opcionales predeterminados y/o necesito una gran cantidad de \IfNoValueTFpruebas para obtener los argumentos correctos, ya que el primer método parece frágil y el segundo muy detallado y repetitivo. Un enfoque similar alLa respuesta de Marijn.podría ser una alternativa, pero al menos en este caso también requiere un conocimiento profundo de la definición de \parbox.


editar: Acabo de ver la nueva versión de la pregunta. \letno es suficiente para comandos robustos con argumentos opcionales:¿Cuándo utilizar \LetLtxMacro?. También sugeriría encarecidamente no redefinir los comandos fundamentales, \parboxincluso si la implementación podría ser compatible con versiones anteriores. Un nuevo nombre es mucho más seguro.

Respuesta2

Alternativamente, puede utilizar xpatchpara insertar el código adicional en el lugar correcto del comando, sin la necesidad de pasar variables. El \parboxcomando llama al \@iiiparboxcomando interno que procesa el contenido real, por lo que este comando interno es el que debe parchearse. 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}

Tenga en cuenta que esto cambia el comportamiento de todos los parboxes. Si desea un comando personalizado con la alineación justificada y también conservar el comando normal, puede definir el comando personalizado usando una copia del \@iiiparboxcomando y parchear la copia en lugar del 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:

ingrese la descripción de la imagen aquí

Respuesta3

Los argumentos opcionales \parboxdeben contener tokens específicos, si están presentes. El valor predeterminado para el primero es c, por lo que podemos realizar algunas comprobaciones de la presencia de argumentos opcionales. Hay que empezar por el último.

El primer argumento opcional debe ser c(predeterminado) to b; el segundo debe ser largo; el último debe ser , co ( si no se proporciona, se usa el primero).tbs

Tenga en cuenta que el último argumento \myparboxdebe indicarse con +m, para poder ingresar diferentes párrafos. La \deliverparboxmacro se utiliza para minimizar la duplicación 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}

ingrese la descripción de la imagen aquí

información relacionada