The selection can be done by stating which items I want {1,3}, or, maybe better, using \label{} and \ref{} so that when I add more items, I do not need to change the numbering in the subset.

I need this for keeping an updated list of publications/references/talks in one place, while being able to generate various documents containing a more, or less verbose list of items.

EDIT:
Due to the many answers below, I'm keeping a copy of the .sty file I ended up writing and using. Its undocumented, and subject to change...but you can use it if you like. Most of the fiel is due to Ryan's accepted answer, but I added some things thanks to andrew and egreg (as noted in the code).

5 Answers
5

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 called tag=<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 either include = {<list>} or exclude = {<list>}, where <list> is a comma-separated list of numbers and text. The numbers can be given in ranges a,...,b like in \foreach. The text can be anything that pgfkeys thinks is a good name for a key. You can also say all or none; the default is all, so with no options at all, this behaves just like itemize usually does.

The order of these options is somewhat important: alternating include and exclude 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. The all and none 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 keys tag = <bullet> as described above, or id = <label>, where <label> is something you might include or exclude. The \items are also secretly enumerated as they go (this enumeration does not depend on what is included; i.e. it depends only on how many \items 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.

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 or none, basically). This part is contained in the select key subtree.

The way that \begin{itemize} sets up these keys is by means of another .unknown handler. This one is contained in the process 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 the select key subtree, so process remains vacant. This makes it possible to put the same id or number in include and exclude 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 then verdict, 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 the verdict key, the process/.unknown handler also attaches a piece of code to the reset key that tells it to undo the other thing. Then reset is called at the beginning of every itemize.

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.

Hmmm. using pgf...Will this work in the LaTeX->dvi->ps workflow?
– Yossi FarjounOct 25 '11 at 21:01

@Yossi: The sample above works perfectly. The subset of PGF I'm using is just a macro language and doesn't actually use the "low-level" stuff, so it should be format-independent.
– Ryan ReichOct 25 '11 at 21:06

3

I don't actually need the onlyitem stuff; however this piece of code really is worth studying. One can learn quite a lot from it. Thanks Ryan for your elaborative and inspirational answer.
– DanielOct 27 '11 at 7:28

@Daniel: Thanks, I really appreciate that. I hope you do learn from it; it's taken me quite a while to understand what it represents about pgfkeys.
– Ryan ReichOct 27 '11 at 15:45

@Yossi: Right, I should have mentioned that this is itemize-specific but only superficially. If you reprogram another list environment in exactly the same way as I did itemize, it should work fine.
– Ryan ReichNov 9 '11 at 0:15

how would you program \do to accept an optional label, and not need \begingroup, \endgroup surrounding the item. in other words, could you make it work more like a regular \item?
– Yossi FarjounOct 24 '11 at 18:18

@YossiFarjoun The \begingroup-\endgroup pair is not necessary. I'll edit the answer to have also an optional argument for \item.
– egregOct 24 '11 at 19:21

If you really want to, you can abuse biblatex+biber to create any lists. The following is extremely simplistic. I guess one could write a configuration files for biber to make things look more natural (and have sorting if desired).

Anyway, biblatex defines the custom[a-f] entry type which can (amongst others) contain the user[a-f] fields. So one could create .bib file like this.

One warning: biber seems to remove newlines from the usera field. This means that paragraphs have to be explicitly marked with \par and that there cannot be any comments.

If you want several of these lists in one document, the refsection environment (see the biblatex manual) can used. If you also want a normal bibliography, you can use biblatex's facilities to handle several separate bibliography resources.

Note: This answer was given the bounty by mistake, or possibly extraterrestrial interference. Please read my other answer.

I had this problem when trying to maintain three versions of my CV, each with different levels of detail. In a nutshell, what I came up with is sort of a hack involving the comment environment from the verbatim package. Here is what I wrote:

% These lists have optional arguments which indicate the formats in which
% they are to be displayed. To display always, write [*], which is the default.
\newif\ifdisplaythis\displaythistrue
\newif\ifinner
\newsavebox{\casket}
\newcommand{\behead}[1]{\basketmacro #1}
\newcommand{\basketmacro}[1]{\gdef\basket{#1}}
\newcommand{\checkresumeformat}[1]{
\ifthenelse{\equal{*}{#1}}%
{\displaythistrue\listbreak}{%
\savebox{\casket}{\behead{#1}}% Hackish way of removing the evidence
\ifthenelse{\equal{\basket}{-}}%
{\ifthenelse{\equal{-\resformat}{#1}}{}{\displaythistrue}\listbreak}%
{\ifthenelse{\equal{\resformat}{#1}}{\displaythistrue\listbreak}{}}%
}%
}
\newcommand{\testifallowed}[1]{%
\displaythisfalse%
\let\do = \checkresumeformat%
\docsvlist{#1}%
}
% Logic:
% \reslist and \resitem both set \innerfalse and then test for being commented.
% When \endreslist or \endresitem comes around, we need to know whether to end
% the comment or not.
% Each of them decides this and then sets \innertrue.
% The decision is: if \ifinner is true, then there must have been a nested
% environment, so we were
% not commented. Otherwise, we can check \ifdisplaythis, which can't have been
% changed by anything
% since there was nothing to change it.
\def\maybecomment#1#2{%
\testifallowed{#1}%
\ifthenelse{\boolean{displaythis}}%
{#2}%
{\comment}%
}
\def\endmaybecomment#1{%
\ifthenelse{\boolean{inner} \OR \boolean{displaythis}}%
{#1}%
{\endcomment}%
}
\newenvironment{reslist}[1][*]
{\innerfalse\maybecomment{#1}{\compactitem}}
{\endmaybecomment{\endcompactitem}\innertrue}
% resitem...
\newenvironment{resitem}[1][*]
{\innerfalse\maybecomment{#1}{\item}}
{\endmaybecomment{}\innertrue}

You'll want to load etoolbox and ifthen to make this work (I also use paralist for the compact lists, but you can just replace that with the usual itemize). You may also want to ignore the business with \ifinner, unless you plan on having nested lists (but see below).

The idea is that somewhere, the macro \resformat is set (I wrote this as a class file, so it is set in an option, but you can define it manually). Let's say it's set to CV, but you also have a resume format. Then you might write a list like:

\begin{reslist}[*]
% This list is displayed in both the CV and resume
\begin{resitem}[CV]
This goes in the CV only.
\end{resitem}
\begin{resitem}[resume]
This goes in the resume only.
\end{resitem}
\begin{resitem}[CV,resume]
This is displayed in both the CV and resume.
\end{resitem}
\begin{resitem}[-CV]
This is displayed in every format other than CV.
\end{reslist}

This is not unlike how beamer works, if memory serves.

Now, suppose you have a nested list; that is, something like:

\begin{reslist}
\begin{resitem}[*]
This item is always displayed.
\end{resitem}
\begin{resitem}[resume]
This item is only in the resume, and has another list.
\begin{reslist}
\item If you don't need the switches, you can use normal notation for lists.
\end{reslist}
\end{resitem}
\end{reslist}

My code is designed to handle this. However, the verbatim code (whence the commenting functionality comes) is not. Thus, you must modify it to recognize nested comments (or nested verbatims, more generally. See the docs for why this is the same thing). I did this, though I am currently reluctant to put it online since I am not sure of the legalities so I feel like I should keep it to myself (for now). If you know what incantations I should say to make it okay to distribute, tell me and I'll do it.

You may be wondering why I chose to use the (awkward) notation in which each item is an environment. This is a necessary evil coming from the way the code in verbatim is designed: the pair \comment and \endcomment which delimits the commenting environment can tell from which environment it is called, but not from which scope. That is, it has to be called from an environment so that it can find the \end{environmentname} tag (which does not have to be \end{comment}; for me, it is \end{reslist} or \end{resitem}). One can not "comment everything between the braces". It also does not work if that tag is not visible in the unprocessed source code, so no tricks like

since \comment will not expand the \item's to figure out whether there is an \endcomment embedded. I know how it is possible to modify \comment so as to get around this, but I haven't done it because it was enough work to get the nested comments working (for now).

The idea is to define package-private commands for every item specified in a DefConditionalList environment. Then, \ConditionalList can loop over the requested names, check to see if their corresponding commands are defined, and insert them if so. Order and repetition are irrelevant, you get an error if a non-existent key is specified, and you can specify something to do if no items are specified (by default, nothing is inserted). Defining conditional list items with spaces at the end is not permitted (though it might work anyway…), so that arbitrary spaces can be provided around the commas.