Comment utiliser un tiret bas dans le texte hors du mode mathématique ?#

Par défaut, le tiret bas (_) se voit attribué le catcode 8, qui introduit les indices en mode mathématique. Si vous l’utilisez tel quel dans votre document, il est fort probable que vous obteniez une erreur « Missing $ inserted ».

1.  Cas où le tiret bas est considéré comme un caractère normal sans ajout d’extensions#

Le tiret bas est considéré par défaut comme un caractère normal dans les arguments de :

  • \label

  • \ref

  • \input

  • \include

  • \includegraphics

  • \begin et \end

  • compteurs

  • paramètres de placement (comme [t]).

Par exemple :

\documentclass[french]{article}
  \usepackage[T1]{fontenc}    % Encodage T1 (adapté au français)
  \usepackage{lmodern}        % Caractères plus lisibles
  \usepackage{babel}          % Réglages linguistiques (avec french)
  \pagestyle{empty}           % N'affiche pas de numéro de page

\begin{document}
\section{Un exemple parlant}
\label{sec_hello}
Cet exemple n'est parlant que si vous observez 
le code de cette section \ref{sec_hello}.
\end{document}

Si vous rencontrez quand même le message d’erreur indiqué quand vous utilisez un tiret bas dans un de ces cas, vous utilisez sans doute une extension qui modifie le comportement du tiret bas (autre que babel, qui ne pose pas de problèmes). Dans ce cas, vous devez appliquer l’une des solutions suivantes.

2.  Solution simple et généralement suffisante#

L’extension underscore redéfinit le tiret bas comme un caractère actif qui a le comportement suivant :

  • en mode mathématique, pas de changement (introduit un caractère en indice) ;

  • dans le corps du texte, affiche un tiret bas ;

  • s’il est précédé du caractère \, affiche un tiret bas après lequel il est possible de faire une coupure de mots.

Dans la plupart des cas, cela correspond à l’effet souhaité. Cependant, la redéfinition du tiret bas par underscore a pour conséquence qu’il n’est plus considéré comme un caractère normal dans les cas où il devrait être considéré comme tel (les cas vus en début de cette question). Ce problème est résolu en grande partie si vous chargez babel, ou de manière plus limitée en utilisant l’options [strings] de underscore. Pour plus de détails, veuillez vous référer à la documentation, particulièrement p. 2.

\documentclass[french]{article}
  \usepackage[T1]{fontenc}    % Encodage T1 (adapté au français)
  \usepackage{lmodern}        % Caractères plus lisibles
  \usepackage{babel}          % Réglages linguistiques (avec french)
  \pagestyle{empty}           % N'affiche pas de numéro de page
  \usepackage{underscore}

\begin{document}
\section{Le fichier test_tiret-bas.pdf}
\label{sec_hello}
Nous étudions ici le fichier test_tiret-bas.pdf.

\section{Autre section}
Voir la section \ref{sec_hello}.
\end{document}

2.1.  Solution plus souple mais plus complexe#

Si les effets du tiret bas ont été redéfinis par d’autres extensions avec lesquelles l’extension underscore interfère, on peut, au lieu de charger l’extension underscore, utiliser ponctuellement la commande \string, qui indique que le caractère qui suit immédiatement doit être traité comme un caractère normal (plus précisément, de la catégorie 12).

\label{sec\string_hello}
\ref{sec\string_hello}

Comme le nom de l’étiquette est également écrit dans le fichier .aux, il faut assigner au tiret bas la catégorie (catcode) 12 lors de la lecture de ce fichier :

\usepackage{atveryend}
\AfterLastShipout{\catcode`\_=12\relax}

Si l’extension en question rend le tiret bas actif avant le \begin{document}, alors il faut qu’il soit inactif pendant la lecture du fichier .aux à la fin du préambule.

\ifnum\catcode`\_=\active
  \catcode`\_=12\relax
  \AtBeginDocument{\catcode`\_=\active}%
\fi

Voici le code complet de l’exemple :

\documentclass[french]{article}
  \usepackage[T1]{fontenc}    % Encodage T1 (adapté au français)
  \usepackage{lmodern}        % Caractères plus lisibles
  \usepackage{babel}
  \pagestyle{empty}           % N'affiche pas de numéro de page

  \catcode`\_=\active
  \def_{\textunderscore}

  \usepackage{atveryend}
  \AfterLastShipout{\catcode`\_=12\relax}
  \ifnum\catcode`\_=\active
    \catcode`\_=12\relax
    \AtBeginDocument{\catcode`\_=\active}%
  \fi

\begin{document}
\section{Une autre tentative}
\label{sec\string_hello}
Voir la section \ref{sec\string_hello}.
\end{document}