xindy et hyperref

jeudi 16 avril 2015, mise à jour lundi 2 novembre 2015, par Maïeul
Suivre la vie du site RSS 2.0 Forum

Nous arrivons maintenant à un point délicat dans l’utilisation de xindy : sa compatibilité avec le package hyperref. Ce dernier insère en effet des liens hypertextes dans l’index : chaque référence pointe vers la page correspondante. Cependant l’insertion de ces liens utilisent les mécanismes de makeindex et pas ceux de xindy ce qui n’est pas sans poser quelques petits problèmes.

Un exemple qui marche …

Reprenons l’exemple de l’article précédent mais en activant hyperref :

\documentclass{article}

\usepackage{fontspec}
\usepackage{polyglossia}
\setmainlanguage{french}
\setmainfont{Linux Libertine O}
\usepackage{setspace}
\onehalfspacing
\usepackage[xindy]{indextools}%On précise qu'on veut utiliser xindy
\makeindex[name=animal,title=Animaux,columnseprule]

% Personnaliser l'apparence de lettergroup
\newcommand{\lettergroup}[1]{%
  {\centering\large---\emph{#1}---\par}%
}
\apptocmd{\subitem}{$\rightarrow$\,}{}{}


\begin{document}


On va parler de 
chats sauvages\index[animal]{chat!sauvage} et domestiques\index[animal]{chat!domestique},
de tortues marines\index[animal]{tortue!marine} et terrestres\index[animal]{tortue!terrestre},
d'élèphant d'Asie\index[animal]{élèphant!d'Asie} et d'Afrique\index[animal]{élèphant!d'Afrique},
et soyons fou, d'élans de Sibérie\index[animal]{élan!de Sibérie} et d'Amérique\index[animal]{élan!d'Amérique}.

\newpage

On va parler sur la page suivante des même animaux. C'est à dire : de 
chats sauvages\index[animal]{chat!sauvage} et domestiques\index[animal]{chat!domestique},
de tortues marines\index[animal]{tortue!marine} et terrestres\index[animal]{tortue!terrestre},
d'élèphant d'Asie\index[animal]{élèphant!d'Asie} et d'Afrique\index[animal]{élèphant!d'Afrique},
et soyons fou, d'élans de Sibérie\index[animal]{élan!de Sibérie} et d'Amérique\index[animal]{élan!d'Amérique}.

\newpage

Et pour la bonne cause, on va aussi parler de chats sauvages\index[animal]{chat!sauvage} qui se disputent avec les chiens errants\index[animal]{chien!errant}.
\printindex[animal]
\end{document}

Cela produit le PDF ci-dessous.

xindy + hyperref : exemple qui fonctionne

Comme vous pouvez constater, tout semble fonctionner : notre index est correct et les liens internes fonctionnent.

… mais c’est tout

Les problèmes surviennent lorsqu’on tente de marquer une référence comme importante, par exemple avec |textbf. Ainsi :

Et pour la bonne cause, on va aussi parler de chats sauvages\index[animal]{chat!sauvage|textbf} qui se disputent avec les chiens errants\index[animal]{chien!errant}.
\printindex[animal]

Lors de la compilation texindy vous obtenez le message suivant :

WARNING : unknown cross-reference-class `hyperindexformat’ !

Et de fait, la référence marquée par |textbf est absente de l’index final.

xindy + hyperref + |textbf ne fonctionne pas

La cause du problème

Rappelons que xindy se « contente » de transformer un fichier .idx en un fichier .ind. Ouvrons le fichier .idx pour comprendre comment cela.

À côté de ligne sans qui ne posent pas de soucis telle que :

\indexentry{chat!sauvage|hyperpage}{1}

Nous y trouvons la ligne problématique :

\indexentry{chat!sauvage|hyperindexformat{\textbf}}{3}

Et nous voici en face de deux limites de xindy [1] :

  • alors que makeindex transforme toute syntaxe de type |xxx en la commande correspondante, il n’en va pas de même avec xindy, qui nécessite qu’on lui déclare ces commandes manuellement. En effet, xindy, qui n’est pas conçue uniquement pour LaTeX, considère que la syntaxe |xxx après une entrée dans le fichier .idx correspond à un attribut de localisation, c’est à dire une propriété associée à la localisation d’une entrée. Certains de ces attribut de localisation sont déclarés dans le fichier base/latex-loc-fmts.xdy que texindy charge par défaut.
  • ces attributs ne peuvent pas recevoir d’arguments. Ainsi, même si nous déclarions hyperindexformat, cela ne nous arrangerait pas. En effet, les commandes avec arguments sont considérés par \xindy comme des marqueurs de renvois au sein de l’index, alors que makeindex est plus souple sur la question.

Solution

Comment résoudre ce problème ? En demandant à hyperref de ne pas intervenir dans la gestion du .idx et en gérant nous même cela via le fichier de configuration .xdy

Désactiver la modification de l’index par hyperref

Il suffit simplement de charger le package avec l’option hyperindex=false :

\usepackage[hyperindex=false]{hyperref}

Vous constaterez alors que le fichier .ind ne contient plus que des lignes de type :

\indexentry{chat!sauvage}{1}

et

\indexentry{chat!sauvage|textbf}{3}

qui sont très bien interprétés par xindy, mais sans évidemment que les liens hypertextes ne soit intégrés.

Configuration de xindy

Pour résoudre ce problème, il nous suffit d’ajouter dans le fichier de configuration .xdy les lignes suivantes :

La première ligne permet de définir l’attribut emph qui n’est pas défini par défaut dans texindy alors qu’il est plus sémantique que l’attribut textit.

Dans les quatres lignes nous réglons la propriété markup-locref pour l’attribut de localisation indiqué entre guillemets après le :attr, sachant que l’attribut defaut est – comme son nom l’indique – celui utilisé si aucun attribut n’est mentionné.

Pour chaque attribut nous définissons via :open un marqueur à insérer avant la localisation, et via :close nous définissons un marqueur à insérer après la localisation.

Avec un tel système, notre fichier .idx deviendra un fichier .ind contenant des lignes telles que

\subitem sauvage\dotfill \hyperpage{1}--\hyperpage{2}, \textbf{\hyperpage{3}}

Ce qui est parfaitement compris par LaTeX lors de compilation suivante, \hyperpage insérant un lien hypertexte vers une page.

Cela nous permet d’obtenir le fichier ci-dessous, contenant de liens internes, y compris en gras.

xindy + hyperref + |textbf exemple qui fonctionne

Notes

[1Bien tenues par rapport à ses avantages, puisqu’on peut facilement les contourner.

Vos commentaires

  • Le 16 avril 2015 à 13:42, par pluton En réponse à : xindy et hyperref

    Super, c’est ce problème entre hyperref et xindy qui m’empêchait d’utiliser xindy !

  • Le 16 avril 2015 à 13:48, par Maïeul En réponse à : xindy et hyperref

    oui, c’est assez piégeux. Une fois qu’on a compris ca va, mais avant ...

  • Le 2 novembre 2015 à 19:24, par Namrod En réponse à : xindy et hyperref

    Merci pour ces tutoriels clairs et précis qui m’aide beaucoup dans la réalisation d’un index. Seulement, je rencontre un problème similaire à ceux exposés ici, si ce n’est qu’il s’agit pas de mise en forme mais de l’usage de |see et de |seealso avec hyperref. Auriez vous une idée du code à ajouter au fichier .xdy pour que ces deux fonctions fonctionnent correctement ?

  • Le 2 novembre 2015 à 20:08, par Maïeul En réponse à : xindy et hyperref

    @Namrod. Bon déjà il faut savoir/constater que hyperref makeindex seul n’insère pas de lien hypertexte pour les see. Mais on peut ruser un peu.

    Prenons le contenu minimum suivant :

    \begin{document}
    \index{chat}
    \index{chien|see{chat}}
    \printindex

    Si hyperref est chargé ainsi :

    \usepackage[hyperindex=false]{hyperref}

    on obtient le fichier .idx suivant :

    \indexentry{chat}{1}
    \indexentry{chien|see{chat}}{1}

    Le tout maintenant est 1) de marquer les cibles 2) de marquer les textes qui pointent vers les cibles.

    Mettons dans notre fichier .xdy les lignes suivantes :

    Nous indiques : 1) que les mots clefs doivent êtres intégrés dans une commande \targetindexentry 2) que les références croisés de type see doivent être marqué par la commande \seelink

    Ce qui produit un fichier .ind ainsi :

    \begin{theindex}
      \providecommand*\lettergroupDefault[1]{}
      \providecommand*\lettergroup[1]{%
          \par\textbf{#1}\par
          \nopagebreak
      }
    
      \lettergroup{C}
      \item \targetindexentry{chat}, 1
      \item \targetindexentry{chien}, \seelink{chat}{}
    
    \end{theindex}

    Il ne nous reste plus qu’à définir dans notre préambule nos deux commandes, qui font appelle aux commandes d’hyperref :

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

    Merci de me signaler s’il s’agit bien là d’une réponse à votre problème. J’en ferai un article.

    Ps : merci aussi d’ouvrir le ticket github suite à votre question sur texnique.fr

  • Le 2 novembre 2015 à 20:32, par Namrod En réponse à : xindy et hyperref

    Merci d’avoir pris le temps de me répondre, ceci répond en effet parfaitement à ma question, à ceci près qu’avec l’option passée à hyperref, le reste des numéros de page indiqués dans l’index n’est plus cliquable. Est-il possible d’arranger cela ?

    PS : oui bien sûr, désolé, cela m’était complétement sorti de la tête...

  • Le 2 novembre 2015 à 20:49, par Namrod En réponse à : xindy et hyperref

    Oups, veuillez m’excuser, je n’avais pas vu que la réponse à ma question figurait dans cet article... Ainsi tout fonctionne parfaitement avec votre solution, merci !

  • Le 2 novembre 2015 à 22:47, par Maïeul En réponse à : xindy et hyperref

    Et voilà, publié sur xindy, hyperref et |see.

  • Le 2 novembre 2015 à 22:52, par Namrod En réponse à : xindy et hyperref

    Quelle rapidité ! Merci beaucoup !

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Acheter XeLaTeX appliqué aux sciences humaines

À propos

Titulaire d’un doctorat en théologie et d’un doctorat en histoire, sous la direction conjointe de Frédéric Amsler et d’Élisabeth_Malamut, je commence à partir du 1er août 2017 un travail d’édition critique des Actes de Barnabé.

Dans le cadre de la rédaction de mon mémoire de master puis de ma thèse de doctorat, j’ai été emmené à utiliser LaTeX, et j’ai donc décider de partager mes techniques. En effet, au cours de mes premiers apprentissages, j’ai découvert que les ressources indiquant les outils pour l’utilisation de LaTeX en sciences humaines étaient rares. Ceci m’a conduit à maintenir ou créer plusieurs packages LaTeX et à donner plusieurs formations.

J’ai reçu en 2018 le prix DANTE e.V pour mon travail autour de LaTeX, en particulier autour de reledmac et reledpar.

Par ailleurs, je suis membre actif de la communauté SPIP, au sein de laquelle j’administre le site Spip-Contrib. Je propose sur ce site quelques notes sur SPIP, en général à destination de webmestre.

Il m’arrive également de faire un petit peu de Python, de temps en temps.

Enfin, je tiens un blog de réflexions politiques et religieuses.

Maïeul