根据引擎级别的迭代参数生成页面?

根据引擎级别的迭代参数生成页面?

暂时先记在这里,我想到的是:我使用的方法是在为什么 \vspace 在节标题之后有时会以离散步骤跳跃/捕捉?基本上就是让一个bash脚本调用pdflatexX 次,每次都使用一个参数的新值\mylength,并生成 X 个输出 PDF 文件。显然,每次pdflatex调用时,它都必须重新加载\documentclass,然后\usepackage重新加载,等等——总之,很耗时。

我在想 - 如果在 .tex 文档的某个点上我可以写类似这样的内容(伪代码),那就更好了:

...
blah blah. 

\newlength{\mylength}
\steplength{\mylength}{2.5pt}{20pt}{0.5pt} % pseudo
\generateParameterSequencePages{}          % pseudo

\begin{minipage}{\textwidth}
\textbf{Something here}
\vspace{\mylength}
\textit{Something else here}
\end{minipage}

Blah blah blah....

...因此当 tex 引擎遇到 时\generateParameterSequencePages,它基本上会“保存”当前页面的状态;创建一个新文件,,\jobname_pgY.pdf用当前页码( \jobname 文档中的 Y )编号;并且在这个新文件内,它会抛出 Z 次迭代(\steplength{\mylength}{startvalue}{endvalue}{step}将指定)\mylength当前页面中的页面,作为单独的页面。完成后,引擎退出 (不确定此时我是否希望引擎返回到 tex 原始 PDF)。

因此,我最终会得到一个新文件\jobname_pgY.pdf,其中包含 Z 页,显示参数的 Z 次迭代\mylength及其对原始\jobname.pdf文档中第 Y 页布局的影响。我可以想象这会比每次都bash调用脚本更快一些。pdflatex

使用当前的引擎是否可能synctex实现这样的事情?使用 会有什么不同吗?使用 怎么样luatex

非常感谢您的任何建议,
干杯!


编辑:另请参阅这个帖子以获得更详细的lualatex例子。

答案1

为什么不直接使用一个 PDF 文件来生成,\foreach这几乎是我在tikz 中的埃拉托斯特尼筛法制作动画:

\documentclass{article}
\usepackage{pgffor}
\begin{document}
\foreach \len in {2.5, 3.0, ..., 20.0}{%
    \newpage%
    \begin{minipage}{\textwidth}%
    \textbf{Something here}
    \vspace{\len pt}

    \textit{Something else here}
    \end{minipage}%
}%
\end{document}

答案2

我将在这里发布此内容,以免阻塞原始问题。

但基本上,这个问题背后的意图是调试长度对页面排版的影响......我现在已经对其进行了一些研究,并且可以提供部分答案:synctex“只是”为GUI编辑器建立了源.tex和输出.pdf之间的对应关系 - 但是,lualatex这已经有助于更好地理解事情了。

所以,我一直在研究lua-visual-debug.lua/.styLuaTEX 参考手册 (luatexref-t.pdf)\AtBeginShipout来自包阿特别格什输出例程和 \box255基本上,我想处理这样的情况:

\documentclass[12pt]{article}

\usepackage{lipsum}

\begin{document}

  \newlength{\mylength}

  \section{Lorem Ipsum}

    \lipsum[1-6]

  \setlength{\mylength}{5pt}
  \vspace*{\mylength}

  \section{Sed commodo}

    \lipsum[7-12]

\end{document}

在上面的例子中,我想看看不同的\mylengths 对页面排版的影响。问题是我们不知道第二部分最终会出现在哪一页(好吧,我已经排版过一次文件,所以我知道它会出现在第 2 页 - 但是,我们事先并不知道这一点)。但无论如何,latex 必须至少排版一次,直到该\mylength部分。

现在,据我(粗略)理解,\mylength超过此部分后,tex 引擎将继续添加页面元素,直到页面溢出。此时,我们可以利用\AtBeginShipout运行宏或 lua 脚本 - 显然有些事情可以在那里进行更改;但我还不确定要更改哪些内容或如何更改它们。

在下面的例子中,我使用了 lua 代码(其原始设置来自lua-visual-debug.lua)基本上遍历了所谓的中的所有节点AtBeginShipoutBox。运行时\AtBeginShipoutAtBeginShipoutBox本质上是\box256\box255而是nil

这告诉我输出例程可能尚未运行 - 而且很可能尚未生成 pdf 页面(并且终端日志确实显示了脚本输出,在 pdf 页面生成时输出的字符串之前[1][2]我猜)。

因此显然,应该有可能改变一些事情 - 但是,我尝试在例程tex.print("\\mylength=20pt ")中插入一个“黑客” \AtBeginShipout- 不幸的是,生成的 PDF 中完全没有任何变化。

然而,如果那里发生了变化;那么我可以想象以下解决方案:

  • 在 tex 文件中我们要检查的位置放置一个“标记”(例如\setlength本文第一个例子中的命令
  • 运行乳胶
  • 跑步\AtBeginShipout
    • 此页面上是否出现过标记?如果出现:
    • 保存页面上下文(开头的样式)
    • 设置\mylength为迭代的第一步
    • 暂时切换输出到另一个 pdf
    • 运行输出例程并输出单页
    • 从现在开始,不是将执行优先级返回给 latex!
    • 开始循环直到迭代的最后一步
    • 检索页面上下文
    • 更改\mylength至下一步
    • 运行输出例程并输出单页
    • (重复循环)

因此,这里有两个问题:

  • 我们可以改变类似\mylength在 ; 中运行的 lua 代码之类的东西吗,以便 latex 使用新的;\AtBeginShipout重新排版页面;\mylength
  • 是否有可能检索类似“页面上下文”(“样式”:页面排版开始时的字体、跳过等)的内容,保存它,然后再次检索已保存的版本,就像在 lua 代码中运行一样\AtBeginShipout

至于“页面上下文”,我会考虑\baselineskip在页面排版开始时的值,比如说和这样的值(这是由 luatex 提供的tex.baselineskip);但如果环境(如列表)有效(我不知道 luatex 是否允许检查这一点);大概,对于 luatex 提供的那些变量,以某种方式保存它们的值应该不是问题。但是tex.baselineskip在给定页面排版开始\AtBeginShipout\baselineskip;或者在页面末尾(如果你\setlength{\baselineskip}{...}在页面中间有一个)?

好吧,这就是我现在能得到的——以我对这个过程的有限理解,看起来做这样的事情是可能的,尽管我找不到确切的程序。所以如果知道这种方法是否从根本上是不可能的(至少对于当前版本的软件来说),那就太好了。此外,可能相关的是:在 LuaTeX 中并发交叉执行 Lua 和 TeX

无论如何,这里是上面的例子,添加了 lua 函数来迭代并打印出页面的节点列表到终端:

\documentclass[12pt]{article}

\usepackage{lipsum}
%\usepackage{everyshi} % use atbegshi instead
\usepackage{atbegshi}
\usepackage{ifluatex}

\ifluatex
\usepackage{luacode}
\begin{luacode*}
--~ module(...,package.seeall)
--~ module("...","package.seeall")

  -- running this \AtBeginShipout will typeset "test" (with the quotes) on start of every page other than first (regularly broken paragraph continues)
  function mytest()
    tex.sprint([["test"]]) -- typesets "test" (w/ quotations)
  end

  -- texlive/2011/texmf-dist/tex/context/base/node-ini.lua
  local function simplified(t)
    local r = { }
    for k, v in next, t do
      r[k] = string.gsub(v,"_","")
    end
    return r
  end

  local function table2string(t)
    local ret = ""
    for i,v in ipairs(t) do
      -- print(i,v)
      ret = ret .. "[" .. i .. "]= " .. tostring(v) .. "; "
    end
    return ret
  end

  function print_basic_nodedata()
    local rep = "\n"
    rep = rep .. " ## node.types: " .. table2string(node.types()) .. "\n" -- doesn't list whatsit?!
    rep = rep .. " ## node.whatsits: " .. table2string(node.whatsits()) .. "\n"
    rep = rep .. " ## tex: " .. tostring(tex) .. " / " .. table2string(tex) .. "\n" -- empty at this point
    return rep
  end

  print(print_basic_nodedata()) -- once here, as well

  -- texlive/2011/texmf-dist/tex/context/base/node-ini.lua
  function nodes_fields(n)
    local id = n.id
    --local node_fields   = node.fields
    --local nodecodes     = node.types() -- simplified(node.types())
    --local whatsit_node  = nodecodes.whatsit -- whatsit not listed in node.types(); go explicitly
    --print(id .. " / " .. table2string(nodecodes) ..  " / " .. tostring(whatsit_node))
    local whatsit_node = 8

    if id == whatsit_node then
        return node.fields(id,n.subtype) --node_fields
    else
        local t = node.fields(id)
        return t
    end
  end

  function node_field_vals(n)
    local id = n.id
    local myfields = nodes_fields(n)
    local rep = ""
    local whatsit_node = 8
    local whatsit_node_subtypes = node.whatsits()
    for k, v in next, myfields do
      if ((k>0) and not(v=="head")) then -- k=0 next; k=-1 prev; k=12 head; avoid those
        local vv = ""
        if (v == "subtype") then
          if (n.id == whatsit_node) then
            vv = " (" .. tostring(whatsit_node_subtypes[n.subtype]) .. ")"
          end
        end
        rep = rep .. ".[" .. k .. "/" .. v .. "]= " .. tostring(n[v]) .. vv .. "; "
      end
    end

    if (n.id == whatsit_node) then
      if (n.subtype == 1) then -- 1: "write"
        rep = rep .. table2string(n.data[1])
      end
    end

    return rep .. "\n"
  end

  level = 0

  -- texlive/2011/texmf-dist/tex/luatex/lua-visual-debug/lua-visual-debug.lua
  function show_page_elements(parent)
    local head = parent.list
    level = level + 1
    print("") -- just a newline
    while head do
      local spacer = ""
      for i=1,level,1 do
        spacer = spacer .. " "
      end
      print(level .. spacer .. ": " .. tostring(head) .. "/" .. head.id)
      --texio.write("term and log", "\nsomething\n" )
      -- below print is for more verbose information:
--~       print (" " .. spacer .. ": " .. node_field_vals(head) )
      if head.id == 0 or head.id == 1 then -- hbox / vbox
        show_page_elements(head)
      end
      head = head.next
    end
    level = level - 1
    return true
  end

  function start_inspect_page()
    print("")
    print("Start inspect page")
    print("tex.output: " .. tex.output) -- shows "{\let \par \@@par \ifnum \outputpenalty <-\@M \@specialoutput ..."
    print("tex.box[255]: " .. tostring(tex.box[255])) -- nil here
    print("tex.box[256]: " .. tostring(tex.box[256]))
    print("tex.box[AtBeginShipoutBox]: " .. tostring(tex.box["AtBeginShipoutBox"])) -- same as 256; as it says in log file: "\AtBeginShipoutBox=\box256"
--~     print(print_basic_nodedata()) -- same as the first time
    show_page_elements(tex.box["AtBeginShipoutBox"])
    -- perform hack
    tex.print("\\mylength=20pt ")
    -- tex.tprint({-2,\\mylength=20pt}) -- gets typeset
  end
\end{luacode*}

\AtBeginShipout {%
%\directlua{mytest()}
\directlua{start_inspect_page()}
}
\else
\fi

\begin{document}

\newlength{\mylength}

\section{Lorem Ipsum}
% \directlua{mytest()}

\showboxdepth=100
\showboxbreadth=100
% \showbox255       % > \box255=void here
% \showbox256       % > \box256=void here

\lipsum[1-6]

\setlength{\mylength}{5pt}
\vspace*{\mylength}

\section{Sed commodo}

\lipsum[7-12]

\end{document}

编辑:刚刚对进行了一些实验tex.set;似乎有些东西可以在中改变\AtBeginShipout,并且仍然对生成的 PDF 产生影响,例如voffset

-- tex.voffset = "-2cm" -- works!
-- tex.set ('global', 'voffset', '2cm') --works!
-- tex.set ('global', '\\voffset', '2cm') -- nowork
tex.set ('voffset', '-2cm') --works!

但是,tex.parindent在手册的同一页“4.13.1.2 尺寸参数”中列出,但是tex.voffset,在 PDF 上看到变化效果的唯一方法是global

--tex.set ('parindent', '2cm') -- nowork
tex.set ('global', 'parindent', '2cm') -- work

这样做的好处是,它显示了单词的换行方式不同,我想这“证明”我们可以在这里更改内容 - 并且 latex 会排版包含更改。这是个好消息。请注意tex.baselineskip不同之处:

-- tex.set ('baselineskip', '2cm') -- "There should have been a lua <node> here, not an object with type string!:"
-- tex.set ('\baselineskip', '20cm') -- pass, nowork
-- tex.set ('\\baselineskip', '20cm') -- pass, nowork

...并且手册还指出:“4.13.1.4 ... glue 参数接受并返回代表 glue_spec 节点的用户数据对象

但是,我仍然找不到改变的方法\mylengthtex.set所以这仍然是问题的一部分......

相关内容