summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/underscore/underscore.sty
blob: f0cfb895d196c5f9061747991b1f2cac3a756ed2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
% underscore.sty     21-Sep-2005   Donald Arseneau   asnd@triumf.ca
% Make the "_" character print as "\textunderscore" in text.
% Copyright 1998,2001,2005,2006 Donald Arseneau;  
% License: LPPL version 1.2 or later.
% Instructions follow after the definitions.

\ProvidesPackage{underscore}[2006/09/13]

\begingroup
 \catcode`\_=\active
 \gdef _{% \relax % No relax gives a small vulnerability in alignments
   \ifx\if@safe@actives\iftrue % must be outermost test!
      \string_%
   \else
      \ifx\protect\@typeset@protect
         \ifmmode \sb \else \BreakableUnderscore \fi
      \else
         \ifx\protect\@unexpandable@protect \noexpand_%
         \else \protect_%
      \fi\fi
    \fi}
  \global\let\ActiveUnderscore=_
  \gdef\normalUnderscoreDef{\let_\ActiveUnderscore}
\endgroup

% At begin: set catcode; fix \long \ttdefault so I can use it in comparisons; 
% reapply definition of active _ in output routine (\@firstofone to strip
% away braces, so avoiding deeper nesting).
\AtBeginDocument{%
  {\immediate\write\@auxout{\catcode\number\string`\_ \string\active}}%
  \catcode\string`\_\string=\active
  \edef\ttdefault{\ttdefault}%
  \output=\expandafter\expandafter\expandafter
     {\expandafter\expandafter\expandafter\normalUnderscoreDef
      \expandafter\@firstofone\the\output}%
}

\newcommand{\BreakableUnderscore}{\leavevmode\nobreak\hskip\z@skip
 \ifx\f@family\ttdefault \string_\else \textunderscore\fi
 \usc@dischyph\nobreak\hskip\z@skip}

\DeclareRobustCommand{\_}{%
  \ifmmode \nfss@text{\textunderscore}\else \BreakableUnderscore \fi}


\let\usc@dischyph\@dischyph
\DeclareOption{nohyphen}{\def\usc@dischyph{\discretionary{}{}{}}}
\DeclareOption{strings}{\catcode`\_=\active}

\ProcessOptions
\ifnum\catcode`\_=\active\else \endinput \fi

%%%%%%%%   Redefine commands that use character strings   %%%%%%%%

\@ifundefined{UnderscoreCommands}{\let\UnderscoreCommands\@empty}{}
\expandafter\def\expandafter\UnderscoreCommands\expandafter{%
  \UnderscoreCommands
  \do\include \do\includeonly
  \do\@input \do\@iinput \do\InputIfFileExists
  \do\ref \do\pageref \do\newlabel
  \do\bibitem \do\@bibitem \do\cite \do\nocite \do\bibcite
  \do\Ginclude@graphics \do\@setckpt
}

% Macro to redefine a macro to pre-process its string argument
% with \protect -> \string.
\def\do#1{% Avoid double processing if user includes command twice!
 \@ifundefined{US\string_\expandafter\@gobble\string#1}{%
   \edef\@tempb{\meaning#1}% Check if macro is just a protection shell...
   \def\@tempc{\protect}%
   \edef\@tempc{\meaning\@tempc\string#1\space\space}%
   \ifx\@tempb\@tempc % just a shell: hook into the protected inner command
     \expandafter\do
       \csname \expandafter\@gobble\string#1 \expandafter\endcsname
   \else % Check if macro takes an optional argument
     \def\@tempc{\@ifnextchar[}%
     \edef\@tempa{\def\noexpand\@tempa####1\meaning\@tempc}%
     \@tempa##2##3\@tempa{##2\relax}%
     \edef\@tempb{\meaning#1\meaning\@tempc}%
     \edef\@tempc{\noexpand\@tempd \csname
        US\string_\expandafter\@gobble\string#1\endcsname}%
     \if \expandafter\@tempa\@tempb \relax 12\@tempa % then no optional arg
       \@tempc #1\US@prot
     \else  % There is optional arg
       \@tempc #1\US@protopt
     \fi
   \fi
 }{}}

\def\@tempd#1#2#3{\let#1#2\def#2{#3#1}}

\def\US@prot#1#2{\let\@@protect\protect \let\protect\string
  \edef\US@temp##1{##1{#2}}\restore@protect\US@temp#1}
\def\US@protopt#1{\@ifnextchar[{\US@protarg#1}{\US@prot#1}}
\def\US@protarg #1[#2]{\US@prot{{#1[#2]}}}

\UnderscoreCommands
\let\do\relax \let\@tempd\relax  % un-do

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\endinput

underscore.sty    13-Sep-2006  Donald Arseneau

Features:
~~~~~~~~~
The "\_" command (which normally prints an underscore character or
facsimile) is altered so that the hyphenation of constituent words
is not affected, and hyphenation is permitted after the underscore.
For example, "compound\_fracture" hyphenates as com- pound\_- frac- ture.
If you prefer the underscore to break without a hyphen (but still with 
the same rules for explicit hyphen-breaks) then use the [nohyphen]
package option.

A simple "_" acts just like "\_" in text mode, but makes a subscript
in math mode: activation_energy $E_a$

Both forms use an underscore character if the font encoding contains
one (e.g., "\usepackage[T1]{fontenc}" or typewriter fonts in any encoding),
but they use a rule if there is no proper character.

Deficiencies:
~~~~~~~~~~~~~
The skips and penalties ruin any kerning with the underscore character
(when a character is used).  However, there doesn't seem to be much, if
any, such kerning in the ec fonts, and there is never any kerning with
a rule.

You must avoid "_" in file names and in cite or ref tags, or you must use 
the babel package, with its active-character controls, or you must give 
the [strings] option, which attempts to redefine several commands (and 
may not work perfectly).  Even without the [strings] option or babel, you 
can use occasional underscores like: "\include{file\string_name}".

Option: [strings]
~~~~~~~~~~~~~~~~~
The default operation is quite simple and needs no customization; but
you must avoid using "_" in any place where LaTeX uses an argument as
a string of characters for some control function or as a name.  These
include the tags for "\cite" and "\ref", file names for "\input", 
"\include", and "\includegraphics", environment names, counter names,
and placement parameters (like "[t]").  The problem with these contexts
is that they are `moving arguments' but LaTeX does not `switch on' the
"\protect" mechanism for them.

If you need to use the underscore character in these places, the package
option [strings] is provided to redefine commands that take such a string
argument so that protection is applied (with "\protect" being "\string").
The list of commands is given in "\UnderscoreCommands", with "\do" before
each; plus several others covering "\input", "\includegraphics, "\cite", 
"\ref", and their variants.  Not included are many commands regarding font 
names, everything with counter names, environment names, page styles, and 
versions of "\ref" and "\cite" defined by external packages (e.g., "\vref" 
and "\citeyear").

You can add to the list of supported commands by defining "\UnderscoreCommands"
before loading this package; e.g.

   \usepackage{chicago}
   \newcommand{\UnderscoreCommands}{%   (\cite already done)
     \do\citeNP \do\citeA \do\citeANP \do\citeN \do\shortcite
     \do\shortciteNP \do\shortciteA \do\shortciteANP \do\shortciteN
     \do\citeyear \do\citeyearNP
   }
   \usepackage[strings]{underscore}

Not all commands can be supported this way!  Only commands that take a
string argument *first* can be protected.  One optional argument before
the string argument is also permitted, as exemplified by "\cite": both
"\cite{tags}" and "\cite[text]{tags}" are allowed.  A command like
"\@addtoreset" which takes two counter names as arguments could not
be protected by listing it in "\UnderscoreCommands".

*When you use the [strings] option, you must load this package
last* (or nearly last).

There are two reasons: 1) The redefinitions done for protection must come
after other packages define their customized versions of those commands.
2) The [strings] option requires the "_" character to be activated immediately
in order for the cite and ref tags to be read properly from the .aux file
as plain strings, and this catcode setting might disrupt other packages.

The babel package implements a protection mechanism for many commands,
and will be a complete fix for most documents without the [strings] option.
Many add-on packages are compatible with babel, so they will get the
strings protection also.  However, there are several commands that are 
not covered by babel, but can easily be supported by the [strings] and 
"\UnderscoreCommands" mechanism.  Beware that using both [strings] and
babel might lead to conflicts, but none are seen yet (load babel last).

Implementation Notes:
~~~~~~~~~~~~~~~~~~~~~
The first setting of "_" to be an active character is performed in a local
group so as to not interfere with other packages.  The catcode setting
is repeated with "\AtBeginDocument" so the definition is in effect for the
text.  However, the catcode setting is repeated immediately when the
[strings] option is detected.

The definition of the active "_" is essentially:

       \ifmmode \sb \else \BreakableUnderscore \fi

where "\sb" retains the normal subscript meaning of "_" and where
"\BreakableUnderscore" is essentially "\_".  The rest of the definition
handles the "\protect"ion without causing "\relax" to be inserted before
the character.

"\BreakableUnderscore" uses "\nobreak\hskip\z@skip" to separate the
underscore from surrounding words, thus allowing TeX to hyphenate them,
but preventing free breaks around the underscore. Next, it checks the
current font family, and uses the underscore character from tt fonts or
otherwise "\textunderscore" (which is a character or rule depending on
the font encoding).  After the underscore, it inserts a discretionary
hyphenation point as "\usc@dischyph", which is usually just "\-"
except that it still works in the tabbing environment, although it
will give "\discretionary{}{}{}" under the [nohyphen] option.  After
that, another piece of non-breaking interword glue is inserted. 
Ordinarily, the comparison "\ifx\f@family\ttdefault" will always fail 
because "\ttdefault" is `long' whereas "\f@family" is not (boooo hisss),
but "\ttdefault" is redefined to be non-long by "\AtBeginDocument".

The "\_" command is then defined to use "\BreakableUnderscore".

If the [strings] option is not given, then that is all!

Under the [strings] option, the list of special commands is processed to:

 - retain the original command as "\US_"*command* (e.g., "\US_ref")
 - redefine the command as "\US@prot\US_command" for ordinary commands
   ("\US@prot\US_ref") or as "\US@protopt\US_command" when an optional
   argument is possible (e.g., "\US@protopt\US_bibitem").
 - self-protecting commands ("\cite") retain their self-protection.

Diagnosing the state of the pre-existing command is done by painful
contortions involving "\meaning".

"\US@prot" and "\US@protopt" read the argument, process it with 
"\protect" enabled, then invoke the saved "\US_command".

Modifications:
~~~~~~~~~~~~~~
13-Sep-2006  Reassert my definition in the output routine (listings).
21-Sep-2005  \includegraphics safe.
12-Oct-2001  Babel (safe@actives) compatibility and [nohyphen] option.

Test file integrity:  ASCII 32-57, 58-126:  !"#$%&'()*+,-./0123456789
:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~