我正在编写一个主要使用 Lua 文件的包。到目前为止,我还没有找到测试的方法在 Lua 代码中给定的包是否已加载。我正在做的是使用\@ifpackageloaded
并调用 Lua 函数:
% Configure cref names if cleveref is loaded
\makeatletter
\@ifpackageloaded{cleveref}%
{\directlua{lyluatexmp.set_cref_names()}}%
\makeatother
但是我思考该信息也应该适用于 Lua,这使得处理这个问题变得更容易。
[编辑:]
虽然解决方案这个答案 做工作(在 TeX Live 2019/2017 上)当将函数移到外部 Lua 文件(我希望它在该文件中)时它不起作用:
local function loaded(ext)
local fmt = "ver@\\csstring\\%s." .. ext
return function(name)
return not not token.get_macro(fmt:format(name))
end
end
return {
package = loaded"sty",
class = loaded"cls"
}
在 test-two.lua 文件中(注意这里需要双反斜杠)和
\directlua{
local mod = require('test-two.lua')
classloaded = mod.class
packageloaded = mod.package
}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
}
\documentclass{article}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\usepackage{cleveref}
\directlua{
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\stop
总是返回false
。事实证明,在第二个实现中(TeX Live 2017 和 2019),的结果get_macro
始终为,而在第一个实现中,始终返回 的值。nil
token.create(fmt:format(name)).command
undefined_cs
有什么办法可以解决这个问题吗?
答案1
您可以通过将原始的 TeX 级实现转换为 Lua 来实现\@ifpackageloaded
(和):\@ifclassloaded
\directlua{
local not_loaded_cmds = {
[token.command_id'undefined_cs'] = true,
[token.command_id'relax'] = true,
}
local function loaded(ext)
local fmt = "ver@\csstring\%s." .. ext
return function(name)
return not not_loaded_cmds[token.create(fmt:format(name)).command]
end
end
packageloaded = loaded"sty"
classloaded = loaded"cls"
}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
}
\documentclass{article}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\usepackage{cleveref}
\directlua{
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\stop
这会写入标准输出(和日志)
[...]
`article` not loaded
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/article.cls
Document Class: article 2018/09/03 v1.4i Standard LaTeX document class
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/size10.clo))
`article` loaded
`cleveref` not loaded
(/usr/local/texlive/2019/texmf-dist/tex/latex/cleveref/cleveref.sty)
`cleveref` loaded)
[...]
可以使用而不是检查命令 id 来创建另一个与旧 LuaTeX 版本更兼容的版本(适用于 TeXLive 2017,我还没有测试过任何更早的版本)token.get_macro
。理论上,这与 TeX 宏的兼容性较差,但我目前想不出任何与此相关的情况:
\directlua{
local function loaded(ext)
local fmt = "ver@\csstring\%s." .. ext
return function(name)
return not not token.get_macro(fmt:format(name))
end
end
packageloaded = loaded"sty"
classloaded = loaded"cls"
}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
}
\documentclass{article}
\directlua{
if classloaded"article" then
texio.write_nl"`article` loaded"
else
texio.write_nl"`article` not loaded"
end
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\usepackage{cleveref}
\directlua{
if packageloaded"cleveref" then
texio.write_nl"`cleveref` loaded"
else
texio.write_nl"`cleveref` not loaded"
end
}
\stop
两个答案都使用了
local fmt = "ver@\csstring\%s." .. ext
这里\csstring\%
只是扩展为%
(带有 catcode other)。这是必要的,因为 TeX 否则会将其%
视为注释字符。如果将此代码移动到普通 Lua 文件(或块luacode*
)中,TeX 永远不会看到该行,因此\csstring\%
必须将其替换为%
。然后该行变为
local fmt = "ver@%s." .. ext
答案2
我已经接受了回答但我想展示一下我得出的结果,在 Lua 文件中实现解决方案
local function _loaded(ext)
--[[
Returns a function that checks whether a class or a package is loaded
--]]
local fmt = "ver@%s." .. ext
return function(name)
local macro = token.get_macro(fmt:format(name))
return macro ~= nil
end
end
-- Lua implementations of \@ifpackageloaded and \@ifclassloaded
lib.class_loaded = _loaded('cls')
lib.package_loaded = _loaded('sty')
lib
是从模块返回的表,代码用于luaoptions
包裹 (https://github.com/lualatex-tools/luaoptions/blob/master/luaoptions-lib.lua#L142) 即将在 CTAN 上发布。