Leeres optionales Argument oder überhaupt kein optionales Argument angeben?

Leeres optionales Argument oder überhaupt kein optionales Argument angeben?

Ich habe erfahren, dass \parboxes fünf Argumente hat, nämlich: \parbox[<align>][<height>][<inner-align>]{<width>}{<text>}. Also konstruiere ich meine eigene \myparbox, in die ich \sloppy\setlength\parfillskip{0pt}vor #5 einfüge. Aber es schlägt fehl. Was ist der Grund und wie kann ich \myparbox neu definieren?

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}

BEARBEITEN:

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

Antwort1

Wie in den Kommentaren erwähnt, []muss ein leeres optionales Argument nicht unbedingt gleichbedeutend damit sein, überhaupt kein optionales Argument anzugeben. Ob das Nichtangeben des Arguments gleichbedeutend mit der Übergabe eines bestimmten Werts ist, muss anhand der Dokumentation oder Implementierung des Befehls überprüft werden.

Im Beispiel wird es noch schlimmer, weil xparsedas optionale oArgument von tatsächlich den speziell markierten Wert enthält, -NoValue-wenn das entsprechende optionale Argument nicht angegeben wurde. Sie können und sollten das Vorhandensein eines Wertes mit testen \IfNoValueTF(wie vorgeschlagen vonAbonnieren's Kommentar).

Das ist eine sehr praktikable Lösung, wenn Sie nur mit einem optionalen Argument arbeiten müssen, aber es wird kompliziert, wenn die Zahl der Argumente zunimmt.

In diesem Fall können Sie als speziellen Marker \parboxherausfinden, dass die Standardargumente sind c, und wenn Sie die Definition in nachschlagen .\relaxssourc2e.pdf

Sie könnten es also versuchen

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

Normalerweise würde ich versuchen, Probleme wie dieses zu umgehen, bei denen ich die standardmäßigen optionalen Argumentwerte/das Verhalten kennen muss und/oder eine große Anzahl von \IfNoValueTFTests durchführen muss, um die Argumente richtig zu erhalten, da die erste Methode fragil und die zweite sehr ausführlich und repetitiv erscheint. Ein Ansatz ähnlich wieMarijns Antwortkönnte eine Alternative sein, erfordert aber zumindest in diesem Fall auch genaue Kenntnisse der Definition von \parbox.


bearbeiten: Ich habe gerade erst die neue Version der Frage gesehen. \letreicht für robuste Befehle mit optionalen Argumenten nicht aus:Wann soll \LetLtxMacro verwendet werden?. Ich würde außerdem dringend davon abraten, grundlegende Befehle wie neu zu definieren, \parboxselbst wenn die Implementierung abwärtskompatibel sein könnte. Ein neuer Name ist viel sicherer.

Antwort2

Alternativ können Sie xpatchden zusätzlichen Code an der richtigen Stelle im Befehl einfügen, ohne Variablen übergeben zu müssen. Der \parboxBefehl ruft den internen \@iiiparboxBefehl auf, der den eigentlichen Inhalt verarbeitet, daher ist dieser interne Befehl derjenige, der gepatcht werden sollte. 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}

Beachten Sie, dass dies das Verhalten aller Parboxen ändert. Wenn Sie einen benutzerdefinierten Befehl mit Blocksatzausrichtung wünschen und gleichzeitig den regulären Befehl beibehalten möchten, können Sie den benutzerdefinierten Befehl mithilfe einer Kopie des \@iiiparboxBefehls definieren und die Kopie anstelle des Originals patchen. 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}

Ergebnis:

Bildbeschreibung hier eingeben

Antwort3

Die optionalen Argumente \parboxmüssen bestimmte Token enthalten, falls vorhanden. Der Standardwert für das erste ist c, sodass wir uns einige Überprüfungen auf das Vorhandensein der optionalen Argumente sparen können. Man muss mit dem letzten beginnen.

Das erste optionale Argument sollte c(Standard) toder sein b, das zweite sollte eine Länge sein, das letzte sollte c, oder tsein (wenn nicht angegeben, wird das erste verwendet).bs

Beachten Sie, dass das letzte Argument \myparboxmit gekennzeichnet werden sollte +m, um verschiedene Absätze eingeben zu können. Das \deliverparboxMakro wird verwendet, um Code-Duplikationen zu minimieren.

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

Bildbeschreibung hier eingeben

verwandte Informationen