Indexing in partial decimal order, Luke 10:25 after Luke 1:5

enter image description here

\documentclass{article}

\usepackage{imakeidx}

\makeindex

\newcommand\bindex[3]{\index{#1:\string\number\string\numexpr\the\numexpr1000+#2\relax-1000:\string\number\string\numexpr\the\numexpr1000+#3\relax-1000}}
\begin{document}

zzz\bindex{Luke}{10}{25}  zzz\bindex{Luke}{1}{5} zzz\bindex{Matthew}{1}{1}

\printindex
\end{document}

If you look in the generated .ind file you see what it is doing:

\begin{theindex}

  \item Luke:\number\numexpr1001-1000:\number\numexpr1005-1000, 1
  \item Luke:\number\numexpr1010-1000:\number\numexpr1025-1000, 1

  \indexspace

  \item Matthew:\number\numexpr1001-1000:\number\numexpr1001-1000, 1

\end{theindex}

1000 gets added so all numbers end up the same length, then (after sorting) 1000 is subtracted and \number applied to remove leading zeros.


Pad the numbers with zeros and use the @ feature for sorting.

\documentclass{article}
\usepackage{imakeidx}

\makeindex

\ExplSyntaxOn
\NewDocumentCommand{\indexverse}{mmm}
 {% #1 = name, #2 = chapter, #3 = verse
  \index
   {% the sorting part
    #1\prg_replicate:nn{4-\tl_count:n{#2}}{0}#2\prg_replicate:nn{4-\tl_count:n{#3}}{0}#3
    @
    #1~#2:#3
   }
 }
\ExplSyntaxOff

\begin{document}

text
\indexverse{Luke}{10}{25}
\indexverse{Luke}{10}{5}

\printindex

\end{document}

This is the .idx file

\indexentry{Luke00100025@Luke 10:25}{1}
\indexentry{Luke00100005@Luke 10:5}{1}

and the .ind file

\begin{theindex}

  \item Luke 10:5, 1
  \item Luke 10:25, 1

\end{theindex}

Thanks, egreg and David Carlisle, for your help! Having seen what technique you used, I decided to reimplement the same technique outside of latex, like this:

perl -i -pe 's/(\d+)/$$1+1000/ge' jesus.idx
makeindex jesus.idx -o jesus.ind 
perl -i -pe 's/(\d\d\d\d)/$$1-1000/ge' jesus.ind

A disadvantage is that this method won't work for people running Windows. Advantages are that it only adds two lines of code to my build script, it's pretty readable, and it correctly handles strings that are not quite in the same format, e.g., Luke 5 or Matthew 8:27-9:1. So I thought I would post this as a self-answer, and that way others coming across this can have one more method to choose from.

Tags:

Indexing