Usar información de índice para generar referencias cruzadas

Usar información de índice para generar referencias cruzadas

La idea es utilizar la información del índice para generar automáticamente referencias cruzadas. Si una entrada de índice se refiere a más de una página (por ejemplo, "Smith, Juan 5, 9"), entonces la entrada de índice junto con los otros números de página deberían aparecer en el margen en el lugar donde hago la entrada de índice (es decir, siguiendo el ejemplo anterior, en la página 5 al margen aparece "Smith, John 9").

¿Es posible cambiar el showidxpaquete en consecuencia?

Además, la solución debe ser compatible con hyperrefel hecho de que estoy usando, twosidedpero el margen más grande siempre está a la derecha (estoy usando tufte-latex).

Gracias por cualquier pista.

Y aquí mi intento de un MWE (no estoy seguro si eso ayuda):

%\documentclass[twoside]{tufte-book}
\documentclass{book}
\usepackage{makeidx,showidx,lipsum}
\makeindex
\begin{document}
John Smith\index{Smith, John}
\lipsum
John Smith\index{Smith, John}
\lipsum
\printindex
\end{document}

Respuesta1

El"pequeño ajuste"es un eufemismo. Después del procesamiento habitual del .idxarchivo por parte de makeindex, la relación de los datos sin procesar dentro \index(archivo LaTeX) o \indexentry( .idxarchivo) con la entrada de índice formateada en el .indarchivo se pierde. Ejemplo:

\index{foobar}         ⇒ \item foobar, ...
\index{foo@foobar}     ⇒ \item foobar, ...          (sort spec.
\index{foobar|(}       ⇒ \item foobar, ...          (range spec.)
\index{foobar|textbf}  ⇒ \item foobar, \textbf{1}   (encap feature)
\index{"f"o"o"b"a"r}   ⇒ \item foobar, ...          (quote char)
\index{foo!bar}        ⇒ \item foo ...\subitem bar  (level char)
\index{fooX@foo!barY@b"ar|(emph}
                        ⇒ \item foo ...\subitem bar  (sort + level + quote + range + encap)

A partir del archivo de índice generado, \indexsolo se puede adivinar la forma exacta de (por ejemplo, \index{foobar}y \index{foo!bar}. Las especificaciones de clasificación, rango y encapsulación desaparecieron. Por lo tanto, el resultado del archivo de índice generado sería una asignación de dichas claves a la lista de páginas, por ejemplo:

foobar  ⇒ 1, \textbf{2}, 3
foo!bar ⇒ 3--7, 10

El siguiente paquete indexpagelistdefine un archivo de estilo indexpagelist.istpara makeindex que genera dicho mapeo.

De vuelta al nivel de LaTeX, necesitamos eliminar las especificaciones de clasificación, rango y encapsulación de la cadena, que se le da a \index.

Para reducir el nivel de complejidad y ahorrar algo de tiempo, no he implementado el soporte para comillas y caracteres de escape. Además actual, los caracteres level, y encapsolo se admiten con sus valores predeterminados ( @, !, |).

%%% indexpagelist.sty %%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{indexpagelist}[2013/07/16 v0.1 Index page list for showidx] 
\RequirePackage{filecontents}
\begin{filecontents*}{indexpagelist.ist}
preamble ""
postamble ""
setpage_prefix ""
group_skip ""
headings_flag 0
symhead_negative ""
numhead_negative ""
item_0 "\\iplItemA{"
item_1 "\\iplItemB{"
item_2 "\\iplItemC{"
item_01 "\\iplItemB{"
item_x1 "}\n\\iplItemB{"
item_12 "\\iplItemC{"
item_x2 "}\n\\iplItemC{"
delim_0 "}\n\\iplPageList{"
delim_1 "}\n\\iplPageList{"
delim_2 "}\n\\iplPageList{"
delim_n "\\iplMultiPage, "
delim_r "\\iplMultiPage--"
delim_t "}\n"
line_max 1000
\end{filecontents*}
\immediate\write18{%
  makeindex %
  -s indexpagelist.ist %
  -t \jobname-ipl.ilg %
  -o \jobname.ipl %
  \jobname.idx%
}
\immediate\write18{makeindex \jobname}% for convenience

\newcommand*{\iplItemA}[1]{%
  \def\iplCurrentItemA{#1}%
  \@onelevel@sanitize\iplCurrentItemA
  \let\iplCurrent\iplCurrentItemA
}
\newcommand*{\iplItemB}[1]{%
  \def\iplCurrentItemB{#1}%
  \@onelevel@sanitize\iplCurrentItemB
  \edef\iplCurrent{\iplCurrentItemA!\iplCurrentItemB}%
}
\newcommand*{\iplItemC}[1]{%
  \def\iplCurrentItemC{#1}%
  \@onelevel@sanitize\iplCurrentItemC
  \edef\iplCurrent{\iplCurrentItemA!\iplCurrentItemB!\iplCurrentItemC}%
}
\newcommand*{\iplPageList}[1]{%
  \expandafter\@ipl@PageList#1\iplMultiPage\@nil
}
\newcommand*{\iplMultiPage}{}
\def\@ipl@PageList#1\iplMultiPage#2\@nil{%
  \def\@ipl@Temp{#2}%
  \ifx\@ipl@Temp\@empty
  \else
    \expandafter\protected@xdef\csname ipl@\iplCurrent\endcsname{#1#2}%
  \fi
}
\InputIfFileExists{\jobname.ipl}{}{}

\newcommand*{\iplGetPageList}[1]{%
  \def\@ipl@Temp{#1}%
  \@onelevel@sanitize\@ipl@Temp
  \let\@ipl@Key\@empty
  \expandafter\@ipl@GetPageList@Encap\@ipl@Temp|\@nil
  \@ifundefined{ipl@\@ipl@Key}{}{%
    , \@nameuse{ipl@\@ipl@Key}%   
  }%
}   
\def\@ipl@GetPageList@Encap#1|#2\@nil{%
  \let\@ipl@Key\@empty
  \@ipl@GetPageList@Level#1!\@nil
}
\def\@ipl@Temp#1{%
  \def\@ipl@GetPageList@Level##1!##2\@nil{%
    \@ipl@GetPageList@Sort##1#1\@nil
    \def\@ipl@Temp{##2}%
    \ifx\@ipl@Temp\@empty
    \else
      \@ipl@GetPageList@Level##2\@nil
    \fi
  }%   
  \def\@ipl@GetPageList@Sort##1#1##2\@nil{%
    \def\@ipl@Temp{##2}%
    \edef\@ipl@Key{%
      \ifx\@ipl@Key\@empty
      \else
        \@ipl@Key!%
      \fi
      \ifx\@ipl@Temp\@empty
        ##1%
      \else 
        \@ipl@RemoveSortChar##2\@nil
      \fi
    }%   
  }%     
  \def\@ipl@RemoveSortChar##1#1\@nil{##1}%
}
\expandafter\@ipl@Temp\string @
% remaining "small tweak" for package showidx
\newcommand*{\iplPatchShowidx}{%
  \@ifpackageloaded{showidx}{%  
    \@ifdefinable{\saved@showidx}{%
      \let\saved@showidx\@showidx  
      \renewcommand*{\@showidx}[1]{%
        \saved@showidx{##1\iplGetPageList{##1}}%
      }%
    }%  
    \global\let\iplPatchShowidx\relax
  }{}%
}
\iplPatchShowidx
\AtBeginDocument{\iplPatchShowidx}
\endinput

Entonces, el "ajuste" del archivo TeX principal es pequeño, sólo es necesario cargar el paquete. Debido a deficiencias en la codificación OT1, el encapcarácter |se muestra como un guión , por lo tanto, he utilizado la codificación de fuentes T1 con fuentes latinas modernas.

%%% test.tex %%%
\documentclass{book}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{makeidx,showidx,lipsum,indexpagelist}
\makeindex

\begin{document}
John Smith\index{Smith, John}, John Doe\index{Doe, John},
cat\index{animals!cat|(}, dog\index{animals!dog}
\lipsum
John Smith\index{Smith, John}, dog\index{animals!dog|textbf},
Donald E. Knuth\index{Knuth, Donald E.}
\lipsum
cat\index{animals!cat|)}, dog\index{animals!dog},
Donald E. Knuth\index{Knuth, Donald E.}
\newpage
\printindex
\end{document}

El archivo de índice sin formato test.idx:

\indexentry{Smith, John}{1}
\indexentry{Doe, John}{1}
\indexentry{animals!cat|(}{1}
\indexentry{animals!dog}{1}
\indexentry{Smith, John}{2}
\indexentry{animals!dog|textbf}{2}
\indexentry{Knuth, Donald E.}{2}
\indexentry{animals!cat|)}{3}
\indexentry{animals!dog}{3}
\indexentry{Knuth, Donald E.}{3}

El archivo de índice principal se genera como de costumbre:

$ makeindex test

El archivo de índice test.indpara \printindex:

\begin{theindex}

  \item animals
    \subitem cat, 1--3
    \subitem dog, 1, \textbf{2}, 3

  \indexspace

  \item Doe, John, 1

  \indexspace

  \item Knuth, Donald E., 2, 3

  \indexspace

  \item Smith, John, 1, 2

\end{theindex}

El archivo con las asignaciones de la lista de páginas se genera mediante:

$ makeindex -s indexpagelist.ist -t test-ipl.ilg -o test.ipl test.idx

Para mayor comodidad, agregué ambas llamadas de makeindex vía \immediate\write18en el archivo del paquete (TeX Live las ejecuta con escape de shell restringido).

El archivo test.iplcontiene las asignaciones de las claves de índice a sus listas de páginas:

iplItemA{animals}
\iplItemB{cat}
\iplPageList{1\iplMultiPage--3}
\iplItemB{dog}
\iplPageList{1\iplMultiPage, \textbf{2}\iplMultiPage, 3}
\iplItemA{Doe, John}
\iplPageList{1}
\iplItemA{Knuth, Donald E.}
\iplPageList{2\iplMultiPage, 3}
\iplItemA{Smith, John}
\iplPageList{1\iplMultiPage, 2}

Eso define macros como \ipl@animals!dogcon contenidos 1, \textbf{2}, 3. La macro \iplMultiPagese utiliza como marcador para detectar listas de una o varias páginas más fácilmente.

Luego, el paquete se conecta \@showidxpara agregar la lista de páginas.

El índice:

índice

Página 1:

Página 1

Página 2:

página 2

Página 3:

página 3

información relacionada