Justifique el cuadro en el margen izquierdo manteniendo \parindent pegamento/obedeciendo \noindent si está presente

Justifique el cuadro en el margen izquierdo manteniendo \parindent pegamento/obedeciendo \noindent si está presente

Cómo definir un comando que toma dos argumentos y a partir del primer argumento crea un nuevo párrafo donde el margen derecho de un cuadro que contiene el segundo argumento se justifica en el margen izquierdo de ese párrafo con el punto de referencia de ese cuadro verticalmente en el línea de base de la primera línea de texto de ese párrafo?

Si lo hago

\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

, entonces (como se esperaba) \noindentno tiene ningún efecto y el margen derecho del cuadro que contiene la frase "¿Justificado a la izquierda?" no está justificado al margen izquierdo del párrafo pero sí a la izquierda de la letra T.

Si en lugar de \leavevmodelo hago \noindent, entonces el margen derecho del cuadro que contiene la frase "¿Justificado a la izquierda?" está justificado tanto en el margen izquierdo del párrafo como a la izquierda de la carta, Tpero no habrá \parindentpegamento antes de la carta Ta menos que lo agregue "a mano" como parte del \Commandprimer argumento de ':

\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

Entonces, después de pasar días analizando frases ambiguas e inescrutables del TeXbook, solo encontré formas de no lograr lo que deseo y solo aprendí por qué mis intentos no funcionan.

¿Alguien podría señalar una manera quehace¿trabajar?

Respuesta1

ingrese la descripción de la imagen aquí

Creo que te refieres a esto, no del todo claro:

\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

Respuesta2

Tomé tu comentario

Casi. Gracias. \Command{\hbox{This box should be part of the paragraph, too} text text}{Left justified?}no funciona...

enLa respuesta de David Carlisleen cuenta:

La caja horizontal de ancho \parindental inicio del modo horizontal se produce y se coloca sin sacar el gancho \everyhbox.

Por lo tanto, puede crear un mecanismo para configurar un \if...interruptor en caso de que \everyhbox/ \everyvboxse active antes \everypar:

Cree un cuadro vertical temporal a partir \Commanddel primer argumento.

Mientras crea ese cuadro vertical temporal, anteponga a los ganchos \everyhbox/ \everyvboxun macro-token que establece globalmente un \if...interruptor.
Anteponga a cada uno de los ganchos \everyhbox/ \everyvboxy \everyparuna directiva para restaurar todos estos ganchos.

Efecto:

En caso de que \everyparse lleve a cabo antes de \everyvboxo \everyhbox, los ganchos se restaurarán y, por lo tanto, la directiva para cambiar el \if..interruptor adjunto a \everyhbox/ \everyvboxdesaparecerá y nunca se ejecutará.

En caso de que \everyvboxo \everyhboxse lleve a cabo antes \everypar, la directiva para configurar el \ifinterruptor se ejecuta una vez y se restablecen todos los ganchos.

Como hay tres ganchos involucrados ( \everypar,, ), definí una rutina recursiva en la que puede proporcionar una lista de tuplas, el primer componente indica un gancho y el segundo componente indica tokens para que este gancho se entregue antes de restaurar todos \everyvboxlos ganchos en la lista de tuplas y entregar. las señales que el gancho también entregó antes de redefinir.\everyhbox\prependtorestorehooks

También necesita algunas precauciones en caso de que el mecanismo \Commandesté anidado.

Advertencias:

  • Agregar a ganchos/restaurar ganchos solo funciona siempre que los propios ganchos no contengan \outertokens. Por ejemplo, el siguiente código genera un mensaje de error ! 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/ \everyvboxse activa al crear un \hbox/ \vboxsin importar si ese cuadro llega al archivo de salida o ingresa a un registro de cuadro cuyo contenido nunca llegará al archivo de salida. Por lo tanto, se puede engañar al mecanismo colocando, por ejemplo, una \setboxasignación al comienzo del \Commandargumento de.

  • \vboxSe crea un temporal a partir \Commanddel primer argumento de para configurar el \if...interruptor -en caso de que \everyhbox/ \everyvboxse active antes \everypar. Así, el material del \Commandprimer argumento de se procesa dos veces: una para crear el cuadro temporal. Una vez para crear el párrafo que debería ir al archivo de salida. Puede haber cosas \immediate\writeque no quieras que se hagan dos veces. Desafortunadamente, no existe un modo "obtener propiedades de caja"/"medición de caja" donde esas cosas puedan desactivarse.

 

\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

ingrese la descripción de la imagen aquí

Para ser sincero:

No sé por qué es necesario todo esto. En el manual de \Commandsimplemente diga que TeX cambia al modo vertical antes de procesar #1. El usuario puede decidir por sí mismo si es explícito \leavevmodeo \noindentsi es necesario cambiar al modo horizontal.

información relacionada