使用一次编译来测量 \hskip 的长度

使用一次编译来测量 \hskip 的长度

我正在尝试测量一个的宽度\hskip。我尝试过类似

\ExplSyntaxOn
a
\skip_horizontal:N 10pt plus 1fill
\box_set_to_last:N \l_tmpa_box
b\par

\the\box_wd:N \l_tmpa_box
\ExplSyntaxOff

\l_tmpa_box宽度似乎为零。我以为\hskip一旦排版完成,它就会变成一个框,但也许我误解了什么。

无论如何,我知道如何使用\tikzmark两次编译来测量宽度。但是,我想知道是否可以在一次编译中直接完成。

答案1

该函数\box_set_to_last:N本质上是 TeX 原语\lastbox,并且调用如下

\box_set_to_last:N \l_tmpa_box

是相同的

\setbox\l_tmpa_box=\lastbox

TeXbook 对此是这样说的:

上表底部的行指的是\lastbox,这是之前没有提到过的一个基本操作。如果当前水平列表或垂直列表的最后一项是 hbox 或 vbox,则将其从列表中移除并变为\lastbox;否则 \lastbox为空。此操作在内部垂直模式、水平模式和受限水平模式下允许,但您不能使用它在垂直模式下从当前页面中获取框。在数学模式下, \lastbox始终为空。在段落开头,' {\setbox0=\lastbox}' 会删除缩进框。

因此您的尝试失败了,因为当前水平列表中的最后一项是跳过。

然而,

a\setbox0=\lastbox\hskip 10pt plus 1fill

将导致\box0宽度为零;更准确地说,它将为空,因为最后一项不是 hbox 或 vbox,而是字符。

不能检测段落被吸收时的最终跳过量,因为拉伸或收缩发生在段落被分成行时的后期阶段。

答案2

如果您事先知道该行右侧包含什么,那么您可以执行以下操作。

塔托包定义了一个命令\tabto,该命令会跳转到一行中的特定位置,以及一个\CurrentLineWidth包含调用该命令时行宽的长度。此外,\tabto还将上次调用的位置存储在一个长度中\TabPrevPos。因此,如在https://tex.stackexchange.com/a/541683/89417(由包作者回答),您可以“跳转”到当前宽度(这不会导致位置发生变化),然后执行\hskip,然后通过从线宽中减去右侧和第一个位置的宽度来计算跳过的宽度。此计算仅需要一次编译。

梅威瑟:

\documentclass{article}
\usepackage{showframe}
\usepackage{calc}
\usepackage{tabto}

\newlength{\hskiplen}
\newlength{\firstpos}
\newlength{\secondpos}
\newsavebox{\rhs}
\begin{document}
\sbox{\rhs}{xyz}
abc\hskip10pt plus 1fill xyz

abc\tabto{\CurrentLineWidth}\hskip10pt plus 1fill\setlength{\firstpos}{\TabPrevPos}\setlength{\secondpos}{\linewidth-\wd\rhs-\TabPrevPos}\usebox{\rhs}

first position: \the\firstpos

second position: \the\secondpos

\setlength{\hskiplen}{\secondpos-\firstpos}length of hskip: \the\hskiplen

width of rhs: \the\wd\rhs
\end{document}

结果:

在此处输入图片描述

请注意,这实际上绕过了原始问题,因为您不是在测量 hskip 本身,而是测量行中的所有其他元素。实际上很难测量使用\hskip填充创建的框,因为宽度取决于行的其余部分,因此在实际命令之后该框尚不可用(我认为……)。您可以尝试 LuaLaTeX 是否可以提供有关完整框列表的更多信息,请参阅https://www.overleaf.com/learn/latex/Articles/Pandora%E2%80%99s_%5Chbox%3A_Using_LuaTeX_to_Lift_the_Lid_of_TeX_Boxes以获得一些指点。

相关内容