\savepos=\savepos in lualatex. Why?

\savepos=\savepos in lualatex. Why?

我使用 LuaLaTeX。今天我决定尝试一下这个gridset包。令我惊讶的是,\usepackage{gridset}它产生了一个错误,告诉我该\savepos命令已经定义。

梅威瑟:

\documentclass{article}
% will be undefined in pdflatex, defines as itself in lualatex: 
\show\savepos
\begin{document}
yada yada
\end{document}

看起来 LuaLaTeX 定义了\savepos=\savepos。这很奇怪。

如果我先取消定义,\savepos然后我就可以加载gridsetLuaLaTeX,而且它似乎可以工作:

\let\savepos\relax
\usepackage{gridset}
% Then I can use \savepos in the document body.

这是一个“哎呀”,还是 LuaLaTex 中这种行为有原因?

编辑:回应 ShreevatsaR 的回答:

\documentclass{article}
% compile with lualatex
\begin{document}
yada yada\savepos{eek}\par
yada yada
\end{document}

结果:没有错误,但打印了“eek”,文件中没有任何内容aux。或者,使用pdfsavepos{eek}会产生错误。使用 TeXlive 2017,最新版。

EDIT2:接受的答案非常有用。我能够解决我最初提出问题的问题,并将解决方案作为后续答案发布在下面。

答案1

您的迫切问题

不幸的是,该gridset包定义了一个\savepos与 LuaTeX 原语同名的宏。如果您不需要 LuaTeX\savepos功能(至少不需要该名称),您可以执行以下操作:

\let\luatexPrimitiveSavepos=\savepos
\let\savepos=\relax
\usapackage{gridset}
\let\gridsetPackageSavepos=\savepos

类似于您在问题中提到的,然后使用\luatexPrimitiveSavepos\gridsetPackageSavepos,无论您需要哪一个,避免使用歧义的名称\savepos

也许可以将该包更改为在 LuaTeX 下自动执行一些合理的操作,或者(如果可行的话)只是使用不同的名称而不是\savepos


被问到的“为什么”

在 LuaTeX 引擎中,\savepos是一个基元。当 TeX 被要求处理\show一个基元时,它会将其显示为自身(例如,\show\def将显示\def=\def)。

此原语也存在于 pdfTeX 和 XeTeX 引擎中,名称为\pdfsavepos,但在 LuaTeX 程序中,他们删除了pdf前缀。这记录在LuaTeX 手册,第 2.1.4 节与 pdfTeX 1.40 的变化

由于位置跟踪在 dvi 模式下也可用,因此\savepos\lastxpos\lastypos命令现在取代了其pdf带前缀的原始命令。

还 (第 2.2 节 后端原语 \pdf *):

如果您还想要一些向后兼容性,您可以添加:
...
\let\pdfsavepos \savepos

(有很多这样的重命名原语。)


什么是\savepos(或\pdfsavepos

关于此原语的一些注释\savepos(在 LuaTeX 中)或\pdfsavepos(在 pdfTeX 和 XeTeX 中)。它起源于 pdfTeX,最好的文档是pdfTeX 手册

\pdflastxpos(只读整数)
此基元返回一个整数,表示 标记的最后一个点的绝对 x 坐标\pdfsavepos。单位是“缩放点数”(sp)。
\pdflastypos(只读整数)
与 完全类似\pdflastxpos,返回 y 坐标。...

\pdfsavepos (h, v, m)
此基元标记介质上当前的绝对 (x, y) 位置,参考点位于左下角。它只在页面输出期间(即页面最终组装时)处于活动状态。然后可以通过\pdflastxpos\pdflastypos基元检索位置坐标,并将其写入某个辅助文件。只有在当前坐标\shipout完成后才能使用这些坐标,因此通常需要运行两次 pdfTeX 才能使用这些基元。从 pdfTeX 1.40.0 开始,在 DVI 模式下运行时也可以使用此机制。

(正如@MarcelKrüger 在评论中指出的那样,(h, v, m)表示该原语可以在任何模式下使用:水平模式/垂直模式/数学模式。)

(由于这些原语来自 pdfTeX,它的扩展 XeTeX 和 LuaTeX 没有对它们进行非常广泛的记录,就像它们没有记录 TeX 原语一样:在XeTeX 手册解释很简短,在 LuaTeX 手册中完全省略了。

您可以按如下方式使用它们:

% compile with pdflatex or xelatex
\documentclass{article}
\begin{document}
\pdfpageheight=2.5in % Really short pages, just so that I can get a screenshot.

yada yada\pdfsavepos eek\par
yada yada

\newpage

The last saved position was x=\the\pdflastxpos, and y=\the\pdflastypos.
\end{document}

或者

% compile with lualatex
\documentclass{article}
\begin{document}
\pageheight=2.5in % Really short pages, just so that I can get a screenshot.

yada yada\savepos eek\par
yada yada

\newpage

The last saved position was x=\the\lastxpos, and y=\the\lastypos.
\end{document}

二者均能产生:

output

(这里,使用lualatex和进行编译时, xelatex“x”数字与使用 进行编译时略有不同pdflatex:原因正如@HenriMenke 指出的,是这两个默认加载 Latin Modern,而不是默认pdflatex加载cmr(Computer Modern)——并且这些字体的度量略有不同。)

另请参阅文章pdfTeX 的小秘密:跟踪位置作者:Hans Hagen地图 25(2000)第 74-78 页,似乎是关于这些原语的。

当然,这个原语(无论称为\pdfsavepos或)与包定义的宏完全无关。不幸的是,包选择的名称已被较新的引擎用作原语。\savepos\saveposgridset

答案2

我问这个问题时脑子里想的是某个特定的应用。为了方便大家,我现在将向大家展示我做了什么。类似的代码将出现在我的自定义文档类 (novel) 的下一次更新中,但以下代码将适用于任何使用 LuaLaTeX 的文档类。

问题性质:我只写小说,用于印刷。这意味着连续的文字,而不是方程式。有时,一章中会有场景中断。场景中断用空白行表示。

然而,良好的排版习惯不允许将空白行放在页面的最顶部或最底部,因为在那里可能不引人注意。此外,将其放在上面或下面只有一行看起来也不好。

因此,以下代码检测我的\scenebreak命令的页面位置。如果位置不正确,则会发出警告。

要查看其运行情况,请将代码加载到显示警告的编辑器(例如 TeXworks)中。将数字\yadayada从 43 变为 48。在 43 和 48 时,没有问题。在 44 和 47 时,系统会警告您\scenebreak太靠近页面顶部/底部。在 45 和 46 时,系统会警告您\scenebreak位于顶部/底部。

\documentclass[letterpaper]{article}
% Compile with LuaLaTeX.
\usepackage{fp}
\usepackage{xifthen}
\setlength\parskip{0pt}
\flushbottom
%
\makeatletter
% Assumes contast \baselineskip.
\def\@LinesPerPage{46} % Main text. Change to actual value for your document.
%
\newlength\TotalYpos
\def\InitialYpos{% top of text block
  \begingroup%
    \savepos%
    \protected@write\@auxout{}{%
      \protect\@TotalYpos{\noexpand\number\lastypos}%
    }%
  \endgroup%
}
%
\def\@TotalYpos#1{\setlength\TotalYpos{#1sp}}
%
\newcommand\scenebreak{%
  \leavevmode\getBreakpos{scenebreak}~\par
}
\newlength\CurrentBreakpos
\def\getBreakpos#1{%
  \begingroup%
    \savepos%
    \protected@write\@auxout{}{%
      \protect\@getBreakpos{\noexpand\number\lastypos}{\thepage}{#1}%
    }%
  \endgroup%
}
\gdef\@getBreakpos#1#2#3{} % nothing, when reading aux at beginning
\AtBeginDocument{
  \gdef\@getBreakpos#1#2#3{% numerical position sp, page, break type
    \setlength\CurrentBreakpos{#1sp}% measured up from very bottom of page.
    \FPsub{\@BreakLines}{\strip@pt\TotalYpos}{\strip@pt\CurrentBreakpos}
    \FPdiv{\@BreakLines}{\@BreakLines}{\strip@pt\baselineskip}%
    \FPround{\@BreakLines}{\@BreakLines}{0}% integer lines from text top
    \ifthenelse{\equal{#3}{scenebreak}}{%
      \xdef\thisline{\@BreakLines}%
      \ifnum\@BreakLines=1%
        \ClassWarning{any}{Replace \string\scenebreak\space at top of ^^J%
         page #2 with alternative.}%
      \fi%
      \ifnum\@BreakLines=\@LinesPerPage%
        \ClassWarning{any}{Replace \string\scenebreak\space at bottom of ^^J%
         page #2 with alternative.}%
      \fi%
    }{}%
    \FPsub{\@nearthebottom}{\@LinesPerPage}{1}%
    \ifnum\@BreakLines=2%
      \ClassWarning{any}{\string\ #3 too close to top of page #2.}%
    \fi%
    \ifnum\@BreakLines=\@nearthebottom%
      \ClassWarning{any}{\string\ #3 too close to bottom of page #2.}%
    \fi%
  }%
} % end \AtBeginDocument
\makeatother
%
% This is for the MWE, not part of the position code:
\newcount\yadacurrentcount
\newcount\yadaendcount
\newcommand\yadayada[1]{%
  \yadacurrentcount=1%
  \yadaendcount=#1%
  \loop%
    \makebox[\parindent][l]{\the\yadacurrentcount.}%
    Yada yada.\par
    \advance\yadacurrentcount 1%
  \ifnum\yadacurrentcount<\yadaendcount%
  \repeat%
}
%
\begin{document}
\InitialYpos%
\yadayada{43} % vary from 43 to 48 to see effect
\scenebreak
\yadayada{30}
\end{document}

答案3

我迟到了,但这里还有一个额外的解决方案:

Markus Kohm, author of the gridset package has an updated version, dated 2017, on his own website: https://komascript.de/gridset. This version correctly deals with LuaTeX.

However, that site contains two disclaimers:

Note: I do not longer recommend to use this package!

Note: You cannot find the current release on CTAN.

So, YMMV.

相关内容