0

In order to have a footer at each page that displays the current page number with the total number of pages (Eg.,4 of 12), I used lastpage package and placed the statement:

\rfoot{\thepage\ of \pageref{LastPage}}

just before the \begin{document} statement.

When I run lualatex doc-1.tex, I get the following warnings at the end.

LaTeX Warning: Reference `LastPage' on page 11 undefined on input line 209.

[11]

Package lastpage Warning: Rerun to get the references right on input line 210.


AED: lastpage setting LastPage

LaTeX Warning: Reference `LastPage' on page 12 undefined on input line 210.

[12] (/Users/amanda/ltx/s/build/store/upload/doc-1.aux)

LaTeX Warning: There were undefined references.


LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

This results in footer that looks something similar to:

4 of ??

and the generated document does not have the \tableofcontents. Re-running it resolves the issue.

Is there a way, I could avoid this in the first place? I do not want to rerun the command to get it right the second time (since there would be many different documents all being generated at the same time).

If it is helpful, I have shared the lualatex code that I run to generate the document.

    \documentclass[a4paper,12pt]{report}
\usepackage[english]{babel}
\usepackage{luacode}

\begin{luacode*}
local function json_parser()
        local lpeg = assert(require("lpeg"))
        local C, Cf, Cg, Ct, P, R, S, V =
            lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.V

        -- number parsing
        local digit    = R"09"
        local dot      = P"."
        local eE       = S"eE"
        local sign     = S"+-"^-1
        local mantissa = digit^1 * dot * digit^0 + dot * digit^1 + digit^1
        local exponent = (eE * sign * digit^1)^-1
        local real     = sign * mantissa * exponent / tonumber

        -- optional whitespace
        local ws = S" \t\n\r"^0

        -- match a literal string surrounded by whitespace
        local lit = function(str)
            return ws * P(str) * ws
        end

        -- match a literal string and synthesize an attribute
        local attr = function(str,attr)
            return ws * P(str) / function() return attr end * ws
        end

        -- JSON grammar
        local json = P{
            "object",

            value =
                V"null_value" +
                V"bool_value" +
                V"string_value" +
                V"real_value" +
                V"array" +
                V"object",

            null_value =
                attr("null", nil),

            bool_value =
                attr("true", true) + attr("false", false),

            string_value =
                ws * P'"' * C((P'\\"' + 1 - P'"')^0) * P'"' * ws,

            real_value =
                ws * real * ws,

            array =
                lit"[" * Ct((V"value" * lit","^-1)^0) * lit"]",

            member_pair =
                Cg(V"string_value" * lit":" * V"value") * lit","^-1,

            object =
                lit"{" * Cf(Ct"" * V"member_pair"^0, rawset) * lit"}"
        }

        return { parse = function(str) return assert(json:match(str)) end }
end

local socket = require("socket")
local json = json_parser()
local file = io.open("sample-true.json")
local start = socket.gettime()
tab = json.parse(file:read("*all"))
texio.write_nl("Time passed parsing JSON: " .. socket.gettime() - start .. " s\\string\n")
file:close()
\end{luacode*}

\begin{luacode}
local function isempty(s)
return s == nil or s == ''
end

function renderSections(tab)
    for i,k in ipairs(tab['tableOfContents']) do
        local sec_start = socket.gettime()
        tex.print ("\string\\chapter{" .. k.section.title .. "}")
        tex.print("section text here")
        for ii,kk in ipairs(k["subsection"]) do
            tex.print ("\string\\section{" .. kk.title .. "}")
            tex.print ("some text here")
            tex.print("\string\\newline")
            for iii, kkk in ipairs(kk["content"]) do
                if kkk['type'] == "text" then
                    if not isempty(kkk["line"]) then
                        tex.print(kkk["line"])
                        tex.print("\string\\newline")
                    end
                elseif kkk["type"] == "table" then
                    local column_count = 0
                    local row_count = 0
                    col_schema = ""
                    for _ in ipairs(kkk["columns"]) do 
                        column_count = column_count + 1 
                        col_schema = col_schema .. " |X"
                    end
                    col_schema = col_schema .. "|"
                    for _ in ipairs(kkk["columns"][1]["values"]) do row_count = row_count + 1 end
                    if not isempty(kkk.title) then
                        tex.print("\string\\textbf{" .. kkk.title .."}")
                        tex.print("\\\\[0.1in]")
                    end
                    tex.print("\string\\begin{tabularx}{\\linewidth}{"  .. col_schema ..  "}")
                    tex.print("\\hline")
                    for ci, c in ipairs(kkk["columns"]) do
                        local c_name = string.gsub(c.name, "&","\\&")
                        tex.print(c_name)
                        if ci < column_count then
                            tex.print(" & ")
                        end
                    end 
                    tex.print("\\\\")
                    tex.print("\\hline")
                    i = 1
                    while i <= row_count do
                        local c_c = 1
                        while c_c <= column_count do
                            local row_val = kkk["columns"][c_c]["values"][i]
                            row_val = string.gsub(row_val, "&", "\\&")
                            tex.print(row_val)
                            if c_c < column_count then
                                tex.print(" & ")
                            end
                            c_c = c_c + 1
                        end
                        tex.print("\\\\")
                        tex.print("\\hline")
                        i = i + 1
                    end
                    tex.print("\string\\end{tabularx}")
                    tex.print("\\\\[0.1in]")
                end
            end
        end
        texio.write_nl("Time passed rendering section: " .. socket.gettime() - sec_start .. " s\string\n")
    end
end
\end{luacode}

\title{\directlua{tex.print(tab['documentName'])}}
\author{\directlua{tex.print(tab['author'])}}
\usepackage{fancyhdr}
\usepackage{pgffor}
\usepackage{lastpage}
\usepackage{tabularx}
%\usepackage[extreme]{savetrees}
\usepackage[landscape, margin=1in]{geometry}
\usepackage[yyyymmdd,hhmmss]{datetime}
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,      
    urlcolor=cyan,
    pdftitle={MAC Report},
    bookmarks=true,
    pdfpagemode=FullScreen,
}
% https://en.wikibooks.org/wiki/LaTeX/Colors
\usepackage[svgnames]{xcolor}
\pagestyle{fancy}
\fancyhf{}


\lhead{\directlua{tex.print(tab['headerFooter']['header']['left'])}}
\rhead{\directlua{tex.print(tab['headerFooter']['header']['right'])}}
\lfoot{\directlua{tex.print(tab['headerFooter']['footer']['left'])}}
\rfoot{\thepage\ of \pageref{LastPage}}
\cfoot{}
\renewcommand*\contentsname{TABLE OF CONTENTS}


\begin{document}
\maketitle


\paragraph{Document Information}

\subparagraph{Document information is given in the table below}

\subparagraph{}
\begin{tabular}{|c| c| c|}
\hline
\textbf{S.No} & \textbf{Item} & \textbf{Information} \\
\hline
1 & Document ID & \directlua{tex.print(tab['documentId'])} \\
\hline
2 & Document Generated At & \directlua{tex.print(tab['documentGeneratedAt'])} \\
\hline  
3 & Document Generated By & \directlua{tex.print(tab['documentGeneratedBy'])} \\
\hline
4 & MAC Protocol ID & \directlua{tex.print(tab['macProtocolID'])} \\
\hline
\end{tabular}
%\newpage
%\textcolor{NavyBlue}{TABLE OF CONTENTS}
\tableofcontents
\directlua{renderSections(tab)}

\end{document}

Initial part of the document is static. Most part of the document is generated from renderSections function. I have also shared the json file named sample-true.json, in case you would want to reproduce it.

Amanda
  • 387
  • If you know in advance what ends up on which page, you can just generate an aux file, but I doubt that this is practical. – Henri Menke May 09 '19 at 10:32
  • @HenriMenke No, nothing in advance. – Amanda May 09 '19 at 10:36
  • 3
    Then it is not possible unless you invent time travel. – Henri Menke May 09 '19 at 10:43
  • @HenriMenke Is there an alternative to LastPage? If we could detect a page-break somehow, we could try to add a footer then maybe? – Amanda May 09 '19 at 11:03
  • 8
    The way that all references work, including LastPage and the table of contents, is that on every run through the document the data is written to the aux file. The aux file is read whenever the document is processed so on subsequent runs the data stored in the aux file is read in and can be used anywhere in the document. It is possible to write code that does not use the aux file but it will only be able to add "dynamic" content later in the document. For something like the number of the last page this is of no value because there are no pages after the last page. –  May 09 '19 at 11:18
  • 4
    If you know how many pages there are you can say, before the \begin{document}, something like this: \newlabel{LastPage}{{}{123}{}{}{}}, then the number of pages will be known. The effect would be the same as running the document twice, however. Even MS Word requires you to write all the text before it can tell you how many pages are there. – Phelype Oleinik May 09 '19 at 11:40
  • @Andrew Will it take the same time to compile the document the second time when compared with the first run? Does it recompile all the document again? If it does recompile everything again , is there a way to minimize the compile time for second run? – Amanda May 11 '19 at 12:58
  • 1
    If anything the second compilation will take a fraction more time as pages such as the table of contents or indexes are not and cannot be put together on the first run through. I am not aware of any way to reduce the compilation time. As far as LaTeX is concerned there is no difference between the first and subsequent compilations, except that there is more data in the aux, toc, ind, ... files –  May 11 '19 at 13:09
  • @Andrew Okay! Was going through https://tex.stackexchange.com/questions/8791/speeding-up-latex-compilation . on how to speed up latex compilation. Don't think this would make sense with lualatex – Amanda May 11 '19 at 20:55
  • I'm sure that you can optimise your documents in terms of the packages etc that you use. Unfortunately there are no profiling tools that I am aware of. –  May 11 '19 at 22:17
  • @Andrew Is there some way I can know if the second run is required? – Amanda May 13 '19 at 11:21
  • It is necessary if you have anything like \ref{..}, \cite{...}, an index, a table of contents etc. There will usually be warnings for anything that is "missing" in he log file. –  May 13 '19 at 11:59
  • Usually the .log is a good indicator of whether or not you need to rerun LaTeX. But you can always imagine pathological cases where either (1) reruns are not strictly necessary even though the .log says you should rerun or (2) the .log does not warn about a necessary rerun. See for example https://tex.stackexchange.com/q/479394/35864. That's why tools such as latexmk that take care of this are so sophisticated. – moewe May 18 '19 at 07:21

0 Answers0