には 5 つの引数があることを知りました。\parbox
つまり、 です\parbox[<align>][<height>][<inner-align>]{<width>}{<text>}
。そこで、#5 の前に追加した独自の \myparbox を構築しました\sloppy\setlength\parfillskip{0pt}
。しかし、失敗しました。理由と \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}
編集:
\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}
答え1
コメントに記載されているように、空のオプション引数は、[]
オプション引数をまったく与えないことと同じである必要はありません。引数を与えないことが特定の値を渡すことと同じであるかどうかは、コマンドのドキュメントまたは実装で確認する必要があります。
xparse
この例では、対応するオプション引数が指定されていない場合、のオプションo
引数に実際に特別なマークされた値が含まれているため、状況はさらに悪化します-NoValue-
。 で値の存在をテストできますし、そうすべきです\IfNoValueTF
(ダリフのコメント)。
これは、処理するオプションの引数が 1 つしかない場合に非常に有効なソリューションですが、引数の数が増えると複雑になります。
の場合、で定義を調べると、デフォルトの引数が、特殊マーカーとして 、であること\parbox
がわかります。c
\relax
s
sourc2e.pdf
だから試してみるといい
\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}
通常、私は、最初の方法は脆弱で、2番目の方法は非常に冗長で反復的であるため、デフォルトのオプション引数の値/動作を知る必要があり、引数を正しく取得するために多数の\IfNoValueTF
テストを必要とするような問題を回避しようとします。マラインの答え代替案になるかもしれませんが、少なくともこの場合は の定義に関する詳細な知識も必要です\parbox
。
編集: 質問の新しいバージョンを見たばかりです。\let
オプションの引数を持つ堅牢なコマンドには不十分です。\LetLtxMacro はいつ使用すればよいですか?\parbox
また、実装が下位互換性を持つ可能性がある場合でも、などの基本的なコマンドを再定義しないことを強くお勧めします。新しい名前の方がはるかに安全です。
答え2
あるいは、xpatch
変数を渡すことなく、コマンド内の適切な場所に を使って追加コードを挿入することもできます。この\parbox
コマンドは実際の内容を処理する内部\@iiiparbox
コマンドを呼び出すので、この内部コマンドがパッチを適用すべきコマンドです。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}
これにより、すべての parbox の動作が変わることに注意してください。両端揃えのカスタム コマンドが必要で、通常のコマンドも保持する場合は、コマンドのコピーを使用してカスタム コマンドを定義し\@iiiparbox
、元のコマンドの代わりにコピーにパッチを適用できます。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}
結果:
答え3
のオプション引数には\parbox
、存在する場合は特定のトークンが含まれている必要があります。最初の のデフォルト値は であるc
ため、オプション引数の存在を確認する手間を省くことができます。最後の引数から始める必要があります。
最初のオプション引数はc
(デフォルト)t
またはb
、2 番目の引数は長さ、最後の引数はc
、、t
または(指定されていない場合は最初の引数が使用されます) のいずれb
かです。s
異なる段落を入力できるようにするには、 の最後の引数\myparbox
を で示す必要があることに注意してください。マクロは、コードの重複を最小限に抑えるために使用されます。+m
\deliverparbox
\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}