将用户定义节点添加到数学 NOAD

将用户定义节点添加到数学 NOAD

我正在尝试使用mlist_to_hlist回调标记数学上标。我想象上标 noad 就像一个head(或list有两个 noad 列表nucleussup),我可以在里面放置我创建的 noad。但我不能简单地开始工作node.insert_beforenode.insert_after函数。我想添加围绕所有上标及其部分的用户定义节点(标签),如nucleussup。输出中的期望结果将如下所示:

...\glue(\abovedisplayshortskip) 0.0 plus 3.0
...\glue(\baselineskip) 4.8572
...\hbox(7.1428+0.0)x5.03473, shifted 169.98264, direction TLT
....\whatsit0="pre_superscript"
....\hbox(0.0+0.0)x0.0, direction TLT
.....\whatsit0="pre_nucleus"
.....\whatsit0="empty"
.....\whatsit0="post_nucleus"
....\hbox(3.01389+0.0)x5.03473, shifted -4.12892, direction TLT
.....\whatsit0="pre_sup"
.....\OML/cmm/m/it/7 x
.....\whatsit0="post_sup"
....\whatsit0="post_superscript"
...\penalty 0
...\glue(\belowdisplayshortskip) 6.0 plus 3.0 minus 3.0

周围环境..._nucleus..._sup标签也可以开箱即用(如果它们不影响输出)。到目前为止,我只得到:

...\glue(\abovedisplayshortskip) 0.0 plus 3.0
...\glue(\baselineskip) 4.8572
...\hbox(7.1428+0.0)x5.03473, shifted 169.98264, direction TLT
....\hbox(0.0+0.0)x0.0, direction TLT
.....\whatsit0="empty"
....\hbox(3.01389+0.0)x5.03473, shifted -4.12892, direction TLT
.....\OML/cmm/m/it/7 x
....\whatsit0="post_superscript"
...\penalty 0
...\glue(\belowdisplayshortskip) 6.0 plus 3.0 minus 3.0

这是我的 MWE(math.lua):

local USER_MARK   = node.new("whatsit","user_defined")
USER_MARK.type    = 115   -- This means that value is a Lua string
USER_MARK.value   = "0"     -- anything

local function tag_superscript (h, d, p)
    for n in node.traverse(h) do
        if n.sup then

            if n.nucleus then 
                -- maybe its not nessesary, but there is no where 
                -- to stick "pre_nucleus" and "post_nucleus"
                if node.type(n.nucleus.id) == "sub_mlist" 
                   and not n.nucleus.head then
                    local submlist = node.new("sub_mlist")
                    local usermark = node.copy(USER_MARK)
                    usermark.value = "empty"
                    -- is it valid to create head like this?
                    submlist.head = usermark
                    n.nucleus.head = submlist.head
                end

                -- tagging superscript base (nucleus) 
                local A = node.copy(USER_MARK)
                A.value = "pre_nucleus"
                node.insert_before(n.nucleus, n.nucleus, A) -- what is proper head ????

                local B = node.copy(USER_MARK)
                B.value = "post_nucleus"
                node.insert_after(h, n.nucleus, B)

            end

            -- tagging sup begin and end
            local A = node.copy(USER_MARK)
            A.value = "pre_sup"
            node.insert_before(n.sup, n.sup, A)

            local B = node.copy(USER_MARK)
            B.value = "post_sup"
            node.insert_after(h, n.sup, B)

            -- tagging all superscript begin and end
            local A = node.copy(USER_MARK)
            A.value = "pre_superscript"
            node.insert_before(h, n, A)

            local B = node.copy(USER_MARK)
            B.value = "post_superscript"
            node.insert_after(h, n, B)    
        end
    end
    return node.mlist_to_hlist(h, d, p)
end
luatexbase.add_to_callback('mlist_to_hlist', tag_superscript, 'Tag superscript')

Tex 文件:

\documentclass{article}
\usepackage{luatexbase}
\directlua{dofile("math.lua")}

\begin{document}
\loggingall
$$ {}^x $$
\end{document}

空上标核 ( {}) 我特意查看了如何处理节点列表。我尝试了各种方法n.next,,在和内,但我得到了关于不存在 noads 或任何效果的错误。任何关于如何附加到数学 NOAD 的工作n.sup.head的 建议或解释都将非常有帮助。n.sup.nextnode.insert_beforenode.insert_after

答案1

您想在 nucleaus/sup 中添加多个内容,因此您需要将 nucleus/sup 作为一个列表。如果不是,您可以创建一个只有一个 noad 的列表,其中包含原始 nucleus/sup 作为 nucleus。然后您有一个列表,因此您可以使用 head n.nucleus.head

另一个问题是您使用insert_before:insert_before有时insert_after会更改列表头。它们无法通过自己分配新的列表头,因此它们返回新的列表头。这对您来说不是问题,insert_after因为您从未在列表中插入第一个节点,但insert_before可能会使用列表头进行调用。因此将返回值分配给原始列表头。

我还添加了一个,user_id以便您稍后识别您的内容:

local USER_MARK   = node.new("whatsit","user_defined")
USER_MARK.user_id = luatexbase.new_whatsit'my_special_whatsit'
USER_MARK.type    = 115   -- This means that value is a Lua string
USER_MARK.value   = "0"     -- anything

local function tag_superscript (h, d, p)
    for n in node.traverse(h) do
        if n.sup then
            if n.nucleus then 
                -- maybe its not nessesary, but there is no where 
                -- to stick "pre_nucleus" and "post_nucleus"
                if node.type(n.nucleus.id) == "sub_mlist" 
                   and not n.nucleus.head then
                    local usermark = node.copy(USER_MARK)
                    usermark.value = "empty"
                    n.nucleus.head = usermark
                end

                if node.type(n.nucleus.id) ~= "sub_mlist" then
                  local sublist = node.new'sub_mlist'
                  local noad = node.new'noad'
                  noad.nucleus = n.nucleus
                  sublist.head = noad
                  n.nucleus = sublist
                end
                -- tagging superscript base (nucleus) 
                local A = node.copy(USER_MARK)
                A.value = "pre_nucleus"
                n.nucleus.head = node.insert_before(n.nucleus.head, n.nucleus.head, A)

                local B = node.copy(USER_MARK)
                B.value = "post_nucleus"
                node.insert_after(n.nucleus.head, node.tail(n.nucleus.head), B)
            end
            -- tagging sup begin and end
            if node.type(n.sup.id) ~= "sub_mlist" then
              local sublist = node.new'sub_mlist'
              local noad = node.new'noad'
              noad.nucleus = n.sup
              sublist.head = noad
              n.sup = sublist
            end
            -- tagging superscript base (nucleus) 
            local A = node.copy(USER_MARK)
            A.value = "pre_sup"
            n.sup.head = node.insert_before(n.sup.head, n.sup.head, A)

            local B = node.copy(USER_MARK)
            B.value = "post_sup"
            node.insert_after(n.sup.head, node.tail(n.sup.head), B)

            -- tagging all superscript begin and end
            local A = node.copy(USER_MARK)
            A.value = "pre_superscript"
            h = node.insert_before(h, n, A)

            local B = node.copy(USER_MARK)
            B.value = "post_superscript"
            node.insert_after(h, n, B)    
        end
    end
    return node.mlist_to_hlist(h, d, p)
end
luatexbase.add_to_callback('mlist_to_hlist', tag_superscript, 'Tag superscript')

另一点值得注意的是:node.traverse不会递归到子列表中,因此您的代码将忽略子列表中的任何上标,例如嵌套上标、分数等。

相关内容