缓存文件时出现问题,辅助数据无法导入

缓存文件时出现问题,辅助数据无法导入

以下代码缓存包括。这消除了使用 的需要\includeonly。问题是,为了使引用、计数器、目录正确,需要导入相应的辅助文件。不幸的是,我似乎无法让它做任何正确的事情(我尝试了很多不同的方法)。

基本上,当我手动将 aux 文件内容复制并粘贴到 tex 文件然后进行编译时,我会得到所需的结果,但是当我通过 lua 执行等效操作时,我什么也得不到。就好像插入的 tex 被完全忽略了一样。

这个项目有点复杂,但我会把它分解开来,因为有些人似乎很容易感到困惑或跳到简单的结论:

  1. 这需要 Windows。稍加修改即可在 Linux 或其他操作系统上运行。主要问题是执行简单的文件操作(例如复制)时需要经过一些步骤,因为 TeX 的设计很差。

  2. 以下所有文件都直接放在同一个

TeXCache.lua——主要的 Lua 缓存代码

if __INCLUDES__TeXCache ~= nil then 
else
    __INCLUDES__TeXCache = true 
    if __DEBUG == true then 
        print("Including TeXCache.lua") 
    end

    require "md5"
    require "lfs"
    require "persist"


    ------------------------------------------ Utility functions
    if not file then file = {} end 
    function file.Exists(name) local f = io.open(name, "r") if f ~= nil then io.close(f) return true end return false end
    function FileExists(name) local f = io.open(name, "r") if f ~= nil then io.close(f) return true end return false end
    function FileSize(name) local f = io.open(name, "r") if f == nil then return -1 end local current = f:seek() local size = f:seek("end") f:seek("set", current) io.close(f) return size end

    function split(str, pat) local t = {} local fpat = "(.-)" .. pat local last_end = 1 local s, e, cap = str:find(fpat, 1) while s do if s ~= 1 or cap ~= "" then table.insert(t,cap) end last_end = e+1 s, e, cap = str:find(fpat, last_end) end if last_end <= #str then cap = str:sub(last_end) table.insert(t, cap) end return t end   
    function string.trim(s, c) if not c then c = " \t" end return s:match('^['..c..']*(.-)['..c..']*$') end
    function string.split(str, sep, n) 
        local sep, fields = sep or ":", {}      
        --local pattern = string.format("([^%s]+)", sep) 
        local pattern = '[^'..sep..']'
        if n == 0 or n == nil then pattern = '('..pattern..'+)' end
        if n > 0 then pattern = '^'..(pattern..'+'):rep(n)..'('..pattern..'+)' end
        str:gsub(pattern, function(c) fields[#fields + 1] = c end) 
        return fields 
    end

    function DeepCopyTable(orig)
        local orig_type = type(orig)
        local copy
        if orig_type == 'table' then
            copy = {}
            for orig_key, orig_value in next, orig, nil do
                copy[DeepCopyTable(orig_key)] = DeepCopyTable(orig_value)
            end
            setmetatable(copy, DeepCopyTable(getmetatable(orig)))
        else -- number, string, boolean, etc
            copy = orig
        end
        return copy
    end


    function CopyFile(source, dest)
        local infile = io.open(source, "rb")
        instr = infile:read("*a")
        infile:close()
        local outfile = io.open(dest, "wb")
        outfile:write(instr)
        outfile:close()
    end

    function ReadFile(source, text)
        if not text then text = "rb" else text = "r" end
        local infile = io.open(source, text)
        if not infile then return nil end
        instr = infile:read("*a")
        infile:close()
        return instr
    end

    function WriteFile(source, data)
        local outfile = io.open(source, "wb")
        instr = infile:write(data)
        outfile:close()
    end

    function DeleteFile(Filename)
        -- windows only. os.remove has problems!?
        os.execute('del /Q "'..Filename:gsub("/","\\")..'" > nul')
    end


    --------------------------------------------- Setup



    TeXCache = {}
    TeXCache.Arguments = "";
    TeXCache.ModeAfter = "\\batchmode"
    TeXCache.Disabled = false
    TeXCache.FileExt = "_TeXCache.tex"
    TeXCache.CacheDir = "TeXCache/"
    TeXCache.HistoryFilename = "TeXCacheHistory.dat";   
    TeXCache.Header = ""        
    TeXCache.ForceRegenerate = false
    TeXCache.Count = 0  
    TeXCache.History = {}
    TeXCache.Temp = {}

    --------------------- Preprocessing TeX
    function StartProcessingTeX()

        -- Load TeXCache.History and set all values to nil, If they are cached, they will be set to 1 at the end and the nil values keys/files can be removed
        TeXCache.History = persistence.load(TeXCache.Path..TeXCache.CacheDir..TeXCache.HistoryFilename);        
        if TeXCache.History then
            if not TeXCache.History.Cached then
                TeXCache.History.Cached = {}
            end         
        else
            TeXCache.History = {}
            TeXCache.History.Cached = {}
        end

        local curPage = -1
        local line 

        -- Read the synctex file and attempt to match input file with pages, onces the pages that the input file spans is determined,
        TeXCache.Temp.ValidCache = false

        TeXCache.Temp.Synctex = {}
        TeXCache.Temp.Synctex.Input_ShortFiles = {}
        TeXCache.Temp.Synctex.Input_Indexes = {}
        -- Read Synctex If exists, else cannot cache. Stores page relations to input file relations
        if FileExists(TeXCache.Path..TeXCache.JobName..".synctex") then 
            local f = io.open(TeXCache.Path..TeXCache.JobName..".synctex", "r")
            if f ~= nil then    
                while true do
                    line = f:read()
                    if line == nil then break end

                    -- Get Input files and store in three way lookup
                    if (string.sub(line,1,6) == "Input:") then
                        local idx = tonumber(split(line, ":")[2])
                        line = string.sub(line,8 + #tostring(idx),-1)
                        line = string.gsub(string.gsub(line, "\\./", "\\"), "/", "\\")
                        local files = split(line, "\\")
                        local file = files[#files]
                        local file2 = split(file, "%.") 
                        -- remove tex extension as it is default(we assume that inputs must have an extension of some type, else collisions may occur)
                        if file2[#file2] == "tex" then                                      
                            file2[#file2] = nil                 
                            if #file2 > 1 then
                                file2 = table.concat(file2, ".")
                            else
                                file2 = file2[#file2]
                            end
                            file = file2
                        end

                        TeXCache.Temp.Synctex.Input_ShortFiles[file] = {}
                        TeXCache.Temp.Synctex.Input_ShortFiles[file].idx = idx                  
                        TeXCache.Temp.Synctex.Input_ShortFiles[file].file = file
                        TeXCache.Temp.Synctex.Input_ShortFiles[file].min = 100000
                        TeXCache.Temp.Synctex.Input_ShortFiles[file].max = -1
                        TeXCache.Temp.Synctex.Input_Indexes[idx] = {}
                        TeXCache.Temp.Synctex.Input_Indexes[idx].idx = idx
                        TeXCache.Temp.Synctex.Input_Indexes[idx].file = file
                        TeXCache.Temp.Synctex.Input_Indexes[idx].min = 100000
                        TeXCache.Temp.Synctex.Input_Indexes[idx].max = -1                       

                    elseif (string.sub(line,1,1) == "{") then
                        curPage = string.sub(line,2,-1);
                    elseif #line > 1 then
                        local b = string.sub(line,1,1)
                        if b == "[" or b == "(" or b == "v" or b == "h" or b == "x" or b == "k" or b == "g" or b == "$" then                        
                            local idx = tonumber(split(string.sub(line,2,-1), ",")[1])
                            if not TeXCache.Temp.Synctex.Input_Indexes[idx] then TeXCache.Temp.Synctex.Input_Indexes[idx] = {} end
                            local lp = math.min(TeXCache.Temp.Synctex.Input_Indexes[idx].min or 100000, curPage)
                            local hp = math.max(TeXCache.Temp.Synctex.Input_Indexes[idx].max or -1, curPage)
                            local file = TeXCache.Temp.Synctex.Input_Indexes[idx].file
                            if file then                                 
                                TeXCache.Temp.Synctex.Input_Indexes[idx].min = lp
                                TeXCache.Temp.Synctex.Input_Indexes[idx].max = hp

                                TeXCache.Temp.Synctex.Input_ShortFiles[file].min = lp                                                   
                                TeXCache.Temp.Synctex.Input_ShortFiles[file].max = hp
                            end                         
                        end                                 
                    end
                end                     
                TeXCache.Temp.Synctex.Exists = true
            end     
            f:close()   
        end     


    end 

    function PreBeginDocument()
    end

    function TocWriteAux()
        -- Import aux file preambles headers
        for key, value in pairs(TeXCache.History.Cached) do                                         
            local s = ReadFile(TeXCache.Path..TeXCache.CacheDir.."Cached_"..key..'.aux', 1)
            if s then                   
                local loc = string.find(s, "\\@setckpt{")
                s = s:sub(1,loc-1)
                tex.print("\\makeatletter")
                tex.print(s)
                tex.print("\\makeatother")
                print("\n\n\n\r\n\\makeatletter\r\n"..s.."\r\n\\makeatother\r\n\n\n\n")
            end
        end     
    end

    --------------------- End Of Processing -------------------------
    function DoneProcessingTeX()


        persistence.store(TeXCache.Path..TeXCache.CacheDir..TeXCache.HistoryFilename, TeXCache.History);
        --print("\nTABLE----------------------------"); print(inspect(TeXCache.History)); print("\nTABLE----------------------------------");
        print("\n----Total Includes Cached = "..TeXCache.Count.."\n")

        if TeXCache.Backups then
            for key, value in pairs(TeXCache.Backups) do
                -- Create backup of pdf for later use, could optimize duplicate files away
                -- We must redirect the copy to a batch file asychronously because TeX people suck ass(too lame)
                --CopyFile(TeXCache.Path..TeXCache.JobName..".pdf", TeXCache.Path..TeXCache.CacheDir.."Cached_"..key..".pdf")
                if value == 1 then
                    os.execute('Start "copy" /min '..TeXCache.Path..'CopyFile.bat "'..TeXCache.Path..TeXCache.JobName..".pdf"..'" "'..TeXCache.Path..TeXCache.CacheDir.."Cached_"..key..'.pdf"')
                    os.execute('Start "copy" /min '..TeXCache.Path..'CopyFile.bat "'..TeXCache.Path..key..".aux"..'" "'..TeXCache.Path..TeXCache.CacheDir.."Cached_"..key..'.aux"')
                end             
            end
        end

        -- Another hoop to jump through because of the ignorant TeX people. syntex(busy) won't be renamed when using os.execute above for some ignorant reason      
        os.execute('Start "copy" /min '..string.gsub('CopyFile "'..TeXCache.Path..TeXCache.JobName..'.synctex(busy)" "'..TeXCache.Path..TeXCache.JobName..'.synctex"', "/", "\\"))      
    end


    -- Function callbacks must be above 
    luatexbase.add_to_callback("stop_run", DoneProcessingTeX, "pdfextract3")    

    -------------------------------------- Caching code






    function TeXCache.Initialize(JobName, path)
        -- To write aux files without getting strange write error one must set MIKTEX_ALLOWUNSAFEOUTPUTFILES=1 in environment for miktex.
        -- Get base_dir using dos if necessary
        if not path then local p = io.popen("echo %cd%") if p then path = p:read("*l"):trim("\\").."\\" p:close() end end
        if path == nil or path == "" then path = lfs.currentdir() end
        path = (path or ""):trim('"\' \\/').."/"
        JobName = JobName:trim('"\' /') or "temp"
        TeXCache.JobName = JobName
        TeXCache.Path = path
        print('Path = '..TeXCache.Path)

        StartProcessingTeX()
    end tex.print("\\directlua{TeXCache.Initialize('\\jobname', '\\BasePath')}")





    function TeXCache.Include(code)

        -- compare hash of included file with previously stored hash, if the same, then use cache
        -- could use filesize/date comparision for quicker tests
        local codefilename = TeXCache.Path..code..".tex"
        local fs = -1
        local hash = -1
        local curIdx = -1
        local lp = -1
        local hp = -1   

        if FileExists(codefilename) then
            fs = FileSize(codefilename)
            if  TeXCache.History.Cached[code] and TeXCache.History.Cached[code].FileSize == fs then
                hash = md5.sumhexa(ReadFile(codefilename))
                if TeXCache.History.Cached[code].Hash == hash then                   
                    local idx = -1
                    if TeXCache.Temp.Synctex.Input_ShortFiles[code] then
                        curIdx = TeXCache.Temp.Synctex.Input_ShortFiles[code].idx
                        lp = math.max(TeXCache.Temp.Synctex.Input_ShortFiles[code].min, TeXCache.History.Cached[code].LowPage)
                        hp = math.max(TeXCache.Temp.Synctex.Input_ShortFiles[code].max, TeXCache.History.Cached[code].HighPage)
                    else
                        lp = TeXCache.History.Cached[code].LowPage
                        hp = TeXCache.History.Cached[code].HighPage
                    end
                    if lp < 0 or hp < 0 or lp >= 99999 then
                        TeXCache.Temp.ValidCache = false
                    else        
                        TeXCache.Temp.ValidCache = true
                    end     
                else
                    TeXCache.Temp.ValidCache = false
                end
            else
                TeXCache.Temp.ValidCache = false
            end
        else
            TeXCache.Temp.ValidCache = false
        end     


        if TeXCache.Temp.ValidCache == false then
            tex.print("\\include{"..code.."}")
            if TeXCache.Backups == nil then
                TeXCache.Backups = {}
            end
            TeXCache.Backups[code] = 1
            -- Store Cached information         
            if FileExists(codefilename) then 
                fs = FileSize(codefilename) 
                hash = md5.sumhexa(ReadFile(codefilename))
            end
            if TeXCache.History.Cached[code] then 
                fs = fs
                hash = hash
                curIdx = curIdx
                lp = math.max(lp, TeXCache.History.Cached[code].LowPage or -1);
                hp = math.max(hp, TeXCache.History.Cached[code].HighPage or -1);
            end
            TeXCache.History.Cached[code] = {}                  
            TeXCache.History.Cached[code].FileSize = fs
            TeXCache.History.Cached[code].Hash = hash
            TeXCache.History.Cached[code].LowPage = lp
            TeXCache.History.Cached[code].HighPage = hp     
            return
        end

        for key, value in pairs(TeXCache.History.Cached) do         
            if code == key then
                print("\nUsing cached `"..code..".tex!\n")
                local filename = TeXCache.Path..TeXCache.CacheDir.."Cached_"..code          
                tex.print("\\includepdf[pages={"..lp.."-"..hp.."}]{"..filename.."}")

                -- Import aux file counters                             
                local s = ReadFile(TeXCache.Path..TeXCache.CacheDir.."Cached_"..key..'.aux')
                if s then               
                    local _, loc = string.find(s, "\\@setckpt{"..code.."}{")
                    s = s:sub(loc+1, -1)                
                    for i=#s, 1, -1 do
                        if s:sub(i,i) == "}" then
                            s = string.sub(s,1,i-1) 
                            break;
                        end
                    end

                    s = "\r\n\\makeatletter\r\n"..s.."\r\n\\makeatother\r\n"
                    tex.print(s)
                    print("\r\n\r\n\r\n"..s.."\r\n\r\n\r\n")
                end

                -- Store cached info for use on next run
                TeXCache.History.Cached[code].FileSize = fs
                TeXCache.History.Cached[code].Hash = hash
                TeXCache.History.Cached[code].LowPage = lp
                TeXCache.History.Cached[code].HighPage = hp                                     
                TeXCache.Count = TeXCache.Count + 1
                break
            end     
        end



    end


end -- __INCLUDE__

CopyFile.bat-用于异步复制文件

@echo off
@REM use asynchronously to copy a file after a process as exited(set timeout to be long enough for process to end).
@REM Call with Start "copy file" <path to this batch file> <source> <dest>

TIMEOUT 3 /NOBREAK
copy /B /Y %1 %2
exit

Clear.bat-清除垃圾文件以删除缓存(开始重置所有内容)

@echo off
del test.synctex(busy)
del test.synctex
del test.pdf
del test.toc
del test.log
del test.aux
del TeXCache\TeXCacheHistory.dat
del TeXCache\Cached_testinput.pdf
del TeXCache\Cached_testinput.aux

persist.lua-用于存储和检索 lua 表(可从 git hub 获取)

--t_original = {1, 2, ["a"] = "string", b = "test", {"subtable", [4] = 2}};
--persistence.store("storage.lua", t_original);
--t_restored = persistence.load("storage.lua");

local write, writeIndent, writers, refCount;

persistence =
{
    store = function (path, ...)
        local file, e = io.open(path, "w");
        if not file then
            return error(e);
        end
        local n = select("#", ...);
        -- Count references
        local objRefCount = {}; -- Stores reference that will be exported
        for i = 1, n do
            refCount(objRefCount, (select(i,...)));
        end;
        -- Export Objects with more than one ref and assign name
        -- First, create empty tables for each
        local objRefNames = {};
        local objRefIdx = 0;
        file:write("-- Persistent Data\n");
        file:write("local multiRefObjects = {\n");
        for obj, count in pairs(objRefCount) do
            if count > 1 then
                objRefIdx = objRefIdx + 1;
                objRefNames[obj] = objRefIdx;
                file:write("{};"); -- table objRefIdx
            end;
        end;
        file:write("\n} -- multiRefObjects\n");
        -- Then fill them (this requires all empty multiRefObjects to exist)
        for obj, idx in pairs(objRefNames) do
            for k, v in pairs(obj) do
                file:write("multiRefObjects["..idx.."][");
                write(file, k, 0, objRefNames);
                file:write("] = ");
                write(file, v, 0, objRefNames);
                file:write(";\n");
            end;
        end;
        -- Create the remaining objects
        for i = 1, n do
            file:write("local ".."obj"..i.." = ");
            write(file, (select(i,...)), 0, objRefNames);
            file:write("\n");
        end
        -- Return them
        if n > 0 then
            file:write("return obj1");
            for i = 2, n do
                file:write(" ,obj"..i);
            end;
            file:write("\n");
        else
            file:write("return\n");
        end;
        if type(path) == "string" then
            file:close();
        end;
    end;

    load = function (path)
        local f, e;
        if type(path) == "string" then
            f, e = loadfile(path);
        else
            f, e = path:read('*a')
        end
        if f then
            return f();
        else
            return nil, e;
        end;
    end;
}

-- Private methods

-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
    writers[type(item)](file, item, level, objRefNames);
end;

-- write indent
writeIndent = function (file, level)
    for i = 1, level do
        file:write("\t");
    end;
end;

-- recursively count references
refCount = function (objRefCount, item)
    -- only count reference types (tables)
    if type(item) == "table" then
        -- Increase ref count
        if objRefCount[item] then
            objRefCount[item] = objRefCount[item] + 1;
        else
            objRefCount[item] = 1;
            -- If first encounter, traverse
            for k, v in pairs(item) do
                refCount(objRefCount, k);
                refCount(objRefCount, v);
            end;
        end;
    end;
end;

-- Format items for the purpose of restoring
writers = {
    ["nil"] = function (file, item)
            file:write("nil");
        end;
    ["number"] = function (file, item)
            file:write(tostring(item));
        end;
    ["string"] = function (file, item)
            file:write(string.format("%q", item));
        end;
    ["boolean"] = function (file, item)
            if item then
                file:write("true");
            else
                file:write("false");
            end
        end;
    ["table"] = function (file, item, level, objRefNames)
            local refIdx = objRefNames[item];
            if refIdx then
                -- Table with multiple references
                file:write("multiRefObjects["..refIdx.."]");
            else
                -- Single use table
                file:write("{\n");
                for k, v in pairs(item) do
                    writeIndent(file, level+1);
                    file:write("[");
                    write(file, k, level+1, objRefNames);
                    file:write("] = ");
                    write(file, v, level+1, objRefNames);
                    file:write(";\n");
                end
                writeIndent(file, level);
                file:write("}");
            end;
        end;
    ["function"] = function (file, item)
            -- Does only work for "normal" functions, not those
            -- with upvalues or c functions
            local dInfo = debug.getinfo(item, "uS");
            if dInfo.nups > 0 then
                file:write("nil --[[functions with upvalue not supported]]");
            elseif dInfo.what ~= "Lua" then
                file:write("nil --[[non-lua function not supported]]");
            else
                local r, s = pcall(string.dump,item);
                if r then
                    file:write(string.format("loadstring(%q)", s));
                else
                    file:write("nil --[[function could not be dumped]]");
                end
            end
        end;
    ["thread"] = function (file, item)
            file:write("nil --[[thread]]\n");
        end;
    ["userdata"] = function (file, item)
            file:write("nil --[[userdata]]\n");
        end;
}

test.tex - 要测试的演示 tex 文件

\documentclass[12pt,oneside]{book}
%\batchmode

\directlua{
    require("debugger")()
}

\directlua{
    % Must be ran first, sets up paths
    __DEBUG = true
    local path = BasePath
    local p = io.popen('echo '..string.char(37)..'cd'..string.char(37)) if p and (path == nil or path == "") then path = p:read("*l") p:close() end
    if path == nil or path == "" then path = lfs.currentdir() end
    if path == nil or path == "" then else BasePath = path end
    path = string.gsub(path, string.char(92), "/");
    BasePath = string.gsub(BasePath, string.char(92), "/")
    tex.print(-1, string.char(92).."def"..string.char(92).."BasePath"..string.char(123)..BasePath..string.char(125))        
}

\directlua{
    dofile('TeXCache.lua')
}

\usepackage{luatex}
\usepackage{xcolor}
\usepackage{everypage}
\usepackage{afterpage}
\usepackage{pdfpages}
\usepackage{everyhook}
\usepackage{ifthen}
\usepackage{letltxmacro}
\usepackage{atbegshi}
\usepackage{lipsum}

\directlua{tex.enableprimitives('',tex.extraprimitives())}




\newcommand{\tableofcontentsEx}{\tableofcontents\directlua{TocWriteAux()}}
\newcommand{\cachedInput}[1]{\clearpage\directlua{TeXCache.Include("\luaescapestring{#1}"); }\clearpage}

\title{Sections and Chapters}
\author{Test Author}
\date{ }




\directlua{if PreBeginDocument then PreBeginDocument() end}
\begin{document}





\maketitle
\tableofcontentsEx
\clearpage


\lipsum

%This either includes or includespdf when cached.
\cachedInput{testinput}





slfkljasfasfjllasfjas;df

234214214892784
\chapter{HELP!!!}
asdfjhajsdfkljasjdf
a
asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


\end{document}

testinput.tex - 演示输入文本文件 - 可以是任何普通的 tex 文件

\chapter{AMAZING!}

{{{}}}{}{}{}{}{}{}
$$x =
y + z + z^2 + z^{311}
$$

\begin{tabular}{|c|c|}
  \hline
  % after \\: \hline or \cline{col1-col2} \cline{col3-col4} ...
  1 & 1 \\
  2 & 2 \\
  \hline



\end{tabular}


$$x =
y
$$

$z =
x
$

A\lipsum



\{

\textcolor{red}{
This is a test cache1
B\lipsum
\textcolor{green}{C\lipsum}
}



$$x =
y + z + z^2 + z^43434
$$
\lipsum
\lipsum
\lipsum























$z =
x
$




D\lipsum
test
xxxxxxxxxxxxxxxx

这些就是我们需要的所有文件。完整项目可以在http://www.filedropper.com/test_192

如果代码指定了行号,那么我就可以引用处理辅助文件的块了。无论如何,TeXCache.lua 中实际上只有两个部分处理辅助文件。

一种是尝试使用 TocWriteAux() 在前言中加载它,另一种是在 TeXCache.Include 函数中加载它。这发生在它说“-- 导入辅助文件计数器”的地方。

我尝试将 aux 文件拆分为 setckpt 之前的内容和之后的内容,因为简单地使用“\input”不起作用。

可以删除辅助代码并清空 TocWriteAux(),这样 lua 代码中就不会有任何辅助行为。我之所以包含它,只是为了在出现问题时可以对其进行修改。

再次强调,主要问题是当我在 lua 中“tex.print”辅助代码时,它不起作用,但当我复制和粘贴时它却起作用。为什么?我不知道!这就是我问的原因。请不要用一般性的答案来“帮助”,而是提供一个解决方案,使测试项目按预期工作(任何不能解决这个问题的答案都不是答案。它也应该在一般情况下有效(至少 95% 的测试用例)。)我已经不遗余力地提供了一个“MWE”,我希望任何试图提供帮助的人都能这样做,而不是试图获得“金星”或其他什么。

那么,预期的行为是什么?

  1. 目录始终是正确的。我意识到目录可能需要额外的编译才能正确更新,但这是目录设计的一般问题,而不是缓存机制的问题。

  2. 章节计数器始终是正确的。它们在第一次运行后是正确的,但是当缓存机制启动时,它们就错了,因为辅助文件未被使用。其他计数器等也应正确导入。辅助文件的全部目的是使这些东西保持同步,因此无论缓存设计如何,它都应该按应有的方式运行。

例如,经过几次编译测试后,“帮助”章节应该是 2,但实际是 1。可以直接插入辅助文件(复制并粘贴),然后就可以正常工作。因此,为什么 lua 代码(本质上做同样的事情,至少在我尝试拆分之前我尝试过)不起作用,这让我无法理解。

  1. lua 代码不应该是导入辅助信息的必要条件吗?有人告诉我这个,但我试过的方法不起作用。例如,在以下行之后

    tex.print("\includepdf[pages={"..lp.."-"..hp.."}]{"..filename.."}")

可以添加

tex.print("\\input{"..filename..".aux}")

并且它应该导入 aux 文件,但它什么也没做。就像直接将其添加到 tex 中一样。

无论如何,希望有人能花时间来实现这一点。能够缓存包含内容是一个很好的功能,对于运行缓慢的项目来说,可以大大节省速度。虽然与每页缓存相比,它有点太过精细,但总比没有好,避免了我们目前使用的“仅包含”问题。

我期望答案很简单,因为它只是做了 tex 已经做的事情……例如,包含辅助文件。但要么是我搞砸了,要么就是它没有正常工作(一个错误或由于 TeXCache 代码的一些奇怪问题)。

请注意,另一个错误是 synctex 文件未正确关闭。发生这种情况的原因似乎是另一个错误。它之所以发生只是因为我将 pdf 文件的复制异步委托给了操作系统。这是因为没有后 pdf 回调。如果有人试图通过 lua(stop_run 回调或其他方式)在“末尾”复制 pdf,则 pdf 不会完全完成并且无效。这些问题和解决方法是由于 TeX、LuaLatex 和 syntex 的拼凑性质造成的。如果添加了适当的回调层次结构以及其他一些内容,则可以创建一些非常好的功能。(例如,几乎透明的全页逐页缓存机制等)

无论如何,感谢您的帮助......

相关内容