# Redefine underscore to produce roman subscript without breaking file names

I've been using Hendrik Vogt's answer to my earlier question Redefine underscore to produce roman subscript, in which he explained how to make the underscore character active and assign a macro to it so that it can be redefined to produce roman type in subscripts:

\catcode_=\active
\newcommand_[1]{\ensuremath{\sb{\mathrm{#1}}}}


The solution works like a charm in maths and text environments, however I've run into trouble when I use it in 'literal' environments, such as file names or references, where making _ active breaks things.

Question: How can I make the underscore produce roman subscript, yet still function as a normal character in file names, labels, references and the like? I only need the subscript function in maths environments.

MWE:

\documentclass{article}

\catcode_=\active
\newcommand_[1]{\ensuremath{\sb{\mathrm{#1}}}}

\begin{document}
$D_H$
\label{sec_a} % This causes a "! Missing \endcsname inserted." error
\end{document}

-

If you only need the _ in math, then \mathcode does the trick. However, TeX seems to see the \catcode before the \mathcode, so I changed that, too:

\documentclass{article}

\begingroup
\catcode\_=\active
\gdef_#1{\ensuremath{\sb{\mathrm{#1}}}}
\endgroup
\mathcode\_=\string"8000
\catcode\_=12

\begin{document}
$D_H$
\label{sec_a} % This no longer causes a "! Missing \endcsname inserted." error
\end{document}


For simplicity I used \gdef here; this can be avoided if you want to.

-
Excellent, thank you very much. Your original solution has already saved me so much typing, and I'm glad I don't have to stop using it because of the file name issue. – Jake Mar 8 '11 at 22:34

You can test for mathmode using \ifmmode like \ensuremath is doing it. This should then be done with two macros so that the "normal underscore" doesn't take an argument:

\documentclass{article}

\catcode_=\active
\newcommand{_}{\ifmmode\expandafter\sbrm\else\string_\fi}
\newcommand{\sbrm}[1]{\sb{\mathrm{#1}}}

\begin{filecontents}{\jobname_test.tex}
\end{filecontents}

\begin{document}
\label{sec_a} % Works now
$D_H$

\input{\jobname_test}

\end{document}

-
Thanks for the additional approach (and the filecontents environment, that'll definitely come in handy)! – Jake Mar 8 '11 at 22:37
@Jake: Note that without loading the filecontents package the environment does not overwrite existing files. – Martin Scharrer Mar 8 '11 at 22:51

You need not necessarily name labels like that (try \label{sec:a}), and for filenames or other use cases force _ to be an ordinary character:

\input{file\string_name}

-