Ich verwende Plain TeX (eigentlich XeTeX aus Gründen der Schriftart, aber ich verwende es im Grunde wie Plain TeX, was ich gewohnt bin). Ich tippe ein Gedicht für jemanden ab und möchte einen Effekt erzeugen, der in etwa so aussieht:
it's magic
tragic
Ich dachte, ich könnte \phantom
für diesen Zweck vielleicht Folgendes verwenden:
\begingroup\obeylines
it's magic
\hphantom{it's} tragic
\endgroup%obeylines
Ich habe verwendet \hphantom
, weil ich horizontalen Abstand möchte, aber ich kenne den Unterschied nicht genau. Die Ausgabe mit beiden \hphantom
ist \phantom
dieselbe:
Außerdem scheint es egal zu sein, ob ich den Platz innerhalb \phantom
oder außerhalb der Box anlege.
Ich bin mir nicht ganz sicher, warum das Phantom in eine eigene Zeile gesetzt wird, aber ich nehme an, dass es etwas damit zu tun hat, \obeylines
was ich nicht verstehe. Vielen Dank im Voraus für die Hilfe und entschuldigen Sie, wenn dies vielleicht ein dummer Fehler ist.
Antwort1
Wenn Sie LaTeX verwenden, hat die angezeigte Auszeichnung den gewünschten Effekt.
\documentclass{article}
\begin{document}
\begingroup\obeylines
it's magic
\hphantom{it's} tragic
\endgroup%obeylines
\end{document}
In einfachem TeX \hphantom
beginnt ein Absatz nicht so:
\begingroup\obeylines
it's magic
\leavevmode\hphantom{it's} tragic
\endgroup%obeylines
\bye
Ich würde reines TeX jedoch nur für kleine Testbeispiele verwenden, nicht für echte Dokumente.
Antwort2
Antwort3
Wenn Sie LuaTeX verwenden möchten (das grundsätzlich mit XeTeX kompatibel sein sollte), können wir eine Umgebung definieren, die alle anfänglichen Einrückungen automatisch an der vorherigen Zeile ausrichtet, ohne dass zusätzliche Markierungen erforderlich sind:
%%%%%%%%%%%%%%%%%%
%%% Formatting %%%
%%%%%%%%%%%%%%%%%%
% Make LuaTeX load fonts like XeTeX
\input luaotfload.sty
\directlua{
config.luaotfload.default_features.global.tlig = true
config.luaotfload.default_features.global.trep = true
}
% Load the fonts
\font\seventeenrm="[lmroman17-regular]" at 17pt
\font\adventorbold="TeX Gyre Adventor/B" at 12pt
% Set the main font
\seventeenrm
\baselineskip=1.2em
\nopagenumbers
%%%%%%%%%%%%%%%%
%%% TeX Code %%%
%%%%%%%%%%%%%%%%
\newattribute\alignspacesattr
\def\beginalignspaces{%
\bgroup%
\alignspacesattr=1% Mark all nodes with this attribute
\catcode`\ =12% Make the space into a regular character
\obeylines% Process line-by-line
\toksapp\everypar{\setbox0=\lastbox}% Remove the indent from every line
}
\def\endalignspaces{%
\par% Make sure that the last line is processed
\egroup%
}
%%%%%%%%%%%%%%%%
%%% Lua Code %%%
%%%%%%%%%%%%%%%%
\directlua{
% Helper function to traverse through any marked nodes
local n_attr
local function get_next_attr(n)
local next = n.next
if next then
n_attr = select(2, node.find_attribute(next, "alignspacesattr"))
return n_attr
end
end
% Replaces a node with another node
local function replace_node(head, n1, n2)
local head, current = node.remove(head, n1)
head, n2 = node.insert_before(head, current, n2)
return head, n2
end
local prev_widths = {}
% Define the callback, which runs for every line
luatexbase.add_to_callback("pre_linebreak_filter", function (head)
% Remove any discretionaries
local head = head
if get_next_attr(head) then
head = node.flatten_discretionaries(head)
end
% Initialize the line-local variables
local this_widths = {}
local before_chars = true
n_attr = head
% Iterate over every character in a marked line
while get_next_attr(n_attr) do
local char = n_attr.char
% Replace space glyphs with some sort of glue
if char == string.byte(" ") then
local hskip = node.new("glue")
if before_chars then
% If we're at the start of the line, then make the space the
% same width as the character immediately above it.
hskip.width = prev_widths[rawlen(this_widths) + 1]
else
% If we're in the middle of the line, set it to the regular
% space width.
local params = font.getfont(n_attr.font).parameters
node.setglue(
hskip,
params.space, params.space_stretch, params.space_shrink,
0, 0
)
end
head, n_attr = replace_node(head, n_attr, hskip)
else
% If we're not at a space, then set that we're not at the start
% of the line.
before_chars = false
end
% Recurse through any ligatures
local chars = {}
local function check_components(n)
if n.components then
for m in node.traverse(n.components) do
check_components(m)
end
elseif char and
(n.id == node.id("glyph") or n.id == node.id("glue"))
then
chars[rawlen(chars) + 1] = n
end
end
check_components(n_attr)
% Save the widths of the characters on this line
for _, n in ipairs(chars) do
this_widths[rawlen(this_widths) + 1] = (n.width or 0)
end
end
prev_widths = this_widths
return head
end, "align_spaces")
}
%%%%%%%%%%%%
%%% Demo %%%
%%%%%%%%%%%%
\beginalignspaces
% Works with different character widths
abc def ghi jkl mno pqr
def ghi
hi jkl m
no pqr
r stu
f ghi jkl mno pqr stu
% And with em-dashes
M l M --- M
l M --- M
M --- M
--- M
M
% And with ligatures
waffles
les
% And with different fonts
ABCDEF G {\adventorbold H I} J K
{\adventorbold I} J
EF G {\adventorbold H I}
ABCDEF G {\adventorbold H }
abM l M --- ABC
---
\endalignspaces
\bye