\фантом и \обейлинии

\фантом и \обейлинии

Я использую Plain TeX (на самом деле XeTeX из-за шрифтов, но я использую его в основном как Plain, к которому я привык). Я печатаю стихотворение для кого-то и хочу создать эффект в духе

it's magic
     tragic

Я подумал, что, возможно, я мог бы использовать \phantomдля этой цели, например

\begingroup\obeylines
it's magic
\hphantom{it's} tragic
\endgroup%obeylines

Я использовал, \hphantomпотому что мне нужно горизонтальное пространство, но я не совсем понимаю разницу. Вывод с любым из них \hphantomи \phantomтот же:

введите описание изображения здесь

При этом, похоже, не имеет значения, размещаю ли я пространство внутри коробки \phantomили снаружи.

Я не совсем уверен, почему фантом помещают на отдельную линию, но я думаю, что это как-то связано с \obeylinesэтим, чего я не понимаю. Заранее спасибо за помощь, и извините, если это, возможно, какая-то глупая ошибка.

решение1

введите описание изображения здесь

Если вы используете LaTeX, то отображаемая вами разметка имеет тот эффект, который вы задумали.

\documentclass{article}

\begin{document}

\begingroup\obeylines
it's magic
\hphantom{it's} tragic
\endgroup%obeylines

\end{document}

В простом TeX \hphantomабзац не начинается, поэтому:


\begingroup\obeylines
it's magic
\leavevmode\hphantom{it's} tragic
\endgroup%obeylines


\bye

Но я бы использовал простой TeX только для небольших тестовых примеров, а не для реальных документов.

решение2

С использованием \halign:

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

введите описание изображения здесь

решение3

Если вы готовы использовать LuaTeX (который, как правило, должен быть совместим с XeTeX), мы можем определить среду, которая автоматически выравнивает все начальные отступы с предыдущей строкой, без необходимости какой-либо дополнительной разметки:

%%%%%%%%%%%%%%%%%%
%%% 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

выход

Связанный контент