\유령과 \obeylines

\유령과 \obeylines

나는 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

산출

관련 정보