使用 luatexbase.add_to_callback() 我如何有条件地获取 open_read_file 和 find_read_file 的默认行为?

使用 luatexbase.add_to_callback() 我如何有条件地获取 open_read_file 和 find_read_file 的默认行为?

理由:我的目标是创建一个系统,通过 Lua 假装正在读取某个文件,但实际上内容来自其他地方。其他地方有一个概念叫做 VFS(虚拟文件系统),这是我借用的名字。

考虑以下 MWE(我知道它有缺陷):

% !TeX encoding = UTF-8
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}

\begin{luacode*}
do
    -- Table which contains "reader" functions for the virtual "files" given as keys
    vfs = { ["ZaphodBeeblebrox"] = function() return nil end }

    local function luatexbase_log(text, ...)
        texio.write_nl("log", string.format(text, ...))
    end

    local function get_vfs_realname(name)
        local pfx = "virtual." -- virtual "file" prefix
        if name:find(pfx, 1, true) == 1 then
            local lookup_name = name:sub(#pfx + 1, #name)
            if vfs[lookup_name] ~= nil and type(vfs[lookup_name]) == "function" then
                return lookup_name
            end
        end
        return nil -- not found
    end

    local function hook_find_read_file(id, name)
        kpse_name = kpse.find_file(name)
        if kpse_name then
            return kpse_name
        end
        local rname = get_vfs_realname(name)
        if rname then
            luatexbase_log([[Found VFS \input lookup: %s (id=%d)]], rname, id)
            return name
        end
    end
    
    local function emulate_default_open_read_file(name)
        return {
            ["fhandle"] = assert(io.open(name,"r")),
            ["reader"] = function(self)
                    return self.fhandle:read("*l")
                end,
            ["close"] = function(self)
                    self.fhandle:close()
                end,
        }
    end

    local function hook_open_read_file(name)
        kpse_name = kpse.find_file(name)
        if kpse_name then
            return emulate_default_open_read_file(kpse_name)
        end
        local rname = get_vfs_realname(name)
        if rname then
            return { ["reader"] = vfs[rname] }
        end
    end

    luatexbase.add_to_callback("find_read_file", hook_find_read_file, "vfs")
    luatexbase.add_to_callback("open_read_file", hook_open_read_file, "vfs")
end
\end{luacode*}

\begin{document}
\input{virtual.ZaphodBeeblebrox}
bla
\end{document}

据我所知,代码运行完美。但是,有一点我不喜欢:emulate_default_open_read_file()

我完全编造了该函数,试图猜测 LuaLaTeX 默认做什么。

问题

  1. 除了我自己认为 LuaLaTeX 在“open_read_file”上默认执行的操作之外,有没有办法可以访问默认行为?这里的目标是在行为上与默认行为 100% 相同,除了处理我自己的虚拟“文件”时。
  2. 假设上面有这样的方法,我该如何通过默认函数检测失败并启动我的回退?或者这里唯一的方法是切换顺序,检测之前的虚拟“文件”,然后失败并恢复到默认值?

注意:我知道当前"ZaphodBeeblebrox" reader函数存在缺陷。它应该逐行返回数据并以 结尾以nil表示文件结束。但我在充实这个函数之前遇到了困难。所以请耐心等待。

PS:我擅自重写了luatexbase_log以直接texdoc ltluatex使用该string.format()功能,这样可以节省一些输入。 PPS:我尝试这样做是为了避免必须临时写入磁盘,并避免在使用\directlua\luadirecttex.print()一堆 LaTeX+TikZ 代码时遇到的奇怪行为。可能与扩展有关。但将 Lua 代码的输出(手动)写入磁盘,然后在写入的文件上使用\input,碰巧有效。这就是我在这里试图模拟的。

相关内容