I would like to create to create list with dot leaders.Each entry into the list essentially contains four parts: a number, a description, dot leaders and lastly another number. I want it to look like the following: .
I have looked at various examples on this forum but most of the examples do not give me exactly what I want-the most common problem is that when the description is long it starts from extreme left of the next line. The list I am trying to generate is very similar to a table of contents.
[Tex/LaTex] list with dot leaders
leaderslists
Related Solutions
Here is another answer, now complete. It has the following features:
It uses
pgfkeys
.It is almost completely syntax-compatible with the normal
{itemize}
environment. The only change is that I had to make\item
take key-value optional arguments, so that what used to be the sole optional argument is now calledtag=<something>
; this causes<something>
to be the "bullet" for the item, as before.
Edit: At Yossi's suggestion, I've replaced the modified environment with a "filter" command\onlyitems
that you can use like this:\begin{environment}\onlyitems[inclusion options]\ItemListMacro...
. (If you don't use a macro, of course the items must go in braces.)You pass key-value options to
\begin{itemize}
specifying your selection. You can say eitherinclude = {<list>}
orexclude = {<list>}
, where<list>
is a comma-separated list of numbers and text. The numbers can be given in rangesa,...,b
like in\foreach
. The text can be anything thatpgfkeys
thinks is a good name for a key. You can also sayall
ornone
; the default isall
, so with no options at all, this behaves just likeitemize
usually does.The order of these options is somewhat important: alternating
include
andexclude
specifications will do what you expect, unless you expect id's and numbers to be treated equally. If you ask both to include and exclude an\item
that happens to match both a number and an id, the id wins. Theall
andnone
options are "weak": they can be given anywhere, do not interact with the others, and are overridden by any explicit specification.Each
\item
takes an optional argument that can have the keystag = <bullet>
as described above, orid = <label>
, where<label>
is something you mightinclude
orexclude
. The\item
s are also secretly enumerated as they go (this enumeration does not depend on what is included; i.e. it depends only on how many\item
s are in the TeX file itself), and each one is matched against the selection criteria first by number, and then by id. You can even give multiple id's, or use the same id for multiple items, with the expected behavior.The exclusion of items is compatible with nested
itemize
environments. Selection criteria do not interact; enumerations do not interact. Anything whatsoever can be in an\item
and this thing will still work. I would have had this up six hours ago if it weren't for that.
And here it is:
\documentclass{article}
\usepackage{pgfkeys,pgffor}
% A huge list of pgfkeys to be set up.
\pgfkeys{
/onlyitems/.is family, /onlyitems,
% Utility keys
utility/store tag/.store in = \itemOptions,
utility/store bool/.store in = \itemIf,
utility/process true/.style = {process/#1 = \iftrue},
utility/process false/.style = {process/#1 = \iffalse},%\fi
utility/set store bool/.style 2 args = {#1/.style = {utility/store bool = #2}},
utility/set select style/.style 2 args = {utility/set store bool = {select/#1}{#2}},
utility/verdict/.style = {},
utility/add to reset/.style = {
reset/.prefix style = {select/#1/.style = {select/.unknown}}
},
utility/current key/.estore in = \itemKey,
% Nothing in the process family is ever set, so any selection option is set to store a boolean
process/.unknown/.style = {
utility/current key = \pgfkeyscurrentname,
select/\itemKey/.style = {
utility/set store bool = {utility/verdict}{#1}
},
utility/add to reset/.expand once = \itemKey
},
% For clearing the list of selected items (to support nested {itemize})
reset/.style = {},
reset/reset/.style = {reset/.style = {reset/reset, default}},
reset/reset,
% Here are the options you can actually pass. These go to the {itemize}...
include/.style = {utility/process true/.list = {#1}},
exclude/.style = {utility/process false/.list = {#1}},
all/.style = {utility/set select style = {.unknown}{\iftrue}},
none/.style = {utility/set select style = {.unknown}{\iffalse}},%\fi
default/.style = {all},
% ...and these to the \item's
tag/.style = {utility/store tag = {[#1]}},
id/.style = {select/#1},
}
% Like tikzset, it sets a default key path
\newcommand\onlyitemsset[1]{\pgfkeys{/onlyitems, #1}}
\let\itemLaTeX=\item
% Have to use a \newcount because (ugh) the LaTeX \setcounter is a global assignment
\newcount\itemsSoFar
\renewcommand\item[1][]{%
% The \egroup closes off any \vbox'es from the previously ignored \item.
% The conditional \bgroup cancels it out when there aren't any.
\itemIf\bgroup\fi\egroup
\let\itemIf=\iffalse%\fi
\advance\itemsSoFar by 1 %
\onlyitemsset{utility/store tag = {}, utility/verdict/.style = {}, select/\the\itemsSoFar, #1, utility/verdict}%
\itemIf
\def\next{\expandafter\itemLaTeX\itemOptions}%
\else
% The vbox is set and then discarded, effectively ignoring an entire \item.
% This inner \itemLaTeX is necessary to avoid a glitch when we ignore the first \item of an itemize that itself contains a nested \itemize. Don't ask, I don't know.
\def\next{\setbox0=\vbox\bgroup\itemLaTeX}%
\fi
\next
}
% \let\itemizeLaTeX=\itemize
% \let\enditemizeLaTeX=\enditemize
% \renewcommand\itemize[1][]{%
% \let\itemIf=\iftrue
% \itemsSoFar = 0 %
% % We have to reset here so that the selections from an outer itemize don't conflict with an inner one.
% \onlyitemsset{reset, #1}%
% \itemizeLaTeX
% }
% \renewcommand\enditemize{%
% % This closes off the last \vbox
% \itemIf\bgroup\fi\egroup\enditemizeLaTeX
% }
\newcommand\onlyitems[2][]{%
\let\itemIf=\iftrue
\itemsSoFar = 0 %
% We have to reset here so that the selections from an outer itemize don't conflict with an inner one.
\onlyitemsset{reset, #1}%
#2%
% This closes off the last \vbox
\itemIf\bgroup\fi\egroup
}
\begin{document}
\newcommand{\mylist}{
\item First item
\item[id=banana] Second item, id=banana
\item Third item, with a nested itemize
\begin{itemize}\onlyitems
\item Nested one
\item Nested two
\item Nested three
\end{itemize}
\item[id=banana, id=papaya] Fourth item, id=banana and id=papaya
}
\noindent
All:
\begin{itemize}\onlyitems
\mylist
\end{itemize}
\noindent
Excluding 1,2,3. Note that there is no interference with the inner itemize.
\begin{itemize}\onlyitems[exclude = {1,2,3}]
\mylist
\end{itemize}
\noindent
With 2,\dots,4 excluded; again no interference.
\begin{itemize}\onlyitems[exclude = {2,...,4}]
\mylist
\end{itemize}
\noindent
With id=banana excluded:
\begin{itemize}\onlyitems[exclude = banana]
\mylist
\end{itemize}
\noindent
With 1, id=papaya excluded:
\begin{itemize}\onlyitems[exclude = {1, papaya}]
\mylist
\end{itemize}
\noindent
With none, then id=banana included, then 4 excluded. Note that the label has precedence over the number.
\begin{itemize}\onlyitems[none, include = banana, exclude = 4]
\mylist
\end{itemize}
\end{document}
The non-pgfkeys
part is really sort of straightforward: the keys somehow determine a boolean \itemIf
that, in turn, switches between placing a real \item
(saved as \itemLaTeX
) and saving the next "\item
" in a \vbox
and throwing it away. There's some trickery with braces to make that work, but it's nothing special.
The pgfkeys
block is pretty elaborate, though. The basic principle of its operation is:
I want, ultimately, for each
\item
to process its number (saved in\itemsSoFar
) and its id as keys, and these keys should have been set up previously (in the options to\begin{itemize}
) to appropriately switch\itemIf
. Correspondingly, I need that numbers and id's that were not set to be handled according (via a.unknown
handler) to the default action (all
ornone
, basically). This part is contained in theselect
key subtree.The way that
\begin{itemize}
sets up these keys is by means of another.unknown
handler. This one is contained in theprocess
key subtree, and is in fact the sole inhabitant of that subtree: any key that gets called in that path is unknown and subject to this handler. This handler defines keys in theselect
key subtree, soprocess
remains vacant. This makes it possible to put the same id or number ininclude
andexclude
specifications repeatedly.However, I can't just have each id or number key directly alter
\itemIf
, because I need them to override each other and also the unknown id's and numbers. It wouldn't do if, for example, I wrote\item[id = label]
in the third item, and it happened that 3 were included and label were unknown but processed second, so that in fact the item would be excluded despite its only specified characteristic being explicitly included. So I need to delay the decision until all the characteristics are processed.The way this delay is implemented is by having each id and number key put its vote into a
verdict
key that is executed last. The.unknown
handled keys still modify\itemIf
directly, but thenverdict
, if it was set, does whatever was last put in it, overruling the default if any explicit choice was triggered.In order to support nested
itemize
environments, I need to be able to unset the selection criteria. Alas,pgfkeys
has no way of unsetting keys. Fortunately, I don't need that: I just need that any keys that were previously set be redefined to act just like the.unknown
handler (this is basically unsetting the key, actually). So in addition to telling a newly-defined id or number key to set up theverdict
key, theprocess/.unknown
handler also attaches a piece of code to thereset
key that tells it to undo the other thing. Thenreset
is called at the beginning of everyitemize
.The whole operation is basically a chain of
.style
handlers. I never store a value (okay, I do it once to expand\pgfkeyscurrentname
) and I never set a.code
directly. Every key, when executed, just expands to a few more keys, the end result of which is (finally) to set\itemIf
. If you didn't know already,pgfkeys
is not so much a key-value package as an elaborate finite-state machine specification language that also happens to contain a much better reimplementation of TeX's macro language than LaTeX. The fact that it has a key-value syntax is pretty much incidental.
Simply change the descripton
environment for an enumerate
environment:
\documentclass[12pt, letter]{article}
\newenvironment{specifications}{%
\let\olditem\item%
\renewcommand\item[2][]{\olditem##1\dotfill##2}%
\begin{enumerate}}{\end{enumerate}%
}
\begin{document}
\begin{specifications}
\item[Input Voltage Range] 36-72 V DC
\item[Input Current] 80 mA
\item[Power over Ethernet] 802.3af-compliant Powered Device
\end{specifications}
\end{document}
As per Aditya's comment, the contained \renewcommand
statement may be simplified to only one, compulsory argument, giving:
\documentclass[12pt, letter]{article}
\newenvironment{specifications}{%
\let\olditem\item%
\renewcommand\item[1]{\olditem##1\dotfill}%
\begin{enumerate}}{\end{enumerate}%
}
\begin{document}
\begin{specifications}
\item{Input Voltage Range} 36-72 V DC
\item{Input Current} 80 mA
\item{Power over Ethernet} 802.3af-compliant Powered Device
\end{specifications}
\end{document}
Which of course provides the exact same output.
Best Answer
(Encountered this question while searching for something else. In case there's still any interest in the answer…)
Exactly this problem is discussed in A Beginner's Book of TeX by Seroul and Levy, on page 48. (Having leaders, but without the long line overlapping into the page number area.) Their trick is to make the line narrower on the right, then typeset the page numbers beyond the end of that line using
\rlap
. So, a minor modification of Werner's answer:which produces: