如何在 minipages 中正确使用 \linegoal?

如何在 minipages 中正确使用 \linegoal?

我正在使用\linegoallinegoal 包中的函数来确定当前行的剩余空间。虽然这通常可以完美运行,但在 minipages 中似乎会失败。更具体地说,似乎\linegoalminipage 前面的任何空间都会减少 的值。这个问题似乎与这个问题中的问题有关(也许是同一个来源?):\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}

在此处输入图片描述

相关内容