我想从模拟返回的单个 JSON 文件中加载大量数字到我的文档中。为此,我到目前为止遵循了这个 stackchange 答案但对于多个值,我必须在整个文档中多次加载 JSON 文件(我是 LuaLatex 的新手,所以也许我遗漏了一些重要的东西)。我想要的是这样的:
\documentclass{article}
\usepackage{luacode}
\begin{document}
\begin{luacode}
function read(file)
local handler = io.open(file, "rb")
local content = handler:read("*all")
handler:close()
return content
end
JSON = (loadfile "JSON.lua")()
local table = JSON:decode(read("recipes.json"))
\end{luacode}
The fat content of the recipe \directlua{tex.print(table['recipe']
['title'])} is \directlua{tex.print(table['recipe']
['fat'])}.
\end{document}
实现这一目标的最干净的方法是什么?
答案1
我找到了答案:在上面的例子中,相关变量(表)被定义为本地变量。这就是为什么它在后续的 lua 调用中无法访问。解决方案如下
\documentclass{article}
\usepackage{luacode}
\begin{document}
% load json file
\begin{luacode}
function read(file)
local handler = io.open(file, "rb")
local content = handler:read("*all")
handler:close()
return content
end
JSON = (loadfile "JSON.lua")()
table = JSON:decode(read("recipes.json"))
\end{luacode}
The fat content of the recipe \directlua{tex.print(table['recipe']
['title'])} is \directlua{tex.print(table['recipe']
['fat'])}.
\end{document}
答案2
我想在根据这个问题进行自己的测试后扩展@user45893的答案,并且链接的一。
- -environment
luacode
可以放在序言中,这样可以在其下方创建自定义命令,以便在您需要在文档中打印大量外部值时减少冗长程度。 - 您可以使用 lua 函数格式化数字
string.format()
,该函数使用c++printf语法。 然而, - 该命令
\directlua{}
没有转义%
符号,因此需要使用\luaexec{}
包中的命令\usepackage{luatextra}
。此包已包含luacode
环境。 - 给定的解决方案使用了我无法找到的外部文件
JSON.lua
。无依赖的解决方案是函数utilities.json.tolua()
。 - 环境
luacode
接受 LaTeX 命令。例如描述路径。这允许轻松地将同一目录中的多个文件加载到多个变量中。
我完成的 MWE 如下所示:
\documentclass{article}
\usepackage{luatextra}
\newcommand{\dataPath}{path/to/folder}
% load the data file supposedly containing 'title' and 'numbers'
\begin{luacode}
require("lualibs.lua")
local f = io.open('\dataPath/file.json', 'r')
local s = f:read('*a')
f:close()
data = utilities.json.tolua(s)
\end{luacode}
% Simple print function
\newcommand{\printlua}[1]{\luaexec{tex.sprint(#1)}}
% Example: formatting a number with an optional formatting argument
\newcommand{\printnumber}[2][i]{\printlua{string.format("\%#1", #2)}}
\begin{document}
Simple print function: \printlua{data['title']}.
% '%i' for signed integer (default of the command).
Default number format: \printnumber{data['numbers']['number1']}.
% '%.2f' for decimal float with 2 digits after the decimal point .
Different number format: \printnumber[.2f]{data['numbers']['number1']}.
\end{document}
注意事项:
- 对于列表元素来说,该方法相当有限。我只找到了一种通过其显式索引调用它们的方法: fe
printnumber{data['listofnumbers'][5]}
。 - 科学记数法 ( ) 的格式
%e
返回 fe3.9265e+2
,这在 LaTeX 数学模式下非常难看。对于非常大或非常小的数字,我建议在生成数据文件时将它们另外存储为预格式化的字符串,并使用此解决方案直接用 加载它们\printlua{}
。 - 该命令
luaexec{}
(或tex.sprint()
,我不确定哪个是原因)不只是返回值,而是将其嵌入到组中。这妨碍了其他 LaTeX 命令对值的进一步格式化处理。
例如-package\num{}
的-command siunitx
:
\num{\printnumber[.2e]{data['numbers']['number1']}}
% gives:
% Package siunitx Error: Invalid number '\begingroup \escapechar 92...
注意:我没有任何 lua 经验,请随意按照通常的代码约定编辑格式。