\phantom und \obeylines

\phantom und \obeylines

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 \phantomfü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 \hphantomist \phantomdieselbe:

Bildbeschreibung hier eingeben

Außerdem scheint es egal zu sein, ob ich den Platz innerhalb \phantomoder 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, \obeylineswas ich nicht verstehe. Vielen Dank im Voraus für die Hilfe und entschuldigen Sie, wenn dies vielleicht ein dummer Fehler ist.

Antwort1

Bildbeschreibung hier eingeben

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 \hphantombeginnt 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

Verwendung von \halign:

\halign{#&#\cr
  it's &magic\cr
       &tragic\cr}
\bye

Bildbeschreibung hier eingeben

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

Ausgabe

verwandte Informationen