# Provide boolean from two arguments case insensitives

In most publications scientific names are abbreviated except the first time. Moreover, the names must be in italics and only the first letter of the generic name should be upper-case.

The biocon package allow define a identifier for each species that manage all these requirements, but I don't want depend of remember a identifier for each species. I want also include a well formatted nested index entry each time in the same step, that manually is a lot of code typing that obfuscated the body text.

So I decided to make my own macro for this in the form the command \species{Genus}{species}. The result is the MWE that worked reasonably, but I found some problems that seem related with etoolbox package:

1. \setbool inside tabulars do not work, failing to switch to the abbreviate name.

2. The arguments are case sensitive, but I cannot reduce all possible occurrences to obtain a unique boolean for each species. I tried \providebool{\lowercase{#1#2}} but do not work. This, I can correct case variations in the output but having a different boolean each time, so the macro cannot switch to the abbreviated form, and worse, produce a duplicated index entry.

\documentclass[11pt]{article}
\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{mfirstuc}
\usepackage{makeidx}
\usepackage{biocon}
\makeindex

% Provide \genus{Generic name}
\newcommand\genus[1]{{\em\lowercase{\protect\makefirstuc{#1}}}
\index{#1@{\em\lowercase{\protect\makefirstuc{#1}}}|textbf}}

% Provide \species{Generic name}{specific name}
\newcommand\species[2]{%
\providebool{#1#2}%
\ifbool{#1#2}%
% abbreviated name
{\emph{\uppercase{\StrLeft{#1}{1}}. \lowercase{#2}}}%
% full name
{\setbool{#1#2}{true}{\em\lowercase{\protect\makefirstuc{#1} #2}}}%
%index entry for both types
\index{#1@{\em\lowercase{\protect\makefirstuc{#1}}}!#2@{\em\uppercase{\protect\StrLeft{#1}{1}}. \lowercase{#2}}}}

\begin{document}

\noindent Desired ouput of some \genus{Homo} species:\\\\
\species{Homo}{erectus} \texttt{(full name 1st time, OK)}\\
\species{Homo}{erectus} \texttt{(abbreviation 2nd time, OK)}\\
\species{Homo}{sapiens} \texttt{(indexed as Homo!sapiens, OK)}\\
\species{Homo}{erectus} \\
\species{Homo}{sapiens} \texttt{(indexed as as Homo!sapiens too, OK)}\\

\noindent Testing in tabular environment:\\\\
\begin{tabular}{|l|l|}
\hline\species{Homo}{habilis} & \\
\hline\species{Homo}{habilis} & \texttt{(not working inside tabular)}\\\hline
\end{tabular}\\

\noindent\species{Homo}{habilis} method (try again):\\

\noindent\begin{tabular}{|l|l|}
\hline\species{Homo}{habilis} & \texttt{
(\textbackslash{}setbool worked only outside tabular)}\\\hline
\end{tabular}\bigskip

\noindent Testing case correction:\\
\verb|\species{Homo}{Antecessor}|: \species{Homo}{Antecessor}\\
\verb|\species{Homo}{antecessor}|: \species{Homo}{antecessor}\\
\verb|\species{HOMO}{ANTECEsSOR}|: \species{HOMO}{ANTECEsSOR}\\\\
Problems with these three equivalents commands:\\
\texttt{not abbreviations}\\
\texttt{duplicated "Homo" at index}\\
\texttt{duplicated "antecessor" at index}\\

\printindex
\end{document}

• On the tabular issue, put \global before \setbool in your \species definition. On the second problem, you need to fix the case first, then call an internal version of your \species command that works on saved versions of the case corrected strings. – Alan Munn May 27 '13 at 23:34

Here's a hopefully complete solution also to the indexing problems. The assumption is that in the species' names you have only plain ASCII characters.

\documentclass[11pt]{article}
\usepackage{makeidx}
\usepackage{biocon}
\makeindex

% Provide \genus{Generic name}
\newcommand\genus[1]{%
\lowercase{\ifcsname genus@#1\endcsname}\else
\definnergenus#1\relax
\fi
\lowercase{\csname genus@#1\endcsname}%
}
\def\definnergenus#1#2\relax{%
\def\tempinitial{#1}%
\lowercase{\def\tempsecond{#2}\def\tempname{#1#2}}%
\begingroup\edef\x{\endgroup
\gdef\unexpanded\expandafter{\csname genus@\tempname\endcsname}{%
\noexpand\emph{\tempinitial\tempsecond}%
\noexpand\index{\tempname@{\noexpand\em\tempinitial\tempsecond}|textbf}%
}%
}\x}

% Provide \species{Generic name}{specific name}
\newcommand\species[2]{%
\lowercase{\ifcsname species@#1#2\endcsname\else}%
\definnerspecies#1\relax{#2}%
\fi
\lowercase{\csname species@#1#2\endcsname}%
\lowercase{\csname speciesindex@#1#2\endcsname}%
}
\def\definnerspecies#1#2\relax#3{%
\uppercase{\def\tempinitial{#1}}%
\lowercase{\def\tempfirst{#1}\def\tempsecond{#2}\def\tempthird{#3}}%
\edef\tempname{\tempfirst\tempsecond\tempthird}%
\begingroup\edef\x{\endgroup
\gdef\unexpanded\expandafter{\csname species@\tempname\endcsname}{%
\noexpand\emph{\tempinitial\tempsecond\space\tempthird}%
\gdef\unexpanded\expandafter{\csname species@\tempname\endcsname}{%
\noexpand\emph{\tempinitial.\ \tempthird}}}}\x
\begingroup\edef\x{\endgroup
\gdef\unexpanded\expandafter{\csname speciesindex@\tempname\endcsname}{%
\noexpand\index{%
\tempfirst\tempsecond@{\noexpand\em\tempinitial\tempsecond}!%
\tempthird@{\noexpand\em\tempthird}}%
}}\x}

\begin{document}

\noindent Desired ouput of some \genus{Homo} species:\\
\\
\species{Homo}{erectus} \texttt{(full name 1st time, OK)}\\
\\
\species{Homo}{erectus} \texttt{(abbreviation 2nd time, OK)}\\
\species{Homo}{sapiens} \texttt{(indexed as Homo!sapiens, OK)}\\
\species{Homo}{erectus} \\
\species{Homo}{sapiens} \texttt{(indexed as as Homo!sapiens too, OK)}

\noindent Testing in tabular environment:\\
\begin{tabular}{|l|l|}
\hline\species{Homo}{habilis} & \\
\hline\species{Homo}{habilis} & \texttt{(works also inside tabular)}\\\hline
\end{tabular}

\noindent\species{Homo}{habilis} method (try again):

\noindent Testing case correction:\\
\verb|\species{Homo}{Antecessor}|: \species{Homo}{Antecessor}\\
\verb|\species{Homo}{antecessor}|: \species{Homo}{antecessor}\\
\verb|\species{HOMO}{ANTECEsSOR}|: \species{HOMO}{ANTECEsSOR}

\printindex
\end{document}


Every \species command defines two commands: for instance

\species{Homo}{erectus}


defines

\species@homoerectus
\speciesindex@homoerectus


The first one expands to Homo erectus and globally redefines itself to expand to H. erectus. The input is normalized so that only lowercase letters are used, with the exception of the first initial. The second command deals with the index.

If \speciec@homoerectus is undefined (at the first appearance of \species{Homo}{erectus}, the \definespecies command is called that globally defines the two commands above.

Similarly, \genus{Homo} defines, at its first call, an inner macro with normalized input \genus@homo, that takes care of printing the name and issuing the indexing command.

Here are the pictures.

• Wow. Some day I will be able to understand this code. However, now is \genus{Homo} which produce a duplicated index entry. – Fran May 28 '13 at 1:02
• @Fran Fixed. :-) – egreg May 28 '13 at 8:36
• Geniale. Just curiosity: What is #2 in \genus and #3 in \species if these commands have only 1 and 2 arguments? – Fran May 28 '13 at 10:29
• @Fran The helper command \definnergenus and \definnerspecies have, respectively, two and three arguments; #1 is the first letter of the first (or only) argument to \species or \genus, #2 the remaining part of this argument; for \genus, #3 is the second argument. You'll have problems if you plan to have \genus or \species in a section title; in that case you'll have to decide what should happen for the TOC and index, and for the abbreviated form. – egreg May 28 '13 at 10:35

Just for the record. Although egreg provided (​​in few minutes!) a complete rewrite of the macro, that works perfectly with the bonus point of not relying in etoolbook package, did not solve why \lowercase within \providebool, like the money inside my wallet, is not expandable.

Like stubborn nobody beats me, I was trying a solution for this specific problem although I have not still knowledge to use the Dark Side of La(TeX). Providentially, this answer of David Carlisle put me on the track. This is the result, which seems to work also without problems:

\documentclass[11pt]{article}
\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{mfirstuc}
\usepackage{makeidx}
\makeindex

% Note: ending % neeeded to avoid extra speces

% Provide \species{Generic name}{specific name}
\newcommand\species[2]{%
% expand lowercase https://tex.stackexchange.com/a/95662/11604
\lowercase{\def\tmpa{#1#2}}% Identifier
\lowercase{\def\tmpb{#1}}%   Lower case genus
\lowercase{\def\tmpc{#2}}%   Lower case species
\providebool{\tmpa}%
\ifbool{\tmpa}%
{\emph{\uppercase{\StrLeft{#1}{1}}.~\tmpc}}% abbreviated name
{\global\setbool{\tmpa}{true}{\em\lowercase{\protect\makefirstuc{#1} #2}}}% full name
\index{\tmpb@{\em\protect\makefirstuc{\tmpb}}!\tmpc@{\em\uppercase{\protect\StrLeft{\tmpb}{1}}. \tmpc}|textsf}}% Index

% Provide \genus{Generic name}
\newcommand\genus[1]{%
\lowercase{\def\tmpb{#1}}% Lower cases genus
{\em\lowercase{\protect\makefirstuc{#1}}}% Genus name
\index{\tmpb@{\em\protect\makefirstuc{\tmpb}}|textbf}} % Index

\begin{document}

Hominoidea as \species{Heliopithecus}{leakeyi} existed about 16 million years ago, but \species{PaN}{TroglodYTES} diverged from  \genus{Homo} genus only about six millions years ago. The \genus{Homo} genus have many extint species as \species{Homo}{AnTecessor}. Problably \species{HOMO}{ANTECESSOR} was a evolutionary link between \species{hOmO}{ErgASter} and \species {Homo}{HEIDELBERGensis}. \species{homo}{Antecessor} is one of the earlist human species.
\newpage
The \genus{Pan}\footnote{Just for testing indexing in footnote, in Spanish \genus{pan} \index{pan (food)|see{bread}} mean "bread"\index{bread}.} actually is composed by \species{pan}{troglodytes} (chimpanzee) and \species{pan}{paniscus} (bonobo\index{bonobo|see{\emph{Pan paniscus}}}).
species, but \genus{hOMO} is represented only by \species{homo}{sapiens} and \index{Human!Dummy people} people that believe the speeches of politicians.

\newpage

Cheeta is a fictional character interpreted by several intelligents \species{Pan}{troglodytes} actors whereas Tarzan character was always an \index{hairless} hairless ape-men.

\printindex
\end{document}