在 Lua 世界中,Lua 模块使用 LuaRocks 安装。使用 LuaTeX,这些模块通常安装在文件夹中scripts
(在 MikTeX 窗口下)。
有哪些工具可用于下载和安装普通 Lua 包?如何避免冲突?例如,在下面的最小化中,返回kpse.lookup
带有目录前缀和不带有目录前缀的正确文件路径。如果两个包都提供模块,这不会造成冲突吗Utilities
?
%!TEX TS-program = lualatex
\documentclass{article}
\usepackage{luatexbase}
\usepackage{luacode}
\begin{document}
\begin{luacode}
local path = "luaotfload/"
local filename = "mkstatus"
local src = path..filename
local filename = path.."mkstatus"
local srcdots = "luaotfload.mkstatus"
local f = kpse.lookup(filename, {format = "lua"})
local f1 = kpse.lookup(src, {format = "lua"})
-- success
tex.print("\\par",f)
tex.print("\\par",f1)
-- local mkstatus = require("mkstatus")
\end{luacode}
\end{document}
是否有一种为 LuaTeX 编写和安装模块的标准方法?
答案1
Lua 模块已经发展起来,从 Lua 5.2 开始,您不再需要关键字module
。您很可能见过这样写的模块mymodule.lua
:
module("mymodule", package.seeall)
function foo() -- create it as if it's a global function
print("Hello World!")
end
请勿使用此格式,因为它现已不再使用。
最小模块示例
Lua 模块通常被编写为只返回一个表。它还保存在具有模块名称的文件中。因此,如果您有一个模块test
,则应将其保存为test.lua
-- Module test (saved under test.lua)
local M = M or {}
M.test = function ()
return "a test"
end
return M
使用模块
可以使用require()
函数调用模块。此处的惯例是使用与模块名称同名的局部变量。如果模块名称有点,则使用最后一个点后面的名称。
local test = require"test"
约定的原因是,它有助于帮助记忆长代码中的模块名称,因此您不必向上滚动来查看它的来源。
子模块和包
Lua 允许模块名称分层,使用点分隔名称级别。例如,名为的模块languages.greek
是模块的子模块languages
。包裹是一个完整的模块树,是Lua中的分布单位。
从 Lua 的角度来看,同一个包中的子模块没有明确的关系。 要求一个模块不会自动加载其任何子模块;要求languages.greek
将加载greek
而不是languages
和greek
模块。 如果包要求所有模块,则编写一个初始化模块,然后加载模块的平衡,这是一种很好的做法。
文件夹结构应该遵循一种russian dolls
方法,将主模块保存在具有模块名称的文件中。
在哪里开发模块
我认为使用以下 IDE 开发 LuaTeX 模块是一种更好的做法ZeroBrane工作室或者您最喜欢的编辑器,例如 Vim 或 Emacs。模块应该能够独立于 LuaTeX 引擎工作,以便进行适当的测试。稍后将详细介绍这一点。
记录模块
在开发包的模块时,我自己的经验让我相信最好将它们作为自文档化的 lua 使用卢阿多克或者目录,而不是直接进入ltxdoc\docstrip
方法。这样就可以使用 IDE 和代码开发流量更容易。一旦您对代码满意,就可以将其转换为 |.dtx| 以便于分发。这很容易生成,就像使用以下方法生成的其余包文件一样:
\nopreamble\nopostamble
\generate{
\file{mymodule.lua}{\from{\jobname.dtx}{mymodule}}
}
模块除了其 Lua 注释字符串之外,可能还具有内置标识表,例如:
-- module name
-- cldr based greek translation strings for territories
-- as defined by unicode
local m = m or {}
m = {
el = {
identity = {
version = {
_cldrVersion = "26",
_number = "$Revision: 10809 $",
_version = '1.01',
_author = "some name"
},
generation = {
_date = "$Date= 2014_08_14 15=10=07 _0500 (Thu, 14 Aug 2014) $"
},
},
...
return m
也可以使用luatexbase版本控制和模块加载与注册的样式。这又把我们带回到路径问题,这在使用 Lua 和 LuaTeX 进行开发时很麻烦。
路径
更准确地说,当 LuaTeX 请求foo.bar
(或foo.bar.lua
)时,它首先查找文件foo/bar
)时,它首先使用帕西阿使用扩展名.lua
,然后对于foo.bar
,删除可能的扩展名。因此,为了找到模块,它需要位于Kpathsea
查找 Lua 文件的目录中。如果您只有一个文件,您可以在与 |.tex| 文件相同的文件夹中找到它。当您需要无法找到的文件时,kpathsea
错误消息将指向所有搜索过的目录,这可以提示您需要在哪里找到模块才能让 LuaTeX 访问它们。
安装 Lua 软件包(来自 Lua 存储库,例如卢阿罗克斯)不会自动将它们提供给 LuaTeX。到目前为止,我发现最好的方法是使用git
安装它们。例如安装笔灯,它有一组有用的实用程序,在您的机器上导航到您的\scripts
发行版中的目录并输入:
git clone https://github.com/stevedonovan/Penlight.git
安装后,您必须更新分发数据库。
关注点分离
为 LuaTeX 编写的许多实用程序和模块可能在 TeX 世界之外有一个实用程序,因此我认为将纯 Lua 代码拆分在其自己的模块中并将任何导出到 LuaTeX 的代码拆分在单独的模块中是一种很好的tex.print
做法。Lua 通过节点之一或类似节点与 TeX 对话,这些节点最好位于不同的模块中。此外,最好也有一些测试 Lua 代码。
下面是一个较长的例子来说明讨论。创建 MWE 如下:
%!TEX TS-program = lualatex
\documentclass{article}
\usepackage{luatexbase}
\usepackage{luacode}
\begin{document}
\begin{luacode}
local f = kpse.lookup('cmd', {format = "lua"})
-- success
tex.print("\\par",f)
local cmd = require("cmd")
local csname, def = cmd.csname, cmd.def
csname('test', 'this is a test in csname')
def('test', 'this is a test')
\end{luacode}
\test
\makeatletter
\@test
\end{document}
这个 MWE 将是我们对 中的模块的测试LuaLaTeX
。我们将在 Lua 接口包中创建一个名为 的模块cmd
,它将使用\def
s 或创建宏csname
。代码如下。
---
-- module cmd
--
-- require main (not provided in example)
local m = m or {}
local print = print
if type(tex)== "table" then
print = tex.print
end
m.csname = function (a, b)
return print("\\expandafter\\gdef\\csname"..'@'..a.."\\endcsname{"..b.."}")
end
m.def = function (a, b)
return print("\\gdef\\"..a.."{"..b.."}")
end
return m
print
请注意,在文档中或纯 Lua 测试期间,都使用 进行打印。我们只是测试是否tex
可用并重新定义该print
函数。
它的 Lua 测试可以放在单独的文件或模块中(如果我们有很多测试)。我们将该文件命名为test_cmd
--- cmd_test
local cmd = require("cmd")
local csname, def = cmd.csname, cmd.def
csname('test', 'this is a test in csname')
def('test', 'this is a test')
总之,任何模块都应该有一个相关的模块代码,用于TeX
测试。LuaTeX 包应该包含以下内容
-Lua 模块(我们在上面的例子中没有创建)
- 与 LuaTeX 接口的相关 Lua 模块(如上例所示)
-测试模块(针对 TeX 和 Lua)
以上是我迄今为止的个人经历,不要把它们视为一成不变的。LuaTeX 团队打开了这样一个潘多拉魔盒,人们第一次可以开始思考正确的结构良好的代码。再多的TeX
黑客攻击也无法取代复杂的编程,比如正确的国际化一个包或json
从一个网站获取响应,然后使用 Lua 打印表格。