如何使枚举项与左边距对齐?

如何使枚举项与左边距对齐?

我希望我的列表的顶层没有缩进,即具有与周围段落相同的左边距,并且有足够的空间容纳最宽的标签:

Paragraph text
 1. Item
 2. Item
 3. Item
 ...
10. Item
Paragraph text

我已经使用包对itemize和做了类似的事情:descriptionenumitem

\usepackage{enumitem}
\setlist[itemize]{leftmargin=*}
\setlist[description]{leftmargin=*}

但显然enumerate在确定标签宽度方面存在一些问题。它从一个不可靠的假设开始,将小标签推得太靠右,如果枚举足够大,则会超出左边距(我知道 10000 这个值太荒谬了,这只是为了让我的观点更明显):

\documentclass[twocolumn]{scrbook}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\newcommand{\justsometext}{Just enough text to make the line break so we get to see a second line.}

\begin{document}

\justsometext

\begin{enumerate}
\item \justsometext
\begin{enumerate}
\item Nested. \justsometext
\end{enumerate}
\item \justsometext
\addtocounter{enumi}{9997}
\item \justsometext
\end{enumerate}

\justsometext

\end{document}

包装enumitem给了我一半的路程,但它要求我标明最宽的标签

\usepackage{enumitem}
\setlist[enumerate]{leftmargin=*}

% ...

\begin{enumerate}[widest=10000]
% ...

但是,有没有办法可以enumerate自动检测最宽标签的宽度,而不必为每个单独的列表设置它?我觉得一定有办法,只是我无法从文档中找出方法enumitem……

(我尝试了paralist带有选项的包alwaysadjust,以及compactenum来自同一个包的包;两者都比我从中获得的更糟糕enumitem:首先假设一些标签宽度 - 从左边距推动“1。”和“2。” - 然后当 10000 个标签将其项目推到右边时完全破坏对齐......)

答案1

这是一种使用引用并因此至少进行两次编译的方法。它需要使用labelwidth而不是widest。首先,介绍一些背景知识...

itemize显然,提供解决方案的动机description是,前者 ( itemize) 使用单个元素(符号)来表示列表项,所有列表项的宽度都相同(默认情况下)。将此默认值覆盖为除单个元素(符号)以外的任何元素,将导致项目错位,或项目标签突出边距线:

\begin{itemize}
  \item An item
  \item[qwerty] An item
  \item An item
\end{itemize}

这是由于项目符号具有左对齐的特性。另一个原因是列表是“动态”排版的,甚至允许项目之间分页。因此,为了在开始时知道最宽的项目,enumerate必须在内存中读取/解析整个环境主体,然后确定最宽,然后排版 - 默认情况下并非如此。后者(description)有效,因为它使用右对齐方法来排版项目符号,并且默认情况下对标签和项目内容进行段落样式排版。

使用的解决方案enumerate需要设置以下内容enumitem列表的选项:

  • labelindent=0pt:具有齐平的左边距;
  • labelwidth=\widthof{\ref{last-item}}:这需要calc包裹测量列表中最后一项的标签设置\ref{last-item}位置的宽度;last-item
  • label=\arabic*.:标签将采用阿拉伯语,后跟句点.
  • itemindent=1em:标签与物品之间的间隔/空间;以及
  • leftmargin=!leftmargin:根据上面提供的参数自动计算应该是什么(这是 3.0 版的新功能enumitem)。

这是一个突出显示结果的简单示例:

\documentclass{article}
\usepackage{enumitem}% http://ctan.org/pkg/enumitem
\usepackage{calc}% http://ctan.org/pkg/calc
\begin{document}
\noindent Just enough text to make the line break so we get to see a second line.
\begin{enumerate}[labelindent=0pt,labelwidth=\widthof{\ref{last-item}},label=\arabic*.,itemindent=1em,leftmargin=!]
  \item An item
  \item An item
  \item An item \addtocounter{enumi}{9997}
  \item An item \label{last-item}
\end{enumerate}
Just enough text to make the line break so we get to see a second line.
\end{document}

动态对齐枚举标签

答案2

这是一个简单的技巧,但我不确定它是否适用\include

\def\maxenumi{0}
\def\saveenumi{0}

\makeatletter
\AtEndDocument{%
  \immediate\write\@auxout{%
    \string\gdef\string\maxenumi{\saveenumi}}}
\makeatother

\usepackage{enumitem}

\setlist[enumerate,1]{%
  leftmargin=*,
  widest=\maxenumi,
  after=\ifnum\value{enumi}>\saveenumi\xdef\saveenumi{\the\value{enumi}}\fi}

更新。请参阅下面 Werner 的回答,这个答案更好,但需要\label在最后一项中明确说明(另一方面,可以移至after)。

答案3

可以使用以下包完成enumerate

\documentclass{article}
\usepackage{enumerate}

\begin{document}
\noindent The quick brown fox jumps over the lazy dog.
\begin{enumerate}[ 1.]
\item First item.
\item Second item.
\setcounter{enumi}{9}
\item Tenth item.
\end{enumerate} 
\end{document}

但我不确定这个解决方案有多么强大。

相关内容