# Defining an new itemize like environment where \item[foo] passes foo to a macro

I want to use enumitem or similar package to define a basic list with the following properties:

1. When \item has no optional argument, a small square (\rule{1em}{1em}) is used
2. When \item[foo] is called, the itemize icon is \mymacro{foo}

I would actually settle for \item with no argument defaulting to \mymacro{somedefaultvalue} so I could then conditional-fu my way round that issue...

The background is I am making a list where the items are more or less complete, and would like little pie charts to indicate how complete the various things are. The pie charts I've made in TikZ, but I don't know how to get them where I want them, apart from calling them explicitly. (I'm writing a thesis outline, with indications of which parts need work and which parts are finished. Or rather, I'm procrastinating by playing with TikZ...)

This is what it looks like currently, but I have to call \mymacro explicitly in each \item There's all sorts of other minor things that need fixing, like aligning the centre of the circle with the centre line of the text and so on...

-

\newenvironment{seamusitemize}
{\itemize\let\origitem\item
\renewcommand{\item}[1][default]
{\origitem[\csname seamus##1\endcsname]}}
{\enditemize}

\newcommand{\seamusdefault}{\textbullet}
\newcommand{\seamusx}{x}
\newcommand{\seamusy}{y}

\begin{document}
\begin{seamusitemize}
\item pippo
\item[x] pluto
\item[y] paperino
\end{seamusitemize}
\end{document}


In this way you needn't know how \makelabel is defined in itemize; you can use enumitem to adapt the parameters for the space reserved to the label.

If the definition of the commands \seamus... is not feasible, you can change \csname seamus##1\endcsname into \mymacro{##1}. It's easy to define \mymacro to do a default when its argument is default:

\def\seamusdefault{default}
\newcommand{\mymacro}[1]{%
\def\next{#1}%
\ifx\next\seamusdefault
<default code>%
\else
<code using #1>%
\fi}


As Danie Els observed, it's a bit dangerous to redefine \item; no list environment or other environments that depend on these, such as center or flushleft must not be nested in seamusitemize. A safer strategy would be to redefine \makelabel:

\newenvironment{seamusitemize}
{\itemize[label=default]
\let\origmakelabel\makelabel
\renewcommand{\makelabel}[1]{\origmakelabel{\mymacro{##1}}}}
{\enditemize}


Then \mymacro can do what's required, as explained above. This requires to load enumitem (thanks to Seamus for pointing it out).

-
@egreg this relies on defining \seamusx and friends beforehand: I would like to allow the optional arguments to be at least any number between 0 and 100. I don't want to define 101 macros (leaving aside the issues with macros not being able to have numbers in). I want the option to be passed as an argument to the macro...) –  Seamus May 23 '11 at 16:04
@Seamus You're allowed to do what you want with that argument: say \mymacro{##1} instead of \csname seamus##1\endcsname. –  egreg May 23 '11 at 16:10
Ah I see. and then I'd need to change \mymacro{default} to give me my default behaviour? –  Seamus May 23 '11 at 16:18
This is basically the solution I opted for, but I defined \mymacro with xparse because I find its handling of defaults and so on easier to understand. –  Seamus May 24 '11 at 11:24
@Seamus: The center, quote, flushleft, flushright, verse and some others all have internaly a \item[] command. If you use them inside an environment where \item was redefined you end up with a bullet and bad spacing. I often use quote inside lists to emphasis a paragraph. –  Danie Els May 24 '11 at 12:33

The itemize labels are typest using the \makelabel macro which receives the optional argument of \item as mandatory argument. The default argument is \@itemlabel which is defined to \labelitemi, \labelitemii etc. depending on the level.

You could simply define an own itemize environment which sets this macros accordantly.

\documentclass{article}

\usepackage{tikz}

\makeatletter
\newcommand{\mydefaultlabel}{%
\@gobble{mydefaultlabel}% unique definition
}

\newcommand{\mymakelabel}[1]{%
\begingroup
\def\@tempa{#1}%
\def\@tempb{\@itemlabel}%
\ifx\@tempa\@tempb
\endgroup
\hss \llap{\textcolor{blue}{\rule{1em}{1em}}}%
\else
\endgroup
\hss \llap{%
\begin{tikzpicture}[xscale=-1,rotate=90]
\path (0,0) circle (.5em);
\fill [blue] (0,0) -- +(0:.5em)
arc [start angle=0, delta angle={(#1)*3.6}, radius=.5em] -- cycle; %
\end{tikzpicture}%
}%
\fi
}

\newenvironment{myitemize}{%
\itemize
\let\makelabel\mymakelabel
\let\@itemlabel\mydefaultlabel
}{%
\enditemize
}
\makeatother

\begin{document}
\begin{myitemize}
\item test
\item[10] a
\item[80] b
\item[50] c
\item[100] c
\end{myitemize}
\end{document}


-
I much prefer that more verbose description of arcs. I find the (0:30:1) syntax very difficult to read. This has the drawback/feature (depending on perspective) that you need to do it for each level of itemization... –  Seamus May 23 '11 at 16:20
@Seamus: It took me a while to get so far. The whole arc syntax is quite strange for me. Also I always have to remember which value comes first in polar coordinates, the angle or the radius. The (angle:radius) syntax is counter-intuitive for me I would find (radius:angle) would make more sense. –  Martin Scharrer May 23 '11 at 16:24
@Martin no I think that way round makes sense, first you pick your direction, then you work out how far along that direction to walk... –  Seamus May 23 '11 at 17:58
@Seamus: Ok, this makes sense. I have to remember that. What is with the (0:30:1) syntax you mentioned? I never heard about it. –  Martin Scharrer May 24 '11 at 11:13
That's the short syntax for defining arcs. I don't like it: I prefer the long form. With the short one, the first two numbers are the start and end angles for the arc and the third number is the radius of the circle... –  Seamus May 24 '11 at 11:16

I would keep it as simple as possible by not redefining anything and make a special item command. Unfortunately I do not know TikZ and have therefore used a partially filled box to illustrate the concept.

\documentclass{article}
\usepackage{enumitem}

\newcommand\mybullet[1]{{%
\fboxsep=0pt
\fbox{\rule{0pt}{1em}%
\rule{1em}{#1em}}}}

\usepackage{ifmtarg}
\makeatletter
\newcommand\bitem[1][]{%
\@ifmtarg{#1}{\item[$\bullet$]}%--> or anything else e,g. \mybullet{0}
{\item[\mybullet{#1}]}}
\makeatother

\begin{document}
\begin{itemize}[]
\bitem       aaaa
\bitem[0.25] bbbb
\bitem[0.00] ccc
\bitem[1.00] yyyy
\end{itemize}
\end{document}


This will give something like the following

-
If I understand this correctly, it relies on the fact that if the #1 isn't there it is ignored, and the macro code works whether or not there is something in that place. I'd rather have the "default" code handled differently. How might this be modified to have the default \item be an empty square rather than a full one? –  Seamus May 23 '11 at 16:07
@Seamus: I have changed the default optional argument of \bitem to 0, but note that it is opposite to your original request. –  Danie Els May 24 '11 at 3:02
@Danie I know: I'm not sure what I want to do with the default yet, but I think I'd rather be able to execute arbitrary different code for the default case... –  Seamus May 24 '11 at 11:20
@Seamus: I understand. See the change to code for \bitem. –  Danie Els May 24 '11 at 11:40
It is better in general to do \ifx\empty#1 than \ifx#1\empty: try with #1 equal to 00.1 for instance. –  Bruno Le Floch May 24 '11 at 20:47