到目前为止,在我处理 luatex 中的命名 tex 框时,我能够在 lua 代码中设置/获取/复制其内容,但不知道如何在 lua 中定义新的 tex 框。手册中没有明确用于此的方法(而它有所有其他框操作方法)。有没有办法在 lua 中做到这一点?下面是构建代码的骨架。函数createbox
传递要创建的框的名称,它的作用类似于调用\newsavebox
(使用名称测试)。
\documentclass{article}
\begin{filecontents*}{texbox.lua}
function createbox(boxname)
if <box of name boxname does not exist> then -- luatex equivalent of ifcsname?
tex.print("\\newbox\\" .. boxname)
end
end
\end{filecontents*}
\directlua{require"texbox.lua"}
\begin{document}
\directlua{createbox('mybox')} % use lua method instead of using \newsavebox on tex side
\setbox\mybox = \hbox{Hello World}
\box\mybox
\end{document}
答案1
寄存器分配是宏格式定义的,因此不在 luatex 手册中。您似乎正在使用 lualatex,因此框分配计数为 14(恰好与纯 tex 相同),下面显示了如何以相同的顺序从 tex 或 lua 分配它们。
您可以检查名称(\luaboxa
此处)是否是新的,但 tex 定义\newbox
不会这样做(请参阅\newbox\zzz
下面的多次调用),您可以使用\newbox\frac
或\newbox\section
并破坏文档而不发出任何警告。
它确实会检查您是否没有用完寄存器。在这里,我或多或少直接\e@alloc
在 Lua 中重新实现了 LaTeX 宏。现在,该函数new_box
还会检查该名称的框是否已定义,如果是,则不会为其分配新的框寄存器。这是问题中要求的预期行为,并且还应避免意外为给定的框名分配多个框寄存器。
\documentclass{article}
\newbox\texboxa
\typeout{texboxa: \number\texboxa}
\directlua{
function e_alloc(nm,c,ta,tb,cs)
tex.setcount("global",c,tex.count[c]+1)
e_check_alloc(c,ta,tb,nm)
tex.setcount("global","allocationnumber",tex.count[c])
token.set_char(cs,tex.count[c],"global")
texio.write("log",cs .."=" .. tex.count[c])
end
function e_check_alloc(c,ta,tb,nm)
if ( tex.count[c] >= ta) then
if (tex.count[c] == ta)then
tex.setcount("global",c,256)
if(nm=="count") then
tex.setcount("global",c,tex.count[c]+10)
end
end
if(tex.count[c]>=tb) then
error("No room for a new " .. nm)
end
end
end
% \insc@unt is a count register
% \float@count is a chardef token, accessed via .mode
function new_box(b)
if not token.is_defined(b) then
e_alloc("box",14,tex.count["insc@unt"],token.create("float@count").mode,b)
end
end
new_box("luaboxa")
}
\typeout{luaboxa: \number\luaboxa}
\newbox\texboxb
\typeout{texboxb: \number\texboxb}
\count14=198
% 199 256 257 with tex
%\newbox\zzz \typeout{zzz: \number\zzz}
%\newbox\zzz \typeout{zzz: \number\zzz}
%\newbox\zzz \typeout{zzz: \number\zzz}
% 199 199 199 -- better with Lua
\directlua{new_box("zzz")}\typeout{zzz: \number\zzz}
\directlua{new_box("zzz")}\typeout{zzz: \number\zzz}
\directlua{new_box("zzz")}\typeout{zzz: \number\zzz}
\begin{document}
\directlua{new_box("zzz")}\setbox\zzz=\hbox{Hello World}\copy\zzz\typeout{zzz: \number\zzz}
\directlua{new_box("zzz")}\setbox\zzz=\hbox{Foo World}\copy\zzz\typeout{zzz: \number\zzz}
\directlua{new_box("zzb")}\setbox\zzb=\hbox{Bar World}\copy\zzb\typeout{zzb: \number\zzb}
\directlua{new_box("zzz")}\setbox\zzz=\hbox{ooF World}\copy\zzz\typeout{zzz: \number\zzz}
\setbox\zzz=\hbox{Sham World}\copy\zzz\typeout{zzz: \number\zzz}
\copy\zzb\typeout{zzb: \number\zzb}
\end{document}
终端输出是
texboxa: 45
luaboxa: 46
texboxb: 47
zzz: 199
zzz: 199
zzz: 199
zzz: 199
zzz: 199
zzb: 257
zzz: 199
zzz: 199
zzb: 257
显示了分配如何正确跳转到 etex 扩展寄存器而不覆盖浮点框。它还显示了新的框寄存器未分配给框名(如果用户尝试再次创建具有相同名称的框),从而节省了框寄存器资源。
原始答案
终端输出是
texboxa: 45
luaboxa: 46
texboxb: 47
从
\documentclass{article}
\newbox\texboxa
\typeout{texboxa: \number\texboxa}
\directlua{
tex.setcount("global",14,tex.count[14]+1)
token.set_char("luaboxa",tex.count[14],"global")
}
\typeout{luaboxa: \number\luaboxa}
\newbox\texboxb
\typeout{texboxb: \number\texboxb}
\begin{document}
\end{document}
您可以检查名称(\luaboxa
此处)是否是新的,但 tex 定义\newbox
不会这样做,您可以使用\newbox\frac
或\newbox\section
并中断文档而不会发出警告。它会检查您是否没有用尽寄存器,因此将其定义为具有错误检查以匹配的函数,\newbox
您可以
\directlua{
function new_box(b)
if tex.count[14] > 65534 then
error("No room for a new box register")
else
tex.setcount("global",14,tex.count[14]+1)
token.set_char(b,tex.count[14],"global")
end
end
new_box("luaboxa")
}
笔记这仅当盒子分配已经超过 255 时才是安全的,避免覆盖浮点盒子的更完整版本需要\e@alloc
在 Lua 中重新实现,即将添加.....