Richten Sie die Box am linken Rand aus, während Sie \parindent glue beibehalten/\noindent beachten, falls vorhanden

Richten Sie die Box am linken Rand aus, während Sie \parindent glue beibehalten/\noindent beachten, falls vorhanden

Wie definiert man einen Befehl, der zwei Argumente annimmt und aus dem ersten Argument einen neuen Absatz erstellt, bei dem der rechte Rand eines Felds, das das zweite Argument enthält, am linken Rand dieses Absatzes ausgerichtet ist, wobei sich der Bezugspunkt dieses Felds vertikal auf der Grundlinie der ersten Textzeile dieses Absatzes befindet?

Wenn ich mache

\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

, hat dann (wie erwartet) \noindentkeine Wirkung und der rechte Rand des Kästchens mit der Phrase „Linksbündig?“ wird nicht am linken Rand des Absatzes, sondern links vom Buchstaben ausgerichtet T.

Wenn anstelle von \leavevmodeI do \noindentder rechte Rand des Felds mit der Phrase „Linksbündig?“ gesetzt wird, wird dieser sowohl am linken Rand des Absatzes als auch links vom Buchstaben ausgerichtet. Vor dem Buchstaben Twird jedoch kein -glue angezeigt, sofern Sie es nicht „von Hand“ als Teil des ersten Arguments hinzufügen:\parindentT\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

Nachdem ich also Tage damit verbracht hatte, die unverständlichen, mehrdeutigen Sätze des TeXbook zu analysieren, fand ich nur Wege, die mich daran hinderten, mein gewünschtes Ziel zu erreichen, und ich erfuhr nur, warum meine Versuche nicht funktionierten.

Könnte jemand einen Weg aufzeigen, dertutarbeiten?

Antwort1

Bildbeschreibung hier eingeben

Ich denke, Sie meinen das hier, es ist nicht ganz klar:

\long\def\Command#1#2{%
\everypar{\setbox0\lastbox\llap{#2}\box0\everypar{}}#1}

\Command{The text of the paragraph.}{Left justified?}

\Command{\noindent The text of the paragraph.}{Left justified?}

\bye

Antwort2

Ich habe deinen Kommentar

Fast. Danke. \Command{\hbox{This box should be part of the paragraph, too} text text}{Left justified?}klappt nicht...

AnDavid Carlisles Antwortberücksichtigen:

Die horizontale Box der Breite \parindentam Anfang des Horizontalmodus wird ohne Ausführen des Hakens erzeugt und gesetzt \everyhbox.

Auf diese Weise können Sie einen Mechanismus zum Setzen eines \if...-Schalters erstellen, falls \everyhbox/ \everyvboxvor ausgelöst wird \everypar:

\CommandErstellen Sie aus dem ersten Argument eine temporäre vertikale Box .

Beim Erstellen dieser temporären vertikalen Box stellen Sie den Hooks \everyhbox/ \everyvboxein Makro-Token voran, das global einen \if...-Switch setzt.
Stellen Sie jedem der Hooks \everyhbox/ \everyvboxund \everypareine Anweisung voran, um alle diese Hooks wiederherzustellen.

Wirkung:

Falls vor oder \everyparausgeführt wird , werden die Hooks wiederhergestellt und damit ist die Anweisung zum Ändern des an / angehängten -Schalters weg und wird nie ausgeführt.\everyvbox\everyhbox\if..\everyhbox\everyvbox

Falls \everyvboxoder \everyhboxvorher ausgeführt wird \everypar, wird die Anweisung zum Setzen des \if-Schalters einmal ausgeführt und alle Hooks werden wiederhergestellt.

Da drei Hooks ( \everypar, \everyvbox, \everyhbox) beteiligt sind, habe ich eine rekursive Routine definiert, \prependtorestorehooksin der Sie eine Liste von Tupeln bereitstellen können, wobei die erste Komponente einen Hook bezeichnet und die zweite Komponente Token bezeichnet, die dieser Hook liefern soll, bevor alle Hooks in der Tupelliste wiederhergestellt und die Token geliefert werden, die der Hook auch vor der Neudefinition geliefert hat.

Sie müssen auch einige Vorsichtsmaßnahmen treffen, falls der Mechanismus/ \Commandverschachtelt ist.

Vorbehalte:

  • Das Anhängen an Hooks bzw. Wiederherstellen von Hooks funktioniert nur, solange die Hooks selbst keine \outer-Tokens enthalten. Der folgende Code erzeugt beispielsweise eine Fehlermeldung ! 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/ \everyvboxwird beim Erstellen eines \hbox/ ausgelöst \vbox, unabhängig davon, ob diese Box in die Ausgabedatei gelangt oder in ein Box-Register, dessen Inhalt niemals in die Ausgabedatei gelangt. Der Mechanismus kann also ausgetrickst werden, indem beispielsweise eine -Zuweisung \setboxan den Anfang des \CommandArguments von gesetzt wird.

  • \vboxAus dem ersten Argument von wird ein temporäres Element \Commandzum Setzen des \if...-Schalters erstellt, falls \everyhbox/ \everyvboxvor ausgelöst wird \everypar. Somit \Commandwird das Material des ersten Arguments von zweimal verarbeitet: Einmal zum Erstellen der temporären Box. Einmal zum Erstellen des Absatzes, der in die Ausgabedatei aufgenommen werden soll. Es gibt möglicherweise Dinge, \immediate\writedie Sie nicht zweimal ausführen möchten. Leider gibt es keinen "get-box-properties"/"box-measuring"-Modus, in dem solche Dinge abgeschaltet werden könnten.

 

\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

Bildbeschreibung hier eingeben

Ehrlich gesagt:

Ich weiß nicht, warum das alles nötig ist. Im Handbuch \Commandsteht nur, dass TeX vor der Verarbeitung in den vertikalen Modus wechselt #1. Der Benutzer kann selbst entscheiden, ob er explizit in den horizontalen Modus wechseln muss \leavevmodeoder \noindentnicht.

verwandte Informationen