我正在使用\linegoal
linegoal 包中的函数来确定当前行的剩余空间。虽然这通常可以完美运行,但在 minipages 中似乎会失败。更具体地说,似乎\linegoal
minipage 前面的任何空间都会减少 的值。这个问题似乎与这个问题中的问题有关(也许是同一个来源?):\linegoal:它在双列文档的第二列中的使用无法正常工作
然而,这个问题的答案似乎并不适用于小页面。
为了使问题更加具体:我期望在行首\linegoal
等于\linewidth
。以下示例表明,在不是从页面最左侧开始的 minipage 中,情况并非如此:
\documentclass{article}
\usepackage{parskip}
\usepackage{linegoal}
\begin{document}
Linegoal works correctly in minipage starting on the left:
\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\rule{\linegoal}{1pt}
\end{minipage}
Linegoal is reduced by space before minipage:
\hspace{50pt}\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\rule{\linegoal}{1pt}
\end{minipage}
\end{document}
此示例产生以下输出:
是我使用不当还是这是一个错误\linegoal
?有没有办法解决这个问题,以便在 minipages 中获得正确的测量结果(也许使用另一个包而不是 linegoal)?
答案1
我相信 linegoal 使用\pdfsavepos
与整个页面上的位置相关的位置,并尝试根据该位置计算线上的位置。
我建议使用带有奇怪构造的 tabto.sty
\tabto{\CurrentLineWidth}\rule{\dimexpr\linewidth-\TabPrevPos\relax}{1pt}
这看起来很傻,但是\tabto
有测量迄今为止的行的效果;并且通过制表到相同位置,没有水平间距,并且(相同)位置保存为\TabPrevPos
。
制表符之前的内容排版时未拉伸,这与 \linegoal 的工作方式不同。这是好坏参半。坏处(也是丑陋之处)在于制表符两侧的文本可能拉伸不均匀,看起来很糟糕。好处在于制表符位置稳定 - 不会尝试记录一次运行的位置并在下一次运行中使用它,这可能导致 \linegoal 陷入无休止的调整循环。
抱歉,没有简单的方法可以将其放入任何旧的长度参数中。在测试的扩展中,它不仅修复了偏移量 minipage,而且在与前面的文本共享一行方面做得更好。
\documentclass{article}
\usepackage{parskip}
\usepackage{linegoal}
\usepackage{tabto}
\begin{document}
Linegoal works correctly in minipage starting on the left:
\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\rule{\linegoal}{1pt} and after text \rule{\linegoal}{1pt}
\end{minipage}
\bigskip
Linegoal is reduced by space before minipage:
\hspace{50pt}\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\rule{\linegoal}{1pt} and after text \rule{\linegoal}{1pt}
\end{minipage}
\bigskip
Try with tabto
\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\tabto{\CurrentLineWidth}\rule{\dimexpr\linewidth-\TabPrevPos\relax}{1pt}
and after text \tabto{\CurrentLineWidth}\rule{\dimexpr\linewidth-\TabPrevPos\relax}{1pt}
\end{minipage}
\bigskip
tabto with space before minipage:
\hspace{50pt}\begin{minipage}{100pt}
\rule{\linewidth}{1pt}
\tabto{\CurrentLineWidth}\rule{\dimexpr\linewidth-\TabPrevPos\relax}{1pt}
and after text \tabto{\CurrentLineWidth}\rule{\dimexpr\linewidth-\TabPrevPos\relax}{1pt}
\end{minipage}
\end{document}
答案2
另一种方法是zref-abspos
直接使用包和 LaTeX2e 段落钩子para/begin
(在 LaTeX2e 2021-06-01 或更新版本中提供)。然后,将行目标计算为两个位置的 x 坐标之间的差值zref
,一个位置在行的开始处,一个位置在当前位置。
用法:
\markLineStart{<name>}
在段落之前或段落开头添加。
目前,它通过在下一个段落开头执行代码来工作,因此如果非平凡则不会给出正确的结果\parshape
。理想情况下,代码应该在行的开头执行,而不是在段落的开头执行。- 在某行的中间(不一定是 之后的下一段
\markLineStart{<name>}
),使用来存储 中\getLineGoal{<name>}
的当前行目标。 是一个以 开头的宏,因此它的作用类似于维度。内部计算假定当前行从与 之后的第一段相同的 x 坐标开始。<name>
\xlinegoal
\xlinegoal
\dimexpr
\markLineStart{<name>}
- 用于存储除 以外的
\getLineGoal[\cmd]{<name>}
线路目标。\cmd
\xlinegoal
\documentclass{article}
\usepackage{lipsum}
\usepackage{zref-abspos}
\makeatletter
\IfFormatAtLeastTF{2021-06-01}{% to use hook "para/begin"
\newcounter{xlinegoal}
\newcommand{\markLineStart}[1]{%
\AddToHookNext{para/begin}{\zsaveposx{xlinegoal@#1}}%
\ignorespaces
}
\newcommand{\getLineGoal}[2][\xlinegoal]{%
\stepcounter{xlinegoal}%
\zsaveposx{xlinegoal@#2@\the\c@xlinegoal}%
\edef#1{\noexpand\dimexpr\the\dimexpr\linewidth+\zposx{xlinegoal@#2}sp-\zposx{xlinegoal@#2@\the\c@xlinegoal}sp\relax}%
\ignorespaces
}
}{\PackageError{xlinegoal}{LaTeX2e 2021-06-01 or newer is needed}{}}
\makeatother
% test helpers
\newcounter{testXLG}
\def\testXLineGoal{%
\stepcounter{testXLG}
X\hfill X
\markLineStart{\arabic{testXLG}}
text\nobreakspace
\getLineGoal{\arabic{testXLG}}
\rlap{\the\xlinegoal}\rule{\xlinegoal}{.4pt}%
}
\begin{document}
X\hfill X
\markLineStart{normal para}
some text \getLineGoal{normal para}\rule{\xlinegoal}{.4pt}
\bigskip
\begin{minipage}{100pt}
\lipsum[1][1-3]
\testXLineGoal
\end{minipage}
\qquad\begin{minipage}{100pt}
\lipsum[1][1-3]
\testXLineGoal
\end{minipage}%
\qquad\begin{minipage}{100pt}
\lipsum[1][1-3]
\testXLineGoal
\end{minipage}
\end{document}