9

I would like to sort the index entries independent of case.

Initially I was getting (code provided in MWE) the image on the left. So, that seemed like an easy fix: just apply \lowercase (uncomment the \def in the MWE) but that yields the image on the right:

enter image description here enter image description here

So, how do I get these sorted alphabetically, and get the two entries for zero to be displayed as a sub-entries under a single heading?

Failed Attempts:

  1. I thought this was an explansion issue, so I tried to use

    \edef\LowerCaseWord{\lowercase{#2}}
    \index{\LowerCaseWord!#1}
    

    but this also yielded results identical to the image on the right.

  2. Since a wise member here (who I think no longer wants to be associated with this comment :-)) once alluded that a few carefully placed \expandafters should fix anything I tried this and it also does not change the output:

    \edef\LowerCaseWord{\lowercase{#2}}
    \expandafter\index{\LowerCaseWord!#1}
    

Code:

%\def\UseLowercase{}% Uncomment to use lowercase

\documentclass{article}
\usepackage{imakeidx}

\ifdefined\UseLowercase% Select whether we use lowercase or not
    \newcommand{\IndexTitle}{Index (lowercase)}%
\else
    \newcommand{\IndexTitle}{Index}%
    \renewcommand{\lowercase}[1]{#1}%
\fi

\newcommand*{\AddIndexEntry}[2]{%
    % #1 = indexed term, #2 = word to index this under
    \par\noindent
    Indexing: #2
    \index{\lowercase{#2}!#1}
}%

\makeindex[title={\IndexTitle},columns=1]

\begin{document}
    \AddIndexEntry{aardvark}{aardvark}
    \AddIndexEntry{Saved by Zero}{Saved}
    \AddIndexEntry{Saved by Zero}{Zero}
    \AddIndexEntry{zero}{zero}
    \printindex
\end{document}
1
  • \lowercase isn't expandable, so no amount of \expandafter can do. But there's something that can be done. Be patient. :)
    – egreg
    Commented Apr 12, 2012 at 19:22

2 Answers 2

11

I'd say that

\newcommand*{\AddIndexEntry}[2]{%
    % #1 = indexed term, #2 = word to index this under
    \par\noindent
    \lowercase{\def\temp{#2}}%
    Indexing: #2%
    \expandafter\index\expandafter{\temp!#1}%
}

should be what you need.

How does \lowercase works? It sends its argument to a further processor (it's not a macro, so it doesn't its work in TeX's “mouth”); the token list is converted using the \lccode table: each character token that hasn't a zero \lccode is converted to its lowercase correspondent, but symbolic tokens such as \def or \temp are untouched. The token list so obtained is put back in the input as if it had been there from the beginning. There's no expansion during this process: so if TeX finds \lowercase{\def\temp{Xyz}} when it's executing things, then it "waits" a bit, processes the token list as explained, then it processes

\def\temp{xyz}

and goes along.


In case you have more than one index, you can use a modified form:

\documentclass{article}
\usepackage{imakeidx}

\newcommand*{\AddIndexEntry}[3][]{%
  % #1 = indexed term, #2 = word to index this under
  \par\noindent
  \lowercase{\def\temp{#3}}%
  Indexing: #3%
  \if!#1!
    \expandafter\index\expandafter{\temp!#2}%
  \else
    \expandafter\indexopt\expandafter{\temp!#2}{#1}
  \fi
}
\newcommand{\indexopt}[2]{\index[#2]{#1}}

\makeindex
\makeindex[name=Name,title=Title,columns=1]

\begin{document}

\AddIndexEntry{aardvark}{aardvark}
\AddIndexEntry{Saved by Zero}{Saved}
\AddIndexEntry{Saved by Zero}{Zero}
\AddIndexEntry[Name]{zero}{zero}

\printindex
\printindex[Name]

\end{document}

The \indexopt macro takes care of switching the arguments, so that the \expandafter doesn't need to jump over the optional argument to \index.

1
  • Well, it definitely does what I need, but have to ask: what does it mean to apply a macro like \lowercase to a \def? Don't think I have seen that kind of voodoo magic before. Commented Apr 12, 2012 at 19:34
1

Following egreg's answer, for those who just need a 1-argument version and have the lowercase words in the table:

\newcommand{\lindex}[1]{%
  \lowercase{\def\temp{#1}}%
  \expandafter\index\expandafter{\temp}%
}
3
  • Following this, I am using a command that takes the word "ExampleWord" and adds "exampleword" to the index, while displaying "ExampleWord" in the text (so I don't need to type it twice): \newcommand\indlt[1]{#1 \lowercase{\def\temp{#1}} \expandafter\index\expandafter{\temp}}. However, this throws a weird error when the ExampleWord is in the section header, i.e. \section{\indlt{ExampleWord}}. Can you help?
    – Marie. P.
    Commented Dec 17, 2019 at 14:01
  • Maybe try \section{\protect\indlt{ExampleWord}} ?
    – Tom
    Commented Dec 18, 2019 at 15:09
  • Using \newcommand\indltneu[1]{#1\lowercase{\def\temp{#1}}\expandafter\index\expandafter{\temp}} and then \subsection{\protect\indltneu{Normal Distribution} and Lognormal Distribution} results in in "undefined control sequence" upon second run of pdflatex, probably when when the TOC is generated: Undefined control sequence. <argument> ...tname }{\numberline {10.3}\indltneu {Normal Distribution} and ... l.32 ...ormal Distribution}{16}{subsection.1.10.3}
    – Marie. P.
    Commented Dec 18, 2019 at 19:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .