5

I'm using xindy to create indeces. However, the default sort order is not sensible for uppercase and lowercase. Is there a way to create a .xdy file so that the uppercases are sorted in front of lowercases.

Here is an example:

A
Abel.......
Alex.......
aboutism...
account....
axis.......

B
Bible......
basics.....
bigger.....

I think the issue is, by default, uppercase letters are mapped to lowercase letters, thus cannot be distinguished former and sorted according to that. I wonder if anyone can help me create a .xdy that sorts alphabet case-sensitively.

3 Answers 3

2

If you are using OpTeX then you needn't any external program for sorting index. The sorting is done using TeX macros. There are macros \_sortingdataLANG etc. they enables to configure the sorting process.

I copied the default \_sortingdatalatin from the OpTeX macros and modified it slightly in order to realize your request. The result is here:

\def \sortingdataAa {%
  /,{ },-,&,@,%
  A,a,À,à,Â,â,Ä,ä,Á,á,%
  Ą,ą,%
  B,b,%
  C,c,%
  Ć,ć,Č,č,%
  D,d,Ď,ď,%
  E,e,È,è,É,é,Ë,ë,Ê,ê,Ě,ě,%
  Ę,ę,%
  F,f,%
  G,g,%
  H,h,%
  ^^T^^U^^V,% ch Ch CH
  I,i,Í,í,Ï,ï,Î,î,%
  J,j,%
  K,k,%
  L,l,Ĺ,ĺ,Ľ,ľ,%
  Ł,ł,%
  M,m,%
  N,n,Ň,ň,%
  Ń,ń,Ñ,ñ,%
  O,o,Ö,ö,Ó,ó,Ô,ô,%
  P,p,%
  Q,q,%
  R,r,Ŕ,ŕ,%
  Ř,ř,%
  S,s,ß,%
  Ś,ś,Š,š,%
  T,t,Ť,ť,%
  U,u,Ù,ù,Û,û,Ü,ü,Ú,ú,Ů,ů,Ű,ű,%
  V,v,%
  W,w,%
  X,x,%
  Y,y,Ý,ý,Ÿ,ÿ,%
  Z,z,%
  Ž,ž,%
  Ź,ź,%
  Ż,ż,%
  ^^Z,% Hungarian: cz:c^^Z, etc., see \_compoundcharshu in lang-data.opm
  0,1,2,3,4,5,6,7,8,9,'%
}
\let\_sortingdataen = \sortingdataAa % English language will use the \sortingdataAa

\ii Alex
\ii aboutism
\ii axis
\ii Abel
\ii basics
\ii account
\ii bigger
\ii Bible

\nonum\sec Index

\makeindex

\bye

See OpTeX manual, sections 1.5.2 and 2.33 for more details.

1

Use at own risk.

% make sure Aa.xdy and Aa_utf8.xdy are in working directory
% pdflatex foo.tex
% xindy -M Aa.xdy foo.idx
% pdflatex foo.tex

\documentclass{article}

\usepackage{makeidx}
\makeindex

\begin{document}

\index{Abel}
\index{Alex}
\index{aboutism}
\index{account}
\index{axis}

\index{Bible}
\index{basics}
\index{bigger}

\printindex
\end{document}

file Aa.xdy:

;;; -*- mode: lisp; coding: utf-8; -*-
;;; provided by user691586, May 17 2023
;; USE AT OWN RISK -- THIS IS PROVIDED WITH NO WARRANTY
;; OF ANY KIND NOR LIABILITY OF ANY THING AT ALL
;; (forever)
;; USAGE: put this file together with companion Aa_utf8.xdy
;; in your working directory.  Execute *latex on foo.tex,
;; then xindy -M Aa.xdy foo.idx, then again *latex.

;; (but xindy is hyperref-incompatible last time I checked,
;;  although I don't recall what was this incompatibility,
;;  perhaps something having to do with page hyperlinking)
(require "latex-loc-fmts.xdy")

(require "numeric-sort.xdy")

;; do not use texindy
;; do not load latex.xdy, we copy here what's needed

;(require "latex.xdy")

;; from latex.xdy and tex.xdy

;;;
;;; TeX conventions
;;;

;; Discard leading and trailing white space. Collapse multiple white
;; space characters to blank.

(merge-rule "^ +" "" :eregexp)
(merge-rule " +$" "" :eregexp)
(merge-rule "  +" " " :eregexp)

;; Handle TeX markup

(merge-rule "\\([{}$%&#])" "\1" :eregexp)

;; Standard location classes: arabic and roman numbers, and alphabets.

(define-location-class "arabic-page-numbers" ("arabic-numbers"))
(define-location-class "roman-page-numbers"  ("roman-numbers-lowercase"))
(define-location-class "Roman-page-numbers"  ("roman-numbers-uppercase"))
(define-location-class "alpha-page-numbers"  ("alpha"))
(define-location-class "Alpha-page-numbers"  ("ALPHA"))

;;;
;;; Output Markup
;;;

(markup-index :open
"\begin{theindex}
  \providecommand*\lettergroupDefault[1]{}
  \providecommand*\lettergroup[1]{%
      \par\textbf{#1}\par
      \nopagebreak
  }
"
          :close "~n~n\end{theindex}~n"
          :tree)

(markup-letter-group-list :sep "~n~n  \indexspace~n")
(markup-letter-group :open-head "~n  % ")

(markup-indexentry :open "~n  \item "           :depth 0)
(markup-indexentry :open "~n    \subitem "      :depth 1)
(markup-indexentry :open "~n      \subsubitem " :depth 2)

(markup-locclass-list :open ", " :sep ", ")
(markup-locref-list   :sep ", ")

(require "makeindex.xdy")

(require "latin-lettergroups.xdy")

;; (utf8 *may* work but will require LaTeX from recent
;;  years so that the (in)famous IeC macro is not used
;;  in idx file
;; )
(require "Aa_utf8.xdy")

File Aa_utf8.xdy:

;; -*- mode: lisp; coding: utf-8-unix; -*-
;; Modeled on xindy/lang/general/utf8.xdy and utf8-lang.xdy
;; provided by user691586, May 17 2023
;; USE AT OWN RISK -- THIS IS PROVIDED WITH NO WARRANTY
;; OF ANY KIND NOR LIABILITY OF ANY THING AT ALL
;; (forever)
;; (utf8 *may* work but will require LaTeX from recent
;;  years so that the (in)famous IeC macro is not used
;;  in idx file
;; )
;; USAGE: put this file together with companion Aa.xdy
;; in your working directory.  Execute *latex on foo.tex,
;; then xindy -M Aa.xdy foo.idx, then again *latex.

(define-letter-group "A"           )
(define-letter-group "a" :after "A")
(define-letter-group "B" :after "a")
(define-letter-group "b" :after "B")
(define-letter-group "C" :after "b")
(define-letter-group "c" :after "C")
(define-letter-group "D" :after "c")
(define-letter-group "d" :after "D")
(define-letter-group "E" :after "d")
(define-letter-group "e" :after "E")
(define-letter-group "F" :after "e")
(define-letter-group "f" :after "F")
(define-letter-group "G" :after "f")
(define-letter-group "g" :after "G")
(define-letter-group "H" :after "g")
(define-letter-group "h" :after "H")
(define-letter-group "I" :after "h")
(define-letter-group "i" :after "I")
(define-letter-group "J" :after "i")
(define-letter-group "j" :after "J")
(define-letter-group "K" :after "j")
(define-letter-group "k" :after "K")
(define-letter-group "L" :after "k")
(define-letter-group "l" :after "L")
(define-letter-group "M" :after "l")
(define-letter-group "m" :after "M")
(define-letter-group "N" :after "m")
(define-letter-group "n" :after "N")
(define-letter-group "O" :after "n")
(define-letter-group "o" :after "O")
(define-letter-group "P" :after "o")
(define-letter-group "p" :after "P")
(define-letter-group "Q" :after "p")
(define-letter-group "q" :after "Q")
(define-letter-group "R" :after "q")
(define-letter-group "r" :after "R")
(define-letter-group "S" :after "r")
(define-letter-group "s" :after "S")
(define-letter-group "T" :after "s")
(define-letter-group "t" :after "T")
(define-letter-group "U" :after "t")
(define-letter-group "u" :after "U")
(define-letter-group "V" :after "u")
(define-letter-group "v" :after "V")
(define-letter-group "W" :after "v")
(define-letter-group "w" :after "W")
(define-letter-group "X" :after "w")
(define-letter-group "x" :after "X")
(define-letter-group "Y" :after "x")
(define-letter-group "y" :after "Y")
(define-letter-group "Z" :after "y")
(define-letter-group "z" :after "Z")

(define-rule-set "user-alphabetize"

  :rules  (("Ă" "A" :string)
           ("Ā" "A" :string)
           ("ā" "a" :string)
           ("ă" "a" :string)
           ("Ē" "E" :string)
           ("ē" "e" :string)
           ("Ĕ" "E" :string)
           ("ĕ" "e" :string)
           ("Ī" "I" :string)
           ("ī" "i" :string)
           ("Ĭ" "I" :string)
           ("ĭ" "i" :string)
           ("Ō" "O" :string)
           ("ō" "o" :string)
           ("Ŏ" "O" :string)
           ("ŏ" "o" :string)
           ("ß" "SS" :string)
           ("Ū" "U" :string)
           ("ū" "u" :string)
           ("Ŭ" "U" :string)
           ("ŭ" "u" :string)
           ))


(define-rule-set "user-resolve-case"

  :rules  (("Ā" "8" :string)
           ("ā" "9" :string)
           ("Ă" "8" :string)
           ("ă" "9" :string)
           ("Ē" "8" :string)
           ("ē" "9" :string)
           ("Ĕ" "8" :string)
           ("ĕ" "9" :string)
           ("Ī" "8" :string)
           ("ī" "9" :string)
           ("Ĭ" "8" :string)
           ("ĭ" "9" :string)
           ("Ō" "8" :string)
           ("ō" "9" :string)
           ("Ŏ" "8" :string)
           ("ŏ" "9" :string)
           ("Ū" "8" :string)
           ("ū" "9" :string)
           ("Ŭ" "8" :string)
           ("ŭ" "9" :string)
           ("ß" "99" :string)
           ("A" "8" :string)
           ("B" "8" :string)
           ("C" "8" :string)
           ("D" "8" :string)
           ("E" "8" :string)
           ("F" "8" :string)
           ("G" "8" :string)
           ("H" "8" :string)
           ("I" "8" :string)
           ("J" "8" :string)
           ("K" "8" :string)
           ("L" "8" :string)
           ("M" "8" :string)
           ("N" "8" :string)
           ("O" "8" :string)
           ("P" "8" :string)
           ("Q" "8" :string)
           ("R" "8" :string)
           ("S" "8" :string)
           ("T" "8" :string)
           ("U" "8" :string)
           ("V" "8" :string)
           ("W" "8" :string)
           ("X" "8" :string)
           ("Y" "8" :string)
           ("Z" "8" :string)
           ("a" "9" :string)
           ("b" "9" :string)
           ("c" "9" :string)
           ("d" "9" :string)
           ("e" "9" :string)
           ("f" "9" :string)
           ("g" "9" :string)
           ("h" "9" :string)
           ("i" "9" :string)
           ("j" "9" :string)
           ("k" "9" :string)
           ("l" "9" :string)
           ("m" "9" :string)
           ("n" "9" :string)
           ("o" "9" :string)
           ("p" "9" :string)
           ("q" "9" :string)
           ("r" "9" :string)
           ("s" "9" :string)
           ("t" "9" :string)
           ("u" "9" :string)
           ("v" "9" :string)
           ("w" "9" :string)
           ("x" "9" :string)
           ("y" "9" :string)
           ("z" "9" :string)
           ))


; somewhat random as user691586 does not quite understand
; what is going on
; look in xindy/modules/lang/general/uft8.xdy for more complex
; setup
(define-sort-rule-orientations (forward backward))
(use-rule-set :run 0
          :rule-set ("user-alphabetize"))
(use-rule-set :run 1
          :rule-set ("user-resolve-case"))

This has not been tested beyond the above ascii example:

enter image description here

1
  • when I said it may work with utf8 I was only thinking of Latin based European languages of course as one sees from the code I provided
    – user691586
    May 17, 2023 at 17:10
1

Xindy puts index entries into dedicated lettergroups by the entry prefix, which is the same as the first letter by default. So it's pretty much sufficient to create lettergroups that account for both upper- and lowercase letters. For example, case.xdy:

(define-letter-group "A" :prefixes ("A" "a"))
(define-letter-group "B" :prefixes ("B" "b"))
(define-letter-group "C" :prefixes ("C" "c"))
(define-letter-group "D" :prefixes ("D" "d"))
(define-letter-group "E" :prefixes ("E" "e"))
(define-letter-group "F" :prefixes ("F" "f"))
(define-letter-group "G" :prefixes ("G" "g"))
(define-letter-group "H" :prefixes ("H" "h"))
(define-letter-group "I" :prefixes ("I" "i"))
(define-letter-group "J" :prefixes ("J" "j"))
(define-letter-group "K" :prefixes ("K" "k"))
(define-letter-group "L" :prefixes ("L" "l"))
(define-letter-group "M" :prefixes ("M" "m"))
(define-letter-group "N" :prefixes ("N" "n"))
(define-letter-group "O" :prefixes ("O" "o"))
(define-letter-group "P" :prefixes ("P" "p"))
(define-letter-group "Q" :prefixes ("Q" "q"))
(define-letter-group "R" :prefixes ("R" "r"))
(define-letter-group "S" :prefixes ("S" "s"))
(define-letter-group "T" :prefixes ("T" "t"))
(define-letter-group "U" :prefixes ("U" "u"))
(define-letter-group "V" :prefixes ("V" "v"))
(define-letter-group "W" :prefixes ("W" "w"))
(define-letter-group "X" :prefixes ("X" "x"))
(define-letter-group "Y" :prefixes ("Y" "y"))
(define-letter-group "Z" :prefixes ("Z" "z"))

(define-rule-set "ignore-special"
  :rules (("?" "") ("." "") ("-" "") ("'" "") ("!" "") ("{" "") ("}" "")
          ))

(define-sort-rule-orientations (forward))
(use-rule-set :run 0
          :rule-set ("ignore-special"))

(ignore-special conveniently drops some non-alphabetic characters to ease sorting.)

An example of the indexed TeX source test.tex:

\documentclass[a4paper,12pt,hyphens]{article}

\usepackage[xindy,noautomatic]{imakeidx}
\makeindex

\begin{document}
Abel\index{Abel}
Alex\index{Alex}
aboutism\index{aboutism}
account\index{account}
axis\index{axis}
Bible\index{Bible}
basics\index{basics}
bigger\index{bigger}

\printindex
\end{document}

Executing

pdflatex test.tex
xindy -M case.xdy test.idx
pdflatex test.tex

yields the following result (the second page):

enter image description here

Note that here we use the fact that Latin letters are naturally sorted by there Unicode (or ASCII) codepoints. If you need to sort more complicated characters, you'd have to extend the case.xdy file.

You must log in to answer this question.

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