答案1
这个想法是将输入分成块,以便能够测量相关部分。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentEnvironment{dotfillenum}{+b}
{
\faizlotfy_dotfillenum:n { #1 }
}
{}
\seq_new:N \l__faizlotfy_dotfillenum_items_seq
\seq_new:N \l__faizlotfy_dotfillenum_row_seq
\dim_new:N \l__faizlotfy_dotfillenum_last_dim
\box_new:N \l__faizlotfy_dotfillenum_last_box
\cs_new_protected:Nn \faizlotfy_dotfillenum:n
{
% split the input at \item
\seq_set_split:Nnn \l__faizlotfy_dotfillenum_items_seq { \item } { #1 }
% remove the first (empty) item
\seq_pop_left:NN \l__faizlotfy_dotfillenum_items_seq \l_tmpa_tl
% start measuring the last elements
\dim_zero:N \l__faizlotfy_dotfillenum_last_dim
\seq_map_function:NN \l__faizlotfy_dotfillenum_items_seq \__faizlotfy_dotfillenum_measure:n
% typeset
\begin{enumerate}
\seq_map_function:NN \l__faizlotfy_dotfillenum_items_seq \__faizlotfy_dotfillenum_typeset:n
\end{enumerate}
}
\cs_new_protected:Nn \__faizlotfy_dotfillenum_measure:n
{
\seq_set_split:Nnn \l__faizlotfy_dotfillenum_row_seq { & } { #1 }
\hbox_set:Nn \l__faizlotfy_dotfillenum_last_box
{
\seq_item:Nn \l__faizlotfy_dotfillenum_row_seq { 2 }\unskip
}
\dim_set:Nn \l__faizlotfy_dotfillenum_last_dim
{
\dim_max:nn { \l__faizlotfy_dotfillenum_last_dim }
{ \box_wd:N \l__faizlotfy_dotfillenum_last_box }
}
}
\cs_new_protected:Nn \__faizlotfy_dotfillenum_typeset:n
{
\seq_set_split:Nnn \l__faizlotfy_dotfillenum_row_seq { & } { #1 }
\item
\seq_item:Nn \l__faizlotfy_dotfillenum_row_seq { 1 }
\dotfill
\makebox[\l__faizlotfy_dotfillenum_last_dim][l]
{
\seq_item:Nn \l__faizlotfy_dotfillenum_row_seq { 2 }
}
}
\ExplSyntaxOff
\begin{document}
words for context words for context words for context
words for context words for context words for context
words for context words for context words for context
\begin{dotfillenum}
\item $AB=CD$ & text;
\item $AB=CD$ & longer text;
\item $x$ & text.
\end{dotfillenum}
words for context words for context words for context
words for context words for context words for context
words for context words for context words for context
\begin{dotfillenum}
\item $AB=CD$ & text;
\item $AB=CD$ & longer text;
\item $x$ & text.
\end{dotfillenum}
\end{document}
第二个例子表明环境中的空行不被考虑。
答案2
创建一个对齐方式,使后面的文本\dotfill
出现在其自己的左对齐列中。棘手的部分是为列提供\dotfill
正确的宽度:
\halign to\hsize
不能使用,因为这是通过扩大\tabskip
列之间的距离来实现所需的宽度,并且填充的是空白处,而不是点。
相反,\multispan3
使用 语句,确保所有列合起来使用整个页面宽度 ( \hsize
),但 TeX 的对齐算法始终将超出的宽度放在最后一列。因此对齐前言将带有 的列作为\dotfill
最后一列,这将产生以下输出:
为了交换第二列和第三列,此对齐方式在 a 中排版\vbox
,然后由宏解包\swapcols
(类似的想法已被使用这里)。
\def\swapcols{\unskip\setbox0=\lastbox
\ifhbox0{\swapcols}\hbox{\unhbox0\swapcol}\fi}
\def\swapcol{\unskip\setbox2=\lastbox
\unskip\setbox1=\lastbox
\unskip\setbox0=\lastbox
\unskip
\box0\box2\box1}
\vbox{\halign{\hfil#\enspace&#\hfil&#\dotfill\cr
\multispan3{\hskip\hsize}\cr
1.&text;&$AB=CD$\cr
2.&longer text;&$AB=CD$\cr}\swapcols}
您还可以将此技术嵌入到组中。这样您只需要两列,但必须跳过enumerate
第一行,以免它贡献一个不需要的空项:\multispan2
\newif\ifskipped
\def\swapcols{\unskip\setbox0=\lastbox
\ifhbox0{\swapcols}\ifskipped\item\unhbox0\swapcol
\else\global\skippedtrue\fi\fi}
\def\swapcol{\unskip\setbox1=\lastbox
\unskip\setbox0=\lastbox
\unskip
\box1\box0}
\begin{enumerate}
\vbox{\halign{#\hfil&#\dotfill\cr
\multispan2{\hskip\hsize\hskip-\parindent}\cr %-\parindent compensates for the item number
text;&$AB=CD$\cr
longer text;&$AB=CD$\cr}\global\skippedfalse\swapcols}
\end{enumerate}
答案3
留给eqparbox
它将提取相同下的\eqmakebox[<tag>][<align>]{<stuff>}
所有元素的最大宽度。然后,您可以根据需要在内部添加元素(eft、enter/default 或ight)。<stuff>
<tag>
<align>
l
c
r
\documentclass{article}
\usepackage{eqparbox,lipsum}
\begin{document}
\lipsum[1][1-5]
\begin{enumerate}
\item $AB = C$ \dotfill \eqmakebox[RHS][l]{text;}
\item $D = EF$ \dotfill \eqmakebox[RHS][l]{longer text;}
\end{enumerate}
\lipsum[2]
\end{document}
宽度计算并存储在 中,因此对于任何 , 的.aux
最大宽度的任何变化都需要至少两次编译。这也适用于编译的第一次迭代(因为尚未确定最大宽度)。<stuff>
<tag>