26

I am writing a text document in LaTeX where I need a lot a words with underscores: foo_bar_1, more_bar_2_long_expression_3.

I know about the underscore package, but for some reason the [strings] option doesn't work for me (I get e.g. Extra \endcsname. ...oncluding Chapter~\ref{ch:summary_outlook}).

So my idea would be to define a new command or environment

\newcommand{escunderscore}[1]{...}

in which basically _ would be replaced by \_, so that I then can write \escunderscore{foo_bar_1} in my text whenever I need underscores. Is this possible and how do I do this?

Stefan Kottwitz
  • 231,401
  • 1
    See http://tex.stackexchange.com/questions/10536/how-can-i-fix-my-most-common-latex-complaints – Martin Tapankov Jun 16 '11 at 09:09
  • Looks like a dupe of the question Martin has linked to. – Joseph Wright Jun 16 '11 at 09:14
  • I think you'd be better off if you fix the broken strings option (it worked fine for me in a quick test). Wrapping words with underscores in an \esc_underscore command is not really more convenient or readable than manually escaping the underscores. Perhaps ask a new question about the [strings]underscore issue including a minimal example that reproduces your problem – Jake Jun 16 '11 at 09:17
  • The underscore package {without any special strings option}seems to work just fine for me, so not exactly sure what the problem – Peter Grill Jun 16 '11 at 09:18
  • 3
    @Martin, @Joseph: If I understand correctly, the answer to the linked question is to use the underscore package, which doesn't work for fuenfundachtzig, so it's not really a duplicate. – Jake Jun 16 '11 at 09:18
  • @Peter: underscore without extra options works for you in \ref commands that include underscores? – Jake Jun 16 '11 at 09:19
  • @Jake: You're right that fixing this package would be the better solution, but I was looking for a quick fix. Personally I find \trigger{EF_j75_a4tc_EFFS_jetNoEF_EFxe20_noMu} easier to read than EF\_j75\_a4tc\_EFFS\_jetNoEF\_EFxe20\_noMu. – fuenfundachtzig Jun 16 '11 at 09:32
  • @fuenfundachtzig: Fair point, although that particular example seems hard to read to me regardless of whether the underscores are escaped or not =) – Jake Jun 16 '11 at 09:35
  • Remark, in your "MWE" you missed a backslash before the command name, see this https://tex.stackexchange.com/q/29463/250119 – user202729 Oct 26 '22 at 05:25

2 Answers2

27

You can do even better: say

\usepackage[T1]{fontenc}
\catcode`\_=12

in your preamble and you'll be allowed to use the underscore as a printable character anywhere (requires a T1-encoded font, so the first line). For subscripts you can then use \sb.

A command for temporary escaping the underscore can be the following:

\makeatletter
\newcommand{\escapeus}{\begingroup\@makeother\_\@escapeus}
\newcommand*{\@escapeus}[1]{#1\endgroup}
\makeatother

that, however, will not be usable in the argument of any command, because of the change in the category code (still requires a T1-encoded font).

If T1-encoded fonts are not available, something more complicated is needed:

\makeatletter
\newcommand{\escapeus}{\begingroup\@activeus\@escapeus}
\newcommand*{\@escapeus}[1]{#1\endgroup}
\begingroup\lccode`\~=`\_\relax
   \lowercase{\endgroup\def\@activeus{\catcode`\_=\active \let~\_}}
\makeatother

Again, the \escapeus command cannot be used as the argument of another command. If you really need it there's a way:

\makeatletter
\DeclareRobustCommand*{\escapeus}[1]{%
  \begingroup\@activeus\scantokens{#1\endinput}\endgroup}
\begingroup\lccode`\~=`\_\relax
   \lowercase{\endgroup\def\@activeus{\catcode`\_=\active \let~\_}}
\makeatother
egreg
  • 1,121,712
  • 2
    Thanks, also. This is exactly the solution I was looking for. The underscore package was too aggressive for my purposes: It escapes things like \label{tag_with_underscores}, \input{file_with_underscores} and |short_verbatim_with_underscore|. A command that lets me have control of the process is perfect. – David Hammen Jun 19 '11 at 11:08
  • The last solution also works in caption etc. – fuenfundachtzig Sep 22 '11 at 08:35
  • @fuenfundachtzig Yes, it should, since it delays until the very last minute the interpretation of _. – egreg Sep 22 '11 at 08:39
  • @egreg: I used your last solution and together with @DavidCarlisle answer (http://is.gd/FOv6dA) it works very well. However, I tried to understand the magic for some time now and I fail. Can you please add some explanations? In particular, the order of grouping and the re-definition of _. – Dror Sep 11 '13 at 07:25
  • @Dror There's nothing special: the main command just calls \@activeus and then uses \scantokens so the argument will be reprocessed based on the current catcodes (where _ is active). The second part is the activation code: _ is made active and defined to be equivalent to \_. – egreg Sep 11 '13 at 08:43
  • Why the second part has the form \begingroup ... { \endgroup .. }? I thought groups have to be balanced. – Dror Sep 11 '13 at 09:19
  • @Dror They are balanced. ;-) The tokens in the argument to \lowercase are just subject to lowercasing and then reinserted without being interpreted. This is a trick to get an active _ without the need of explicitly activating it and avoids a global definition. – egreg Sep 11 '13 at 09:34
16
\documentclass{article}
\usepackage{url}
\DeclareUrlCommand\UScore{\urlstyle{rm}}
\begin{document}

foo \UScore{foo_bar_1} bar

\end{document}