
2 つの引数を取り、最初の引数から新しい段落を作成し、2 番目の引数を含むボックスの右余白がその段落の左余白に揃えられ、そのボックスの参照点が垂直方向にその段落の最初のテキスト行のベースライン上にあるコマンドを定義するにはどうすればよいでしょうか。
私が行った場合
\long\def\Command#1#2{\leavevmode\llap{#2}#1}
\Command{The text of the paragraph.}{Left justified?}
\Command{\noindent The text of the paragraph.}{Left justified?}
\bye
の場合、(予想どおり)\noindent
効果はなく、「左揃え?」というフレーズを含むボックスの右余白は、段落の左余白に揃えられるのではなく、文字の左に揃えられますT
。
の代わりに\leavevmode
を実行する\noindent
と、「左揃え?」というフレーズを含むボックスの右余白は、段落の左余白と文字の左の両方で揃えられますが、の最初の引数の一部として「手動で」追加しない限り、文字の前に -glue はT
表示されません。\parindent
T
\Command
\long\def\Command#1#2{\noindent\llap{#2}#1}
\Command{The text of the paragraph.}{Left justified?}
\Command{\noindent The text of the paragraph.}{Left justified?}
\bye
そこで、TeXbook の不可解で曖昧なフレーズを解析するのに何日も費やした後、私が見つけたのは、私が望んでいることを達成できない方法だけで、私の試みがうまくいかない理由だけを知りました。
誰か方法を教えてくれませんかする仕事?
答え1
答え2
あなたのコメントを受け取りました
ほぼ完了です。ありがとうございます。
\Command{\hbox{This box should be part of the paragraph, too} text text}{Left justified?}
うまくいきません...
の上デビッド・カーライルの回答考慮に入れる:
横モードの始めの幅の横ボックスは\parindent
フックせずに作成して設定します\everyhbox
。
したがって、 / がの前にトリガーされた\if...
場合に -switch を設定するためのメカニズムを作成できます。\everyhbox
\everyvbox
\everypar
\Command
の最初の引数から一時的な垂直ボックスを作成します。
一時的な垂直ボックスを作成するときに、フックの先頭に\everyhbox
/\everyvbox
マクロ トークンを追加して、\if...
スイッチをグローバルに設定します。
各フックの先頭に \everyhbox
/\everyvbox
と、\everypar
これらすべてのフックを復元するディレクティブを追加します。
効果:
または\everypar
の前に が実行された場合、フックが復元され、/に追加された -switchを変更するディレクティブはなくなり、実行されることはありません。\everyvbox
\everyhbox
\if..
\everyhbox
\everyvbox
\everyvbox
または が\everyhbox
の前に実行される場合\everypar
、 -switch を設定するディレクティブが\if
1 回実行され、すべてのフックが復元されます。
3 つのフック ( \everypar
、、) が関係しているため、タプルのリストを指定できる再帰ルーチンを定義しました\everyvbox
。最初のコンポーネントはフックを示し、2 番目のコンポーネントはタプル リスト内のすべてのフックを復元する前にこのフックが配信するトークンを示し、再定義前にフックが配信したトークンも配信します。\everyhbox
\prependtorestorehooks
また、mechanism/ が\Command
ネストされている場合には、いくつかの予防措置が必要です。
注意:
フックへの追加/フックの復元は、フック自体にトークンが含まれていない場合にのみ機能します
\outer
。たとえば、次のコードはエラー メッセージを生成します! Forbidden control sequence found while scanning text of \everypar.
。\begingroup \everypar={\problem}% \outer\def\problem{How to overcome the problem?}% \everypar=\expandafter{\the\everypar Again: How to overcome the problem?}% \endgroup \bye
\everyhbox
/ は、そのボックスが出力ファイルに入るか、その内容が出力ファイルに入らないボックス レジスタに入るかに関係なく、/ を\everyvbox
作成するときにトリガーされます。したがって、たとえば、の引数の先頭に -assignment を配置することで、メカニズムを欺くことができます。\hbox
\vbox
\setbox
\Command
の前に/がトリガーされた場合にスイッチを設定するために、 の最初の引数
\vbox
から一時的なものが作成されます。したがって、 の最初の引数の素材は 2 回処理されます。1 回は一時的なボックスを作成するため、もう 1 回は出力ファイルに入れる段落を作成するためです。2回実行したくない処理があるかもしれません。残念ながら、そのような処理をオフにできる「get-box-properties」/「box-measuring」モードはありません。\Command
\if...
\everyhbox
\everyvbox
\everypar
\Command
\immediate\write
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
%\prependtorestorehooks{%
% {{hook 1}{prepend 1}}%
% {{hook 2}{prepend 2}}%
% ...
%}%
\long\def\prependtorestorehooks#1{%
\prependtorestorehookscreraterestore{}{#1}#1\relax
}%
\long\def\prependtorestorehookscreraterestore#1#2#3{%
% #1 - Restore-List created so far
% #2 - entire list
% #3 - next element
\ifx\relax#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\prependtorestorehooksprependtohooks{}{#1}#2\relax}%
{%
\prependtorestorehooksextract#3{#1}{#2}%
}%
}%
\long\def\prependtorestorehooksextract#1#2{%
\expandafter\prependtorestorehooksextractinner\expandafter{\the#1}{#1}%
}%
\long\def\prependtorestorehooksextractinner#1#2#3{%
\prependtorestorehookscreraterestore{#3#2={#1}}%
}%
\long\def\prependtorestorehooksprependtohooks#1#2#3{%
%#1 prepend-list-created so far
%#2 restore-list
%#3 {hook}{prepend}
\ifx\relax#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#1}{%
\prependtorestorehooksprependtohooksb#3{#1}{#2}%
}%
}%
\long\def\prependtorestorehooksprependtohooksb#1{%
\expandafter\prependtorestorehooksprependtohooksc\expandafter{\the#1}{#1}%
}%
\long\def\prependtorestorehooksprependtohooksc#1#2#3#4#5{%
\prependtorestorehooksprependtohooks{#4#2={#3#5#1}}{#5}%
}%
%------------------------------------------------------------------------------------
\newbox\MyBox
\newif\ifleadingbox
\newif\ifintestbox\intestboxfalse
\newif\ifhookdone\hookdonefalse
\def\firstindent{}%
\long\def\setifleadingboxandfirstindent#1{%
\begingroup
\ifintestbox\else\global\hookdonefalse\global\leadingboxfalse\fi
\setbox\MyBox=\vbox{%
\intestboxtrue
\prependtorestorehooks{%
{{\everypar}{\ifhookdone\else\setbox\MyBox=\lastbox\xdef\firstindent{\the\wd\MyBox}\box\MyBox\global\hookdonetrue\fi}}%
{{\everyhbox}{\ifhookdone\else\global\leadingboxtrue\global\hookdonetrue\fi}}%
{{\everyvbox}{\ifhookdone\else\global\leadingboxtrue\global\hookdonetrue\fi}}%
}%
#1%
}%
\endgroup
}%
\long\def\Command#1#2{%
\par
\setifleadingboxandfirstindent{#1}%
\prependtorestorehooks{{{\everypar}{\setbox\MyBox\lastbox\llap{#2}\box\MyBox}}}%
\ifleadingbox\leavevmode\else\noindent\hbox to\firstindent{\hfill}\fi#1%
}%
\leavevmode
\kern-1in
\noindent test \hfill test \hfill test
\setifleadingboxandfirstindent{a}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\hbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\vbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\noindent\vbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\noindent {\bf Test 1:}
\Command{The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 2:}
\Command{\noindent The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 3:}
\Command{\hbox to 5cm{The\hfill wide\hfill text} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 4:}
\Command{\noindent\hbox to 5cm{The\hfill wide\hfill text} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 5:}
\Command{\vtop{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 6:}
\Command{\noindent\vtop{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 7:}
\Command{\vbox{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 8:}
\Command{\noindent\vbox{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 9:}
\newdimen\MyDimen
\setbox\MyBox=\hbox{Left justified?}
\MyDimen=\wd\MyBox
\Command{\noindent\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 10:}
\Command{\leavevmode\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 11:}
\Command{\noindent\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\Command{\noindent The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 12:}
\Command{\noindent\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\Command{The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 13:}
\Command{\leavevmode\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\advance\hsize-\parindent\Command{\noindent The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 14:}
\Command{\leavevmode\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\advance\hsize-\parindent\Command{The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 15:}
\Command{\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 16:}
% `\Command` starts with `\par`, i.e., by resorting to (restricted) vertical mode. Thus \kerns at the beginning of \Command's first argument in any case are vertical.
\Command{\kern\MyDimen\noindent The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 17:}
% `\Command` starts with `\par`, i.e., by resorting to (restricted) vertical mode. Thus \kerns at the beginning of \Command's first argument in any case are vertical.
\Command{\kern\MyDimen\hbox{T}he text of the paragraph.}{Left justified?}
\smallskip\hrule\bigskip
\noindent {\bf Test 18:}
\Command{The text of the paragraph. \par The text of the paragraph. \par The text of the paragraph.\Command{\noindent The text of the paragraph. \par The text of the paragraph. \par The text of the paragraph.}{Left justified?}}{Left justified?}
\smallskip\hrule\bigskip
\noindent{\bf !!!! But: !!!}
\bigskip
\noindent {\bf Test 19:}
\Command{\setbox\MyBox=\hbox{Something to trigger the every-hook}\noindent This text is indented although it should not be indented. The reason is the triggering of {\tt\string\everyhbox} by {\tt\string\setbox...} right at the beginning of {\tt\string\Command}'s first argument.}{Left justified?}
\bye
実を言うと:
なぜこれらすべてが必要なのかわかりません。 のマニュアルでは、\Command
を処理する前に TeX が垂直モードに切り替わるということだけを説明しています#1
。 ユーザーは、水平モードに切り替えるために明示的\leavevmode
または が\noindent
必要かどうかを自分で決定できます。