Ich versuche, ein Makro zu definieren, das wie folgt verwendet werden soll:
\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.
}
Das Problem ist, dass \unskip
der letzte Zeilenumbruch nicht übernommen wird. Wenn ich einen Kommentar hinzufüge (wie as in XKCD 1285.%
), funktioniert es wie erwartet, aber ist das nicht das, was \unskip
passieren soll?
Das Leerzeichen am Anfang wird korrekt weggeschluckt. Ohne \ignorespaces
steht am Anfang ein unterstrichenes Leerzeichen, \ignorespaces
entfernt dieses aber. Das \unskip
soll die unterstrichene Anweisung am Ende entfernen, tut es aber nicht.
Nach meinem Verständnis ist das \unskip
so ähnlich wie \ignorepreviousspace
. Ist das richtig?
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}
Antwort1
\uline
parst sein Argument, um den Text in Wörter zu unterteilen. Ein geparstes Wort wird in eine Box gesetzt, um seine Breite zu messen und es mit den Markierungen (Linie, Doppellinie, Welle, ...) zu überlagern. \unskip
Geht also beim Start eines neuen Wortes an den Anfang einer Box. Es gibt kein Leerzeichen, das entfernt werden könnte. Es ist also wirkungslos.
Putten\unskip
nach \uline{...}
ist besser, weil es den Kleber entfernt. Aber \uline
Einsätzezweidavon anstelle eines Leerzeichens. Das erste ist das unterstrichene Leerzeichen ( \leaders
), das zweite ist ein kleines negatives Leerzeichen (-1/300 Zoll), das wahrscheinlich hinzugefügt wurde, um eine bessere Überlappung der unterstrichenen Segmente zu erreichen.
Das Hinzufügen von nur einem \unskip
nach \uline
in derandere, inzwischen gelöschte Antwort(nur für 10K+-Benutzer sichtbar), wenn das Zeilenende danach \thesis
durch einen Kommentar entfernt wird, funktioniert es versehentlich. Am Ende eines Absatzes entfernt TeX das letzte Leerzeichen durch ein implizites \unskip
.
Lösung mit zwei\unskip
\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand*{\thesis}[1]{%
\uline{\ignorespaces #1}%
\unskip\unskip
}
\begin{document}
Before. \thesis{
Foo.
Bar.
Baz.
} After.
\end{document}
Lösung mit Pakettrimspaces
Im nächsten Beispiel wird das Paket verwendet, trimspaces
um die Leerzeichen zu entfernen, bevor der Text an übergeben wird \uline
. Dadurch wird die Lösung unabhängiger von der Implementierung von \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}
Antwort2
Heiko hat eine ausführliche Beschreibung der Lösung des Problems gegeben, daher beschränke ich mich auf die Kommentierung der Unterfrage
Nach meinem Verständnis ist das
\unskip
so ähnlich wie\ignorepreviousspace
. Ist das richtig?
Grundsätzlich nein, dieses Verständnis ist nicht richtig. \unskip
und \ignorespaces
arbeiten auf völlig unterschiedlichen Ebenen (und %
vor einem Zeilenumbruch noch einmal auf einer anderen Ebene).
Etwas vereinfacht liest TeX eine Folge vonFigurenaus der Datei und verwandelt sich dann inToken(entweder durch Lesen einer Gruppe von Zeichen als Befehlsname oder durch Zuweisen von Catcode-Werten zu Zeichentoken) Anschließend werden diese Tokenlisten verarbeitet und können schließlich horizontale oder vertikaleListenvon Setzkästen und Klebstoff.
%
arbeitet auf der Ebene vonFiguren. Wenn ein %
angezeigt wird, werden die restlichen Zeichen in dieser Zeile und der Zeilenumbruch am Ende der Zeile übersprungen und überhaupt nicht in Token umgewandelt.
\ignorespaces
arbeitet auf der Ebene vonToken. Nachdem \ignorespaces
alle Leerzeichen-Token (die normalerweise im vertikalen Modus ignoriert werden oder im horizontalen Modus eine Verbindung zwischen Wörtern hinzufügen) ignoriert wurden, bis das erste Token ohne Leerzeichen angezeigt wird, wenn die Befehle Enden beeinflussen.
\unskip
arbeitet auf der Ebene vonListen. Wenn das vorherige Element zur aktuellen horizontalen Liste hinzugefügt wurde (unabhängig davon, ob es aus einem Leerzeichen oder von einem expliziten oder impliziten Befehl stammt) \vskip
oder \hskip
aus der aktuellen Liste entfernt und verworfen wird. (Außer in der vertikalen Hauptliste auf der Seite, wo Sie hinzugefügte Elemente nicht mehr entfernen dürfen und wo es \unskip
sich um einen No-Op handelt.)
Abgesehen von der Tatsache, dass sie auf unterschiedlichen Strukturen arbeiten, beachten Sie (was für die Verarbeitung am Ende eines Absatzes in dieser Frage relevant ist), dass \ignorespaces
jede Anzahl aufeinanderfolgender Leerzeichen ignoriert wird, aber \unskip
immer nur ein Verbindungsknoten entfernt wird. Normalerweise wird natürlich \ignorespaces
nur ein Leerzeichen-Token zum Ignorieren angezeigt, da Sie arbeiten müssen, um zwei aufeinanderfolgende Token als aufeinanderfolgendes Leerzeichen zu erhaltenFigurenwerden als einzelnes Leerzeichen tokenisiert. \ignorespaces\space\space
Würde aber beispielsweise beide ignorieren.