1

This is a follow-on from a question answered by Marcel Krüger. I need a custom sort, so I generate a sort key that is prepended to the index entry. This works very nicely, but I'm wondering what is the easiest way to assign a counter to each entry and display that counter in front of each entry when I print it (this is entry #1, #2, ...#523 ...). The actual counter value doesn't matter much (as long as it's unique) It could be a LaTeX counter that I process programatically or it could be the line number in the .ind file.

I do not want to sort on the counter, just assign and use it to refer to the index entries after they have been sorted.

I could do this by writing a program to post-process the .ind file and follow that with a another makeindex run. But I'd much prefer to handle everything in the same pass. The structure of the .ind file looks like turning it into an enumerated list might work.

There may be some way to do this using xindy attributes or tags, but I'm not familiar enough with it to say.

The MWE ouput produces 13 lines - numbering them 1-13 is fine, I don't particularly need to preserve the entry-subentry structure.

MWE (due to Marcel)

\documentclass{article}%                                                                      

\RequirePackage[para]{threeparttable}%
\RequirePackage{imakeidx}\makeindex%
\RequirePackage[unbalanced,indentunit=0.75em]{idxlayout}%

\RequirePackage{luacode}%

\begin{luacode}
function Bsort(s)
--Patch the index to use Bridge sort order
    local t=""

    --Generate a sort key for the input sequence.
    for c in s:gmatch"." do
        if tonumber(c) ~= nil then
            t = t .. c
        end

        if c == "T" then
          t = t .. "A"
       end
        if c == "K" then
          t = t .. "B"
       end
        if c == "C" then
          t = t .. "C"
       end
        if c == "P" then
          t = t .. "D"
       end
        if c == "m" then
          t = t .. "E"
       end
        if c == "M" then
          t = t .. "F"
       end
        if c == "S" then
          t = t .. "G"
       end
    end

    --Section the index. 
    s = string.gsub(s, ";", "!;")

    --Prefix the index with the sort order.
    s = t .. "@" .. s

    -- Write the index back to LuaLaTeX.
    s = "\\index[seq]{" .. s .. "}"
    tex.sprint(s)
    return s
end
\end{luacode}


\DeclareRobustCommand{\Bsort}[1]{\directlua{Bsort([[#1]])}}% 
\makeindex[name=seq,title=Liste des Séquences]

\begin{document}                                                                


\begin{threeparttable}[t]                                                       
\begin{tabular}{*{3}{l}}                                                                                                                              
2xxx    &3xxx   &\Bsort{2SA-3T}\\                                                             
3xxx    &       &\\                                                             
&3K   &Chassé-croisé\Bsort{2SA-3T;3K} \\                                            
&3SA                   &A jouer ;\Bsort{2SA-3T;3SA}\\                                                                                                                                             
2xxx    &3xxx   &\\                                                             
3xxx   &3xxx   &Chassé-croisé ;\Bsort{2SA-3T;3K-3C}\\                                               
3xxx    &       &Fit xxx xxx{3}, en attendant ;\Bsort{2SA-3T;3K-3C;3P}\\                               
3xxx    &       &Sans fit xxx xxx{3},  \Bsort{2SA-3T;3K-3C;3SA}\\                                      
\end{tabular}                                                                                            
\end{threeparttable}                                                            

\printindex[seq]         
\end{document}     

Sample .ind file

\begin{theindex}

  \item 2SA-3T: \hyperpage{35, 36}
  \item 2SA-3T; 3K: \hyperpage{36}
  \item 2SA-3T; 3K-3C: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 3P: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 3SA: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 4T: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 4K: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 4C: \hyperpage{39}
  \item 2SA-3T; 3K-3C; 4P: \hyperpage{39}
  \item 2SA-3T; 3K-3P: \hyperpage{39}
  \item 2SA-3T; 3K-3P; 3SA: \hyperpage{39}
  \item 2SA-3T; 3K-3P; 4T: \hyperpage{39}
  \item 2SA-3T; 3K-3P; 4K: \hyperpage{39}
  \item 2SA-3T; 3K-3P; 4C: \hyperpage{39}
  \item 2SA-3T; 3K-3P; 4P: \hyperpage{39}
  \item 2SA-3T; 3K-3M: \hyperpage{39}
  \item 2SA-3T; 3K-3SA: \hyperpage{39}
  \item 2SA-3T; 3K-4m: \hyperpage{39}
  \item 2SA-3T; 3K-4M: \hyperpage{39}
  \item 2SA-3T; 3K-4SA: \hyperpage{39}
  \item 2SA-3T; 3C: \hyperpage{43}
  \item 2SA-3T; 3C-3P: \hyperpage{43}
  \item 2SA-3T; 3C-3P; 3SA: \hyperpage{43}
  \item 2SA-3T; 3C-3P; 4T: \hyperpage{43}
  \item 2SA-3T; 3C-3P; 4K: \hyperpage{43}
  \item 2SA-3T; 3C-3P; 4C: \hyperpage{43}
  \item 2SA-3T; 3C-3P; 4P: \hyperpage{43}

\end{theindex}
1
  • @Marcel That should compile now.
    – DLyons
    Jul 13, 2018 at 14:18

2 Answers 2

1

If you want the index to be numbered, you can patch \item command to add numbering: First you need a new counter, so add

\newcounter{seqindexitem}
\renewcommand\theseqindexitem{\#\arabic{seqindexitem}}

to your preamble. To change the \item command only for this one index, replace

\printindex[seq]

with

\begingroup
  \makeatletter
  \let\@@idxitem\@idxitem
  \renewcommand\@idxitem{%
    \@@idxitem
    \refstepcounter{seqindexitem}%
    \leavevmode\llap{\theseqindexitem:}
  }
  \printindex[seq]
\endgroup

By using \refstepcounter instead of stepcounter it becomes possible to add labels to the index entries to refer to the numbers.

The full code:

\documentclass{article}%                                                                      

\RequirePackage[para]{threeparttable}%
\RequirePackage{imakeidx}\makeindex%
\RequirePackage[unbalanced,indentunit=0.75em]{idxlayout}%

\RequirePackage{luacode}%

\newcounter{seqindexitem}
\renewcommand\theseqindexitem{\#\arabic{seqindexitem}}
\begin{luacode}
function Bsort(s)
--Patch the index to use Bridge sort order
    local t=""

    --Generate a sort key for the input sequence.
    for c in s:gmatch"." do
        if tonumber(c) ~= nil then
            t = t .. c
        end

        if c == "T" then
          t = t .. "A"
       end
        if c == "K" then
          t = t .. "B"
       end
        if c == "C" then
          t = t .. "C"
       end
        if c == "P" then
          t = t .. "D"
       end
        if c == "m" then
          t = t .. "E"
       end
        if c == "M" then
          t = t .. "F"
       end
        if c == "S" then
          t = t .. "G"
       end
    end

    --Section the index. 
    s = string.gsub(s, ";", "!;")

    --Prefix the index with the sort order.
    s = t .. "@" .. s

    -- Write the index back to LuaLaTeX.
    s = "\\index[seq]{" .. s .. "}"
    tex.sprint(s)
    return s
end
\end{luacode}

\DeclareRobustCommand{\Bsort}[1]{\directlua{Bsort("\luaescapestring{#1}")}}%
\makeindex[name=seq,title=Liste des Séquences]

\begin{document}                                                                


\begin{threeparttable}[t]                                                       
\begin{tabular}{*{3}{l}}                                                                                                                              
2xxx    &3xxx   &\Bsort{2SA-3T}\\                                                             
3xxx    &       &\\                                                             
&3K   &Chassé-croisé\Bsort{2SA-3T;3K} \\                                            
&3SA                   &A jouer ;\Bsort{2SA-3T;3SA}\\                                                                                                                                             
2xxx    &3xxx   &\\                                                             
3xxx   &3xxx   &Chassé-croisé ;\Bsort{2SA-3T;3K-3C}\\                                               
3xxx    &       &Fit xxx xxx{3}, en attendant ;\Bsort{2SA-3T;3K-3C;3P}\\                               
3xxx    &       &Sans fit xxx xxx{3},  \Bsort{2SA-3T;3K-3C;3SA}\\                                      
\end{tabular}                                                                                            
\end{threeparttable}                                                            

\begingroup
  \makeatletter
  \let\@@idxitem\@idxitem
  \renewcommand\@idxitem{%
    \@@idxitem
    \refstepcounter{seqindexitem}%
    \leavevmode\llap{\theseqindexitem:}
  }
  \makeatother
  \printindex[seq]         
\endgroup
\end{document}                                                                  

enter image description here

3
  • Thanks for that Marcel. It works fine in the MWE but for some reason in the live system it prints the index itself OK but without the entry number. The index print is preceded by a line with the text "idxitem@idxitem dxitemi@idxit:" which id overlayed by the llap #. Any thoughts on what could cause that?
    – DLyons
    Jul 14, 2018 at 11:39
  • That's hard to say without an example, but it sounds like another package tries to change \@idxitem too. Jul 14, 2018 at 12:03
  • Could easily be that. I'll comment out glossaries etc and see the results.
    – DLyons
    Jul 14, 2018 at 12:05
0

I eventually decided to change the sort code to digits only e.g. 27303137 and to prepend that and ") " to the entry as a unique reference number. Then I prepend the sort code and "@" to the result.

That gives me a unique, invariant, more-or-less human readable reference number to refer to any sequence. It's much longer than the number of entries in the index but the fact that it doesn't change when stuff is moved around greatly outweighs the length.

I'd have used the accepted answer except that some other program seems to change the index in the live system, so the patched index from that solution doesn't print correctly.

You must log in to answer this question.

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