在 LuaLaTeX 中,我该如何捕获环境内容以供 Lua 逐字处理?例如,考虑类似
\begin{foobar}
Hello {World}
\end{foobar}
我希望能够获取环境的内容并将其传递给 Lua,如下所示
foobar(" Hello {World}\n")
(然后 Lua 最终会将处理后的版本传回 LaTeX,但我大概可以处理这个问题)。
答案1
进入时启动“录制”模式\begin{foobar}
,关闭环境时结束录制模式。这样,您就获得了纯缓冲区内容。
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
do
local mybuf = ""
function readbuf( buf )
mybuf = mybuf .. buf .. "\n"
end
function startrecording()
luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
end
function stoprecording()
luatexbase.remove_from_callback('process_input_buffer', 'readbuf')
local buf_without_end = mybuf:gsub("\\end{foobar}\n","")
print(string.format("Lua: %q", buf_without_end))
end
end
\end{luacode*}
\begin{document}
\newenvironment{foobar}{\directlua{startrecording()}}{\directlua{stoprecording()}}
\begin{foobar}
Hello {World}
\end{foobar}
\end{document}
答案2
在 ConTeXt 中,您可以简单地使用缓冲区来实现这一点。
\def\startfoobar
{\definebuffer[foobar][startfoobar][stopfoobar]}
\def\stopfoobar
{\ctxlua{userdata.luafunction(buffers.getcontents('foobar'))}
然后该函数userdata.luafunction
将接收环境的内容。
查看ConTeXt 维基查看更多示例。
答案3
有点晚了,但这个修复https://tex.stackexchange.com/users/243/topskip的答案可以完成这项工作:
回答评论中的问题:
在 topskip 的回答中你好世界仍会写入 pdf 文件,这通常不是人们想要的。所以我采纳了他的答案并进行了更改,如果读取的行不包含“\end{foobar}”,则不会向 tex 解释器返回任何内容,但如果它包含“\end{foobar}”,则会将其吐回(通过 nil 返回值)tex 解释器,然后结束 foobar 环境。如果“\end{foobar}”行不会返回,则 tex 永远不会结束环境,这显然不是您想要的。
该示例仍不完善,因为如果同一行上“\end{foobar}”之前有文本,它就不会给出所需的结果。
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
do
local mybuf = ""
function readbuf( buf )
print("buf=" .. buf)
i,j = string.find(buf,"\\end{foobar}")
print(i,j)
if i==nil then
mybuf = mybuf .. buf .. "\n"
print("[" .. mybuf .. "]")
return ""
else
return nil
end
end
function startrecording()
luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
end
function stoprecording()
luatexbase.remove_from_callback('process_input_buffer', 'readbuf')
local buf_without_end = mybuf:gsub("\\end{foobar}\n","")
print(string.format("Lua: %s", buf_without_end))
end
end
\end{luacode*}
\begin{document}
\newenvironment{foobar}{\directlua{startrecording()}}{\directlua{stoprecording()}}
\begin{foobar}
Hello {World}
\end{foobar}
\end{document}