Accueil > LaTeX > Index > xindy, hyperref et |see

xindy, hyperref et |see

lundi 2 novembre 2015, par Maïeul

Une personne m’a demandé comment utiliser xindy avec hyperref et l’option d’indexation |see. Je tire donc un article de la solution proposée.

Fichier d’exemple

Je suppose que vous avez, au préalable, créé votre fichier .xdy contenant les instructions proposées dans l’article xindy et hyperref.
Je suppose que vous avez également chargé le package hyperref avec l’option hyperindex=false :

\usepackage[hyperindex=false]{hyperref}

Je prend maintenant le fichier contenant les commandes d’indexation suivantes :

\indexentry{félin}{1}
\indexentry{chat|see{félin}}{1}

Je souhaite que la commande |see non seulement renvoie vers la bonne entrée, mais en plus intègre un lien hypertexte.

Analyse du fichier .idx et du fichier .ind

Le fichier .idx produit est le suivant

\indexentry{félin}{1}
\indexentry{chat|see{félin}}{1}

Après un passage par xindy avec mon précédent .xdy, on obtient les lignes suivantes dans le fichier .ind :

(…)
\item chat, \see{félin}{}
(…)
\item félin, \hyperpage{1}
(…)

On constate donc que si il existe bien un renvoi depuis "chat" vers "félin" et si félin pointe bien avec un lien hypertexte sur la page 1, le renvoi ne propose pas de lien hypertexte.

Modification du .xdy

Nous allons modifier notre fichier .xdy pour ajouter :
 une commande pour indiquer que "félin" est un lieu de destination.
 une commande pour indiquer que "chat" pointe vers félin, ou plus exactement que le \see{félin}{} point vers félin.

Ajoutons donc les deux lignes suivantes au fichier .xdy :

(markup-keyword-list :open "\targetindexentry{"           :close"}")
(markup-crossref-list :open "\seelink{" :close "}{}" :class "see")

La première ligne indique d’entourer les mots-c’est à dire les entrées d’indexation, par \targetindexentry{ à gauche et par } à droite.

La seconde ligne indique que le paramètre marqué entre les accolades qui suivant le |see, ici félin doit être entouré à gauche par \seelink{ et à droite par }{}.

Ceci nous produit donc le fichier .ind avec les lignes suivantes :

(…)
\item \targetindexentry{chat}, \seelink{félin}{}
(…)
\item \targetindexentry{félin}, \hyperpage{1}

Définition de \seelink et de \targetindexentry

Il ne reste plus qu’à définir dans notre fichier .tex les deux commandes \targetindexentry et \seelink qui utilisent des commandes du package hyperref.

\newcommand{\targetindexentry}[1]{\hypertarget{index:#1}{#1}}
\newcommand{\seelink}[1]{\hyperlink{index:#1}{\see{#1}}}

Rien de bien méchant : targetindexentry crée une ancre sur son argument. Le nom de l’ancre correspond à son argument précédé par index: ; \seelink point vers une ancre dont le nom correspond à son argument précédé de index:, le texte pointeur étant tout simple la commande \see à laquelle on passe son argument.

Correction de \hyperlink et hypertarget

Le problème est que les commandes \hyperkink et hypertarget ne fonctionne pas si le premier argument contient des accents. Il nous faut donc corriger ces commandes. Cependant une telle correction ralentissant considérablement le temps de calcul [1], il est recommandé de les faire uniquement avant l’index.

Ajoutez donc ces lignes avant le premier \printindex.

La différence principale avec les définitions de hyperref est l’emploi de \pdfstringdef qui permet de transformer les accents en caractères acceptables dans le code interner d’un pdf, donc dans les liens hypertextes.

Et maintant, non seulement |see fonctionne, mais en plus il produit des liens hypertextes. Miaou !


[1D’après l’auteur du package, Otto Oberdierk.

Messages

  • Merci pour ces explications très utiles. Par contre j’ai deux remarques.
    La première est un conseil : l’utilisation de package \usepackage[shorthands=;!?]{babeltools} peut aider pour ceux qui utilisent le package \usepackage[french]{babel}. Car sinon l’utilisation de index:#1 est parasitée par babel.
    La deuxième est une question. Est-ce normal que chez moi, le numéro de page associé à l’entrée qui utilise |see, ne s’affiche pas ? comment résoudre ce problème ?

  • Merci pour le conseil, même si je n’utilise pas babel (notamment à cause de ce genre de problème).

    Concernant le second point, je pense que la lecture de l’article "Indexation et renvoi" devrait résoudre le problème.

  • En réalité mon problème n’est pas sur la référence après |see, mais sur le numéro de page.
    En effet, pour reprendre ton exemple si j’ai une entrée du fichier .idx qui est \indexentry{chat|see{félin}}{1}
    avec ta solution nous obtenons un résultat dans le fichier .ind \item \targetindexentry{chat}, \seelink{félin}{}.
    Mais est-il possible d’obtenir \item \targetindexentry{chat} \hyperpage{1}, \seelink{félin}{} ?

  • Si je comprend bien, tu veux donc avoir à la fois un renvoi à la page du terme et un renvoi à une autre entrée.

    Dans ce cas il faut que tu fasse deux indexations : une avec |see et une sans.

  • Merci, en effet tu as bien compris et bien répondu à ma question.
    Je comprend un peu mieux comment cela fonctionne à présent.

    Par contre, je me suis aperçu d’un bug que je n’arrive pas à comprendre. J’ai reproduis l’exemple fourni ici, en utilisant polyglossia et XeLaTeX et je n’arrive pas a avoir un hyperlink sur les mots accentués.
    Dans le fichier .ind la commande \item \targetindexentry{chat}, \seelink{félin}{} ou si je rajoute à la suite de mon fichier .tex la commande \hyperlink{index:félin}{félin} créent bien une un hyperlien contenant le félin, mais ce lien est vide, il ne mène lorsqu’on clique dessus. Est-ce normal ? Ou ai-je mal compris quelque chose ?

  • il me faudrait un exemple complet minimal pour que je puisse comprendre le problème.

  • Voici un exemple minimal complet.
    le fichier .tex

    % A compiler avec xelatex -shell-escape
    \documentclass{article}
     
    \usepackage{fontspec}
    \usepackage{polyglossia}
    \setmainlanguage{french}
    \usepackage{setspace}
    \onehalfspacing
    \usepackage[xindy]{indextools}%On précise qu'on veut utiliser xindy
    \usepackage[hyperindex=false]{hyperref}
    
    	\def\xindyopt{ -I xelatex -M style_index1 -L french }
    	\makeindex[program=truexindy, options=\xindyopt, intoc] 				
    
    	
    \begin{document}
    
    toto    \index{toto}  \newpage 
    téte\index{téte}
    toti\index{toti} \index{toti|seealso{toto}} \index{toti|see{téte}} \newpage
    ta\index{ta|see{toto}}\index{ta|seealso{toti}} \newpage
    tata\index{tata}
    
    \printindex
    
    \hyperlink{index:téte}{téte}
    
    \end{document} 

    avec le fichier style_index1.xdy :

    (define-location-class "arabic-page-numbers" ("arabic-numbers")             
                        :min-range-length 2)                            
    
    (define-attributes (("definition" "usage" "default" "hyperpage")))
    
    
    (define-crossref-class "see")
    (markup-crossref-list :class "see" :open "\seelink{" :sep "; " :close "}{}")
    
    (define-crossref-class "seealso")
    (markup-crossref-layer-list :sep ", ")
    (markup-crossref-list :class "seealso" :open "\seealsolink{" :sep "; " :close "}{}")
    
    (define-crossref-class "hyperindexformat")
    (markup-crossref-list :class "hyperindexformat" :open
           "\hyperindexformat{" :sep "; " :close "}{}")
    
    
    (define-location-class-order (
                  "arabic-page-numbers"
                  "see"
                  "seealso"))
    
    (markup-index :open  "~n\begin{theindex}
                        \providecommand*\lettergroupDefault[1]{}
                        \providecommand*\lettergroup[1]{%
                            \par\textbf{#1}\par
                            \nopagebreak
                        }
                        \newcommand{\targetindexentry}[1]{\hypertarget{index:#1}{#1}}
                        \newcommand{\seelink}[1]{\see{\hyperlink{index:#1}{#1}}}
                        \newcommand{\seealsolink}[1]{\seealso{\hyperlink{index:#1}{#1}}}
                    ~n"     
        :close "~n~n\end{theindex}~n"
        :tree)
    
    
    (markup-indexentry :open "~n \item "            :depth 0)
    (markup-indexentry :open "~n    \subitem "      :depth 1)
    (markup-indexentry :open "~n      \subsubitem " :depth 2)
    
    
    (markup-locref-list :sep ", ")
    (markup-locclass-list :open "\dotfill " :close "" )
    
    
    (markup-locref :open "\hyperpage{" :close "}")
    (markup-locref :open "\hyperpage{" :close "}" :attr "hyperpage")   
    
    
    (markup-keyword-list :open "\targetindexentry{" :close "}" )

    Après compilation, il y a bien des liens hypertextes. Mais ceux sur le mot "téte" ne fonctionnent pas, je suppose que cela est causé par le caractère "é".
    J’espère que c’est plus claire comme ça.

  • Je vais regarder cela. Peux tu par contre utiliser la balise <code> pour marquer des bouts de code.

  • Bon, effectivement limite d’hyperref. Je pose la question sur http://tex.stackexchange.com/q/288553/7712

  • J’ai ajouté un dernier paragraphe donnant une solution.

  • Merci pour le conseil. J’ai même décider de passer sur XeLaTeX avec tes conseils.
    Avec ta solution, tout fonctionne super bien. Merci !

Un message, un commentaire ?

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)