LuaTeX:有没有办法纯粹在 lua 端定义新的命名 tex 框(并进行所需的检查)?

LuaTeX:有没有办法纯粹在 lua 端定义新的命名 tex 框(并进行所需的检查)?

到目前为止,在我处理 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 中重新实现,即将添加.....

相关内容