¿Por qué unskip no funciona aquí?

¿Por qué unskip no funciona aquí?

Estoy intentando definir una macro para usar de la siguiente manera:

\usepackage[normalem]{ulem}
\newcommand{\thesis}[1]{\uline{\ignorespaces #1\unskip}}
% underlining required by school - I know, I know

% later...

\thesis{
  This is the beginning of a multi-line thesis statement.
  I use one sentence on each line throughout my document.
  Thus, the thesis is broken as in XKCD 1285.
}

El problema es que \unskipno devora el salto de línea final. Si agrego un comentario (como as in XKCD 1285.%), funciona como se esperaba, pero ¿no es esto lo que \unskipse supone que debe hacer?

El espacio inicial se engulle correctamente. Sin \ignorespaceshay un espacio subrayado al principio, pero \ignorespaceslo elimina. Se \unskipsupone que debe eliminar la declaración subrayada al final, pero no lo hace.

Tengo entendido que \unskipes algo así como \ignorepreviousspace. ¿Es esto correcto?

MWE:

\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand{\thesis}[1]{\uline{\ignorespaces #1\unskip}}
\begin{document}
\thesis{
  Foo.
  Bar.
  Baz.
} % comment at end of previous line gives desired output
\end{document}

Respuesta1

\ulineanaliza su argumento para dividir el texto en palabras. Una palabra analizada se coloca en un cuadro para medir su ancho y superponerle las marcas (línea, línea doble, onda, ...). Por lo tanto, \unskipva del comienzo de una nueva palabra al comienzo de un cuadro. No hay espacio para eliminar. Por lo tanto queda sin efecto.

Poniendo\unskip después \uline{...}Es mejor porque elimina el pegamento. Pero \ulineinsertadosde ellos en el lugar de un espacio. El primero es el espacio subrayado ( \leaders), el segundo es un pequeño espacio negativo (-1/300 in), probablemente añadido para conseguir una mejor superposición de los segmentos subrayados.

Agregando solo uno \unskipdespués \ulineen elotra respuesta ahora eliminada(visible solo para más de 10.000 usuarios), si el final de la línea posterior \thesisse elimina mediante un comentario, funciona por accidente. Al final de un párrafo, TeX elimina el último espacio mediante un implícito \unskip.

solución con dos\unskip

\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand*{\thesis}[1]{%
  \uline{\ignorespaces #1}%
  \unskip\unskip
}

\begin{document}
Before. \thesis{
  Foo.
  Bar.
  Baz.
} After.
\end{document}

Resultado

Solución con paquetetrimspaces

El siguiente ejemplo usa paquete trimspacespara eliminar los espacios antes de pasar el texto a \uline. Esto hace que la solución sea más independiente de la implementación de \uline.

\documentclass{article}
\usepackage[normalem]{ulem}
\usepackage{trimspaces}
\makeatletter
\newcommand*{\thesis}[1]{%
  \def\thesis@text{#1}%
  \trim@spaces@in\thesis@text
  \expandafter\uline\expandafter{\thesis@text}%
}
\makeatother

\begin{document}
Before. \thesis{
  Foo.
  Bar.
  Baz.
} After.
\end{document}

Respuesta2

Heiko ha dado una descripción completa de cómo resolver el problema, por lo que me limitaré a comentar la subpregunta.

Tengo entendido que \unskipes algo así como \ignorepreviousspace. ¿Es esto correcto?

Básicamente no, esa comprensión no es correcta. \unskip y \ignorespacestrabajar en niveles completamente diferentes (y %antes de un salto de línea vuelve a funcionar en otro nivel).

Ligeramente simplificado, TeX lee una secuencia decaracteresdel archivo, convirtiéndose luego enfichas(ya sea leyendo un grupo de caracteres como un nombre de comando o asignando valores de código cat a tokens de caracteres) Luego, estas listas de tokens se procesan y eventualmente pueden producir listas horizontales o verticales.lizade cajas tipográficas y pegamento.

%trabaja a nivel decaracteres. Si %se ve a, el resto de los caracteres en esa línea y el salto de línea al final de la línea se omiten y no se convierten en tokens en absoluto.

\ignorespacestrabaja a nivel defichas. Después de que \ignorespacestodos los tokens de espacio (que normalmente se ignoran en el modo vertical, o agregan pegamento entre palabras en el modo horizontal) se ignoran hasta que se ve el primer token que no es un espacio cuando los comandos afectan a los extremos.

\unskiptrabaja a nivel deliza. Si el elemento anterior agregado a la lista horizontal actual (ya sea que provenga de un espacio o de un elemento explícito o implícito \vskipo \hskipse elimina de la lista actual y se descarta. (Excepto en la lista vertical principal de la página donde no puede eliminar elementos una vez agregados , y \unskipno es una operación).

Aparte del hecho de que están operando en diferentes estructuras, tenga en cuenta (que es relevante para el procesamiento al final de un párrafo de esta pregunta) que \ignorespacesignora cualquier número de espacios consecutivos pero \unskipsolo elimina un nodo de pegamento. Por lo general, por supuesto, \ignorespacessolo se ve una ficha de espacio para ignorar, ya que tienes que trabajar para obtener dos fichas consecutivas como espacio consecutivo.caracteresse tokenizan como una ficha de un solo espacio. Pero, por ejemplo, \ignorespaces\space\spaceignoraría ambos.

información relacionada