我正在尝试使用mlist_to_hlist
回调标记数学上标。我想象上标 noad 就像一个head
(或list
有两个 noad 列表nucleus
和sup
),我可以在里面放置我创建的 noad。但我不能简单地开始工作node.insert_before
或node.insert_after
函数。我想添加围绕所有上标及其部分的用户定义节点(标签),如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
....\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.next
node.insert_before
node.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
不会递归到子列表中,因此您的代码将忽略子列表中的任何上标,例如嵌套上标、分数等。