1# -*- mode: Perl -*- 2# /=====================================================================\ # 3# | natbib | # 4# | Implementation for LaTeXML | # 5# |=====================================================================| # 6# | Part of LaTeXML: | # 7# | Public domain software, produced as part of work done by the | # 8# | United States Government & not subject to copyright in the US. | # 9# |---------------------------------------------------------------------| # 10# | Bruce Miller <bruce.miller@nist.gov> #_# | # 11# | http://dlmf.nist.gov/LaTeXML/ (o o) | # 12# \=========================================================ooo==U==ooo=/ # 13package LaTeXML::Package::Pool; 14use strict; 15use warnings; 16use LaTeXML::Package; 17 18#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19# natbib 20# following natbib.pdf document 21# The basic support function for citation styles is in LaTeX.pool 22# Other formatting support is in Post::MakeBibliography 23#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 25#====================================================================== 26# 5. Package Options 27 28# The kind of citation 29DeclareOption('numbers', sub { 30 setCitationStyle(numbers => 1); 31 ExecuteOptions('square', 'comma', 'nobibstyle'); }); 32DeclareOption('super', sub { 33 setCitationStyle(super => 1, open => Tokens(), close => Tokens()); 34 ExecuteOptions('nobibstyle'); }); 35DeclareOption('authoryear', sub { 36 setCitationStyle(authoryear => 1); 37 ExecuteOptions('round', 'semicolon', 'bibstyle'); }); 38# # The kind of braces around citations 39DeclareOption('round', sub { 40 setCitationStyle(round => 1); 41 ExecuteOptions('nobibstyle'); }); 42DeclareOption('curly', sub { 43 setCitationStyle(curly => 1); 44 ExecuteOptions('nobibstyle'); }); 45DeclareOption('square', sub { 46 setCitationStyle(square => 1); 47 ExecuteOptions('nobibstyle'); }); 48DeclareOption('angle', sub { 49 setCitationStyle(angle => 1); 50 ExecuteOptions('nobibstyle'); }); 51 52# The kind of separator between multiple citations 53DeclareOption('comma', sub { 54 setCitationStyle(comma => 1); 55 ExecuteOptions('nobibstyle'); }); 56DeclareOption('semicolon', sub { 57 setCitationStyle(semicolon => 1); 58 ExecuteOptions('nobibstyle'); }); 59DeclareOption('colon', sub { 60 ExecuteOptions('semicolon'); }); # SIC! 61 62# This disables any future \bibstyle found in the aux file (or from \bibliographystyle) 63DeclareOption('nobibstyle', sub { 64 Let('\bibstyle', '\@gobble'); }); 65DeclareOption('bibstyle', sub { 66 Let('\bibstyle', '\@citestyle'); }); 67 68# sorting options 69DeclareOption('sort', sub { }); 70DeclareOption('sort&compress', sub { }); 71DeclareOption('compress', sub { }); 72 73DeclareOption('longnamesfirst', sub { }); 74 75DeclareOption('openbib', sub { }); 76DeclareOption('sectionbib', sub { 77 AssignMapping('BACKMATTER_ELEMENT', 'ltx:bibliography' => 'ltx:section'); }); 78DeclareOption('nonamebreak', sub { }); 79 80# They _say_ round & semicolon but ... 81#ExecuteOptions('round','semicolon','authoryear'); 82#ExecuteOptions('square','comma','authoryear'); 83setCitationStyle(round => 1, semicolon => 1); 84 85# NOTE \bibliographystyle puts \bibstyle in the *.aux, read at the beginning! 86# Normally, \bibliography appears at the end next to the bibliography.... it's TOO LATE! 87# [FUTURE: Maybe this can be encoded as attributes on ltx:bibliography ??? 88# But then we need to put in stub elements to be filled in by CrossRef! Ugh] 89# In any case, \bibstyle may get redefined by options, so define it now! 90DefMacro('\bibstyle{}', sub { 91 my $style = T_CS('\bibstyle@' . ToString($_[1])); 92 (LookupDefinition($style) ? ($style) : (T_CS('\relax'))); }); 93#AtBeginDocument{\global\let\bibstyle=\@gobble} 94Let('\@citestyle', '\bibstyle'); 95 96# # They _say_ round & semicolon but ... 97ExecuteOptions('round', 'semicolon', 'authoryear'); 98# ExecuteOptions('square','comma','authoryear'); 99AssignValue(CITE_STYLE => 'authoryear'); # the default? 100 101ProcessOptions(); 102#====================================================================== 103# 2.3 Basic Citation Commands 104 105# Leverage the definitions in LaTeX.pool. 106 107# Note that LaTeX's \cite command is treated almost equivalent to \citet in authoryear mode, 108# but like \citep in numbers mode. 109DefMacro('\cite OptionalMatch:* [][] Semiverbatim', sub { 110 my ($gullet, $star, $pre, $post, $keys) = @_; 111 my ($style, $open, $close, $ns, $ay) 112 = map { LookupValue($_) } qw(CITE_STYLE CITE_OPEN CITE_CLOSE CITE_NOTE_SEPARATOR CITE_AY_SEPARATOR); 113 if (!$post) { ($pre, $post) = (undef, $pre); } 114 $pre = undef unless $pre && $pre->unlist; 115 $post = undef unless $post && $post->unlist; 116 my $author = ($star ? "FullAuthors" : "Authors"); 117 if ($style eq 'numbers') { 118 Invocation(T_CS('\@@cite'), 119 Tokens(Explode('cite')), 120 Tokens($open, ($pre ? ($pre, T_SPACE) : ()), 121 Invocation(T_CS('\@@bibref'), Tokens(Explode("Number")), $keys, undef, undef), 122 ($post ? ($ns, T_SPACE, $post) : ()), 123 $close)); } 124 elsif ($style eq 'super') { 125 Invocation(T_CS('\@@cite'), 126 Tokens(Explode('cite')), 127 Tokens(($pre ? ($pre, T_SPACE) : ()), Invocation(T_CS('\textsuperscript'), 128 Invocation(T_CS('\@@bibref'), Tokens(Explode("Number")), $keys, 129 undef, undef)), 130 ($post ? (T_SPACE, $post) : ()))); } 131 else { 132 # Appears to be textual, unless pre or post phrase, then parenthetical (!) 133 if ($pre || $post) { 134 Invocation(T_CS('\@@cite'), 135 Tokens(Explode('cite')), 136 Tokens($open->unlist, ($pre ? ($pre, T_SPACE) : ()), 137 Invocation(T_CS('\@@bibref'), 138 Tokens(Explode($author . "Phrase1Year")), 139 $keys, 140 Invocation(T_CS('\@@citephrase'), 141 Tokens($ay->unlist, T_SPACE)), undef), 142 ($post ? ($ns, T_SPACE, $post) : ()), $close)); } 143 else { 144 Invocation(T_CS('\@@cite'), 145 Tokens(Explode('cite')), 146 Invocation(T_CS('\@@bibref'), 147 Tokens(Explode($author . " Phrase1YearPhrase2")), 148 $keys, 149 Invocation(T_CS('\@@citephrase'), $open), 150 Invocation(T_CS('\@@citephrase'), $close))); } } 151}, locked => 1); 152 153DefMacro('\citet OptionalMatch:* [][] Semiverbatim', sub { 154 my ($gullet, $star, $pre, $post, $keys) = @_; 155 my ($style, $open, $close, $ns) 156 = map { LookupValue($_) } qw(CITE_STYLE CITE_OPEN CITE_CLOSE CITE_NOTE_SEPARATOR); 157 if (!$post) { ($pre, $post) = (undef, $pre); } 158 $pre = undef unless $pre && $pre->unlist; 159 $post = undef unless $post && $post->unlist; 160 my $author = ($star ? "FullAuthors" : "Authors"); 161 if ($style eq 'numbers') { 162 Invocation(T_CS('\@@cite'), 163 Tokens(Explode('citet')), 164 Tokens( #($pre ? ($pre, T_SPACE) : ()), 165 Invocation(T_CS('\@@bibref'), 166 Tokens(Explode("$author Phrase1NumberPhrase2")), 167 $keys, 168 Invocation(T_CS('\@@citephrase'), 169 Tokens($open, ($pre ? ($pre, T_SPACE) : ()))), 170 Invocation(T_CS('\@@citephrase'), 171 Tokens(($post ? ($ns->unlist, T_SPACE, $post->unlist) : ()), $close->unlist)) 172 )))->unlist; } 173 elsif ($style eq 'super') { 174 Invocation(T_CS('\@@cite'), 175 Tokens(Explode('citet')), 176 Tokens(($pre ? ($pre, T_SPACE) : ()), 177 Invocation(T_CS('\@@bibref'), 178 Tokens(Explode("$author Phrase1SuperPhrase2")), 179 $keys, undef, undef)->unlist, 180 ($post ? ($ns, T_SPACE, $post->unlist) : ()))); } 181 else { 182 Invocation(T_CS('\@@cite'), 183 Tokens(Explode('citet')), 184 Invocation(T_CS('\@@bibref'), 185 Tokens(Explode("$author Phrase1YearPhrase2")), 186 $keys, 187 Invocation(T_CS('\@@citephrase'), 188 Tokens($open, ($pre ? ($pre, T_SPACE) : ()))), 189 Invocation(T_CS('\@@citephrase'), 190 Tokens(($post ? ($ns, T_SPACE, $post) : ()), $close)))); } 191}, locked => 1); 192 193DefMacro('\citep OptionalMatch:* [][] Semiverbatim', sub { 194 my ($gullet, $star, $pre, $post, $keys) = @_; 195 my ($style, $open, $close, $ns, $ay) 196 = map { LookupValue($_) } qw(CITE_STYLE CITE_OPEN CITE_CLOSE 197 CITE_NOTE_SEPARATOR CITE_AY_SEPARATOR); 198 if (!$post) { ($pre, $post) = (undef, $pre); } 199 $pre = undef unless $pre && $pre->unlist; 200 $post = undef unless $post && $post->unlist; 201 my $author = ($star ? "FullAuthors" : "Authors"); 202 203 if ($style eq 'numbers') { 204 Invocation(T_CS('\@@cite'), 205 Tokens(Explode('citep')), 206 Tokens($open, ($pre ? ($pre, T_SPACE) : ()), 207 Invocation(T_CS('\@@bibref'), Tokens(Explode("Number")), $keys, undef, undef), 208 ($post ? ($ns, T_SPACE, $post) : ()), $close)); } 209 elsif ($style eq 'super') { 210 Invocation(T_CS('\@@cite'), 211 Tokens(Explode('citep')), 212 Tokens(($pre ? ($pre, T_SPACE) : ()), 213 Invocation(T_CS('\@@bibref'), Tokens(Explode("Super")), $keys, undef, undef), 214 ($post ? (T_SPACE, $post) : ()))); } 215 else { 216 Invocation(T_CS('\@@cite'), 217 Tokens(Explode('citep')), 218 Tokens($open->unlist, ($pre ? ($pre, T_SPACE) : ()), 219 Invocation(T_CS('\@@bibref'), 220 Tokens(Explode("${author}Phrase1Year")), 221 $keys, 222 Invocation(T_CS('\@@citephrase'), Tokens($ay->unlist, T_SPACE)), 223 undef), 224 ($post ? ($ns, T_SPACE, $post) : ()), $close)); } 225}, locked => 1); 226 227#====================================================================== 228# 2.4 Extended Citation Commands 229DefMacro('\@@cite@noparens', sub { 230 AssignValue(CITE_OPEN => Tokens()); 231 AssignValue(CITE_CLOSE => Tokens()); }); 232 233# The next two are the same as \citet, \citep, but redefine open & close to empty. 234DefMacro('\citealt OptionalMatch:* [][] Semiverbatim', sub { 235 my ($gullet, $star, $pre, $post, $keys) = @_; 236 (T_CS('\bgroup'), T_CS('\@@cite@noparens'), 237 Invocation(T_CS('\citet'), $star, $pre, $post, $keys)->unlist, 238 T_CS('\egroup')); }); 239 240DefMacro('\citealp OptionalMatch:* [][] Semiverbatim', sub { 241 my ($gullet, $star, $pre, $post, $keys) = @_; 242 (T_CS('\bgroup'), T_CS('\@@cite@noparens'), 243 Invocation(T_CS('\citep'), $star, $pre, $post, $keys)->unlist, 244 T_CS('\egroup')); }); 245 246DefMacro('\citenum Semiverbatim', sub { # No optional ? 247 my ($gullet, $keys) = @_; 248 Invocation(T_CS('\@@cite'), 249 Tokens(Explode('citenum')), 250 Tokens(Invocation(T_CS('\@@bibref'), Tokens(Explode("Number")), $keys, undef, undef))); }); 251 252# Sorta right, but would like to avoid the nested <ltx:cite>! 253# maybe can neutralize \@@cite? 254DefMacro('\citetext', '\@@cite'); 255 256DefMacro('\citeauthor OptionalMatch:* [][] Semiverbatim', sub { 257 my ($gullet, $star, $pre, $post, $keys) = @_; 258 my $author = ($star ? "FullAuthors" : "Authors"); 259 if (!$post) { ($pre, $post) = (undef, $pre); } 260 $pre = undef unless $pre && $pre->unlist; 261 $post = undef unless $post && $post->unlist; 262 my $ns = LookupValue('CITE_NOTE_SEPARATOR'); 263 Invocation(T_CS('\@@cite'), 264 Tokens(Explode('citeauthor')), 265 Tokens( # ($pre ? ($pre, T_SPACE) : ()), 266 Invocation(T_CS('\@@bibref'), Tokens(Explode($author)), $keys, undef, undef), 267 ($post ? ($ns, T_SPACE, $post) : ()))); }); 268 269DefMacro('\citefullauthor [][] Semiverbatim', sub { 270 my ($gullet, $pre, $post, $keys) = @_; 271 if (!$post) { ($pre, $post) = (undef, $pre); } 272 $pre = undef unless $pre && $pre->unlist; 273 $post = undef unless $post && $post->unlist; 274 my $ns = LookupValue('CITE_NOTE_SEPARATOR'); 275 Invocation(T_CS('\@@cite'), 276 Tokens(Explode('citefullauthor')), 277 Tokens( # ($pre ? ($pre, T_SPACE) : ()), 278 Invocation(T_CS('\@@bibref'), Tokens(Explode("FullAuthors")), $keys, undef, undef), 279 ($post ? ($ns, T_SPACE, $post) : ()))); }); 280 281DefMacro('\citeyear [][] Semiverbatim', sub { 282 my ($gullet, $pre, $post, $keys) = @_; 283 if (!$post) { ($pre, $post) = (undef, $pre); } 284 $pre = undef unless $pre && $pre->unlist; 285 $post = undef unless $post && $post->unlist; 286 my $ns = LookupValue('CITE_NOTE_SEPARATOR'); 287 Invocation(T_CS('\@@cite'), 288 Tokens(Explode('citeyear')), 289 Tokens( # ($pre ? ($pre, T_SPACE) : ()), 290 Invocation(T_CS('\@@bibref'), Tokens(Explode("Year")), $keys, undef, undef), 291 ($post ? ($ns, T_SPACE, $post) : ()))); }); 292 293DefMacro('\citeyearpar [][] Semiverbatim', sub { 294 my ($gullet, $pre, $post, $keys) = @_; 295 my ($open, $close) = map { LookupValue($_) } qw(CITE_OPEN CITE_CLOSE); 296 if (!$post) { ($pre, $post) = (undef, $pre); } 297 $pre = undef unless $pre && $pre->unlist; 298 $post = undef unless $post && $post->unlist; 299 my $ns = LookupValue('CITE_NOTE_SEPARATOR'); 300 Invocation(T_CS('\@@cite'), 301 Tokens(Explode('citeyearpar')), 302 Tokens($open, 303 ($pre ? ($pre, T_SPACE) : ()), 304 Invocation(T_CS('\@@bibref'), Tokens(Explode("Year")), $keys, undef, undef), 305 ($post ? ($ns, T_SPACE, $post) : ()), 306 $close)); }); 307 308#====================================================================== 309# 2.5 Forcing Upper Cased Name 310# These are SUPPOSED to capitalize the first letter, .. but 311DefMacro('\Citet', '\citet'); 312DefMacro('\Citep', '\citep'); 313DefMacro('\Citealt', '\citealt'); 314DefMacro('\Citealp', '\citealp'); 315DefMacro('\Citeauthor', '\citeauthor'); 316 317#====================================================================== 318# 2.6 Citation Aliasing 319# Citation aliasing is achieved with 320# \defcitealias{key}{text} 321# \citetalias{key} ==>> text 322# \citepalias{key} ==>> (text) 323 324# should end the defined key with \@extra@b@citeb ??? 325 326DefPrimitive('\defcitealias Semiverbatim {}', sub { 327 my ($gullet, $key, $text) = @_; 328 DefMacroI(T_CS('\al@' . ToString($key)), undef, $text); }); 329 330# These use the above defined text to fill in the bibref 331# (which will still be a link to the bibitem!) 332DefMacro('\citetalias [][] Semiverbatim', sub { 333 my ($gullet, $pre, $post, $key) = @_; 334 my ($open, $close) = map { LookupValue($_) } qw(CITE_OPEN CITE_CLOSE); 335 if (!$post) { ($pre, $post) = (undef, $pre); } 336 $pre = undef unless $pre && $pre->unlist; 337 $post = undef unless $post && $post->unlist; 338 Invocation(T_CS('\@@cite'), 339 Tokens(Explode('citealias')), 340 Tokens(($pre ? ($pre, T_SPACE) : ()), 341 Invocation(T_CS('\@@bibref'), 342 Tokens(Explode("Phrase1")), 343 $key, 344 Invocation(T_CS('\@@citephrase'), T_CS('\al@' . ToString($key)))), 345 ($post ? (T_SPACE, $post) : ()))); }); 346 347DefMacro('\citepalias [][] Semiverbatim', sub { 348 my ($gullet, $pre, $post, $key) = @_; 349 my ($open, $close, $ns) = map { LookupValue($_) } qw(CITE_OPEN CITE_CLOSE CITE_NOTE_SEPARATOR); 350 Invocation(T_CS('\@@cite'), 351 Tokens(Explode('citepalias')), 352 Tokens($open, 353 ($pre ? ($pre, T_SPACE) : ()), 354 Invocation(T_CS('\@@bibref'), 355 Tokens(Explode("Phrase1")), 356 $key, 357 Invocation(T_CS('\@@citephrase'), T_CS('\al@' . ToString($key)))), 358 ($post ? ($ns, T_SPACE, $post) : ()), 359 $close)); }); 360 361#====================================================================== 362# 2.9 Selecting Citation Punctuation 363DefKeyVal('natbib', 'authoryear', '', 'true'); 364DefKeyVal('natbib', 'numbers', '', 'true'); 365DefKeyVal('natbib', 'super', '', 'true'); 366DefKeyVal('natbib', 'round', '', 'true'); 367DefKeyVal('natbib', 'square', '', 'true'); 368DefKeyVal('natbib', 'open', ''); 369DefKeyVal('natbib', 'close', ''); 370DefKeyVal('natbib', 'semicolon', ''); 371DefKeyVal('natbib', 'comma', ''); 372DefKeyVal('natbib', 'citesep', ''); 373DefKeyVal('natbib', 'aysep', ''); 374DefKeyVal('natbib', 'yysep', ''); 375DefKeyVal('natbib', 'notesep', ''); 376 377AssignValue(CITE_AY_SEPARATOR => T_OTHER(',')); 378 379sub setCitationStyle { 380 my (@pairs) = @_; 381 while (@pairs) { 382 my ($key, $value) = (shift(@pairs), shift(@pairs)); 383 $key = ToString(Digest($key)) if ref $key; 384 if ($key eq 'authoryear') { AssignValue(CITE_STYLE => 'authoryear'); } 385 elsif ($key eq 'numbers') { AssignValue(CITE_STYLE => 'numbers'); } 386 elsif ($key eq 'super') { AssignValue(CITE_STYLE => 'super'); } 387 elsif ($key eq 'round') { AssignValue(CITE_OPEN => T_OTHER('(')); 388 AssignValue(CITE_CLOSE => T_OTHER(')')); } 389 elsif ($key eq 'square') { AssignValue(CITE_OPEN => T_OTHER('[')); 390 AssignValue(CITE_CLOSE => T_OTHER(']')); } 391 elsif ($key eq 'curly') { AssignValue(CITE_OPEN => T_OTHER('{')); 392 AssignValue(CITE_CLOSE => T_OTHER('}')); } 393 elsif ($key eq 'angle') { AssignValue(CITE_OPEN => T_OTHER('<')); 394 AssignValue(CITE_CLOSE => T_OTHER('>')); } 395 elsif ($key eq 'open') { AssignValue(CITE_OPEN => $value); } 396 elsif ($key eq 'close') { AssignValue(CITE_CLOSE => $value); } 397 elsif ($key eq 'semicolon') { AssignValue(CITE_SEPARATOR => T_OTHER(';')); } 398 elsif ($key eq 'comma') { AssignValue(CITE_SEPARATOR => T_OTHER(',')); } 399 elsif ($key eq 'aysep') { AssignValue(CITE_AY_SEPARATOR => $value); } 400 elsif ($key eq 'yysep') { AssignValue(CITE_YY_SEPARATOR => $value); } 401 elsif ($key eq 'notesep') { AssignValue(CITE_NOTE_SEPARATOR => $value); } 402 else { 403 Warn('unexpected', $key, undef, "Unexpected Citation Style keyword '$key'"); } } 404 return; } 405 406DefPrimitive('\setcitestyle RequiredKeyVals:natbib', sub { 407 setCitationStyle($_[1]->getPairs); }); 408 409DefPrimitive('\bibpunct[]{}{}{}{}{}{}', sub { 410 my ($stomach, $notesep, $open, $close, $sep, $style, $aysep, $yysep) = @_; 411 $style = ToString(Digest($style)); 412 AssignValue(CITE_OPEN => $open); 413 AssignValue(CITE_CLOSE => $close); 414 AssignValue(CITE_SEPARATOR => $sep); 415 AssignValue(CITE_STYLE => ($style eq 'n' ? 'numbers' : ($style eq 's' ? 'super' : 'authoryear'))); 416 AssignValue(CITE_AY_SEPARATOR => $aysep); 417 AssignValue(CITE_YY_SEPARATOR => $yysep); 418 AssignValue(CITE_NOTE_SEPARATOR => $notesep) if $notesep; 419 return; }); 420 421DefMacro('\citestyle{}', '\@citestyle{#1}\let\bibstyle\@gobble'); 422 423DefMacro('\bibstyle@chicago', '\bibpunct{(}{)}{;}{a}{,}{,}'); 424DefMacro('\bibstyle@named', '\bibpunct{[}{]}{;}{a}{,}{,}'); 425DefMacro('\bibstyle@agu', '\bibpunct{[}{]}{;}{a}{,}{,~}'); #Amer. Geophys. Union 426DefMacro('\bibstyle@copernicus', '\bibpunct{(}{)}{;}{a}{,}{,}'); #Copernicus Publications 427Let('\bibstyle@egu', '\bibstyle@copernicus'); 428Let('\bibstyle@egs', '\bibstyle@copernicus'); 429DefMacro('\bibstyle@agsm', '\bibpunct{(}{)}{,}{a}{}{,}\gdef\harvardand{\&}'); 430DefMacro('\bibstyle@kluwer', '\bibpunct{(}{)}{,}{a}{}{,}\gdef\harvardand{\&}'); 431DefMacro('\bibstyle@dcu', '\bibpunct{(}{)}{;}{a}{;}{,}\gdef\harvardand{and}'); 432DefMacro('\bibstyle@aa', '\bibpunct{(}{)}{;}{a}{}{,}'); # Astronomy & Astrophysics 433DefMacro('\bibstyle@pass', '\bibpunct{(}{)}{;}{a}{,}{,}'); #Planet. & Space Sci 434DefMacro('\bibstyle@anngeo', '\bibpunct{(}{)}{;}{a}{,}{,}'); #Annales Geophysicae 435DefMacro('\bibstyle@nlinproc', '\bibpunct{(}{)}{;}{a}{,}{,}'); #Nonlin.Proc.Geophys. 436DefMacro('\bibstyle@cospar', '\bibpunct{/}{/}{,}{n}{}{}'); 437DefMacro('\bibstyle@esa', '\bibpunct{(Ref.~}{)}{,}{n}{}{}'); 438DefMacro('\bibstyle@nature', '\bibpunct{}{}{,}{s}{}{\textsuperscript{,}}'); 439DefMacro('\bibstyle@plain', '\bibpunct{[}{]}{,}{n}{}{,}'); 440Let('\bibstyle@alpha', '\bibstyle@plain'); 441Let('\bibstyle@abbrv', '\bibstyle@plain'); 442Let('\bibstyle@unsrt', '\bibstyle@plain'); 443DefMacro('\bibstyle@plainnat', '\bibpunct{[}{]}{,}{a}{,}{,}'); 444Let('\bibstyle@abbrvnat', '\bibstyle@plainnat'); 445Let('\bibstyle@unsrtnat', '\bibstyle@plainnat'); 446 447#====================================================================== 448# 2.12 Other Formatting Options 449# mostly ignored... 450DefMacro('\bibsection', ''); 451DefMacro('\bibpreamble', ''); 452DefMacro('\bibfont', ''); 453DefMacro('\citenumfont', ''); 454DefMacro('\bibnumfmt{}', '#1'); 455DefRegister('\bibhang', Dimension(0)); 456DefRegister('\bibsep', Dimension(0)); 457 458#====================================================================== 459# 2.13 Automatic Indexing of Citations 460# Ignored, but could be done... 461# However, it is basically equivalent to backrefs which are 462# automatically handled in MakeBibliography, anyway... 463RawTeX('\newif\ifciteindex'); 464DefMacro('\citeindextrue', ''); 465DefMacro('\citeindexfalse', ''); 466DefMacro('\citeindextype', ''); 467 468#====================================================================== 469# 2.17 Long Author List on First Citation 470# Ignored (for now...) 471DefMacro('\shortcites Semiverbatim', ''); 472 473#====================================================================== 474# Less Documented 475# For manually formatted bibliographies, the following magical incantations 476# will be recognized to deliniate the author and year: 477# \bibitem[Jones et al.(1990)]{key}... 478# \bibitem[Jones et al.(1990)Jones, Baker, and Williams]{key}... 479# \bibitem[Jones et al., 1990]{key}... 480# \bibitem[\protect\citeauthoryear{Jones, Baker, and Williams}{Jones et al.}{1990}]{key}... 481# \bibitem[\protect\citeauthoryear{Jones et al.}{1990}]{key}... 482# \bibitem[\protect\astroncite{Jones et al.}{1990}]{key}... 483# \bibitem[\protect\citename{Jones et al., }1990]{key}... 484# \harvarditem[Jones et al.]{Jones, Baker, and Williams}{1990}{key}... 485 486DefMacro('\bibitem', '\reset@natbib@cites\refstepcounter{@bibitem}\@ifnextchar[{\@lbibitem}{\@lbibitem[\the@bibitem]}', locked => 1); 487 488RawTeX(<<'EOTeX'); 489%%% 490\def\citeauthoryear#1#2#3(@)(@)\@nil#4{% 491 \if\relax#3\relax 492 \NAT@wrout{\the@bibitem}{#2}{#1}{}{#4}\else 493 \NAT@wrout{\the@bibitem}{#3}{#2}{#1}{#4}\fi} 494\let\natbib@citeauthoryear\citeauthoryear 495\def\astroncite#1#2(@)(@)\@nil#3{% 496 \NAT@wrout{\the@bibitem}{#2}{#1}{}{#3}} 497\let\natbib@astroncite\astroncite 498\def\citename#1#2(@)(@)\@nil#3{% 499 \expandafter\NAT@apalk#1#2, \@nil{#3}} 500\let\natbib@citename\citename 501\newcommand\harvarditem[4][]{% 502 \if\relax#1\relax\bibitem[#2(#3)]{#4}\else\bibitem[#1(#3)#2]{#4}\fi } 503%%%% 504\newcommand\NAT@ifcmd{\futurelet\NAT@temp\NAT@ifxcmd} 505\newcommand\NAT@ifxcmd{\ifx\NAT@temp\relax\else\expandafter\NAT@bare\fi} 506\def\NAT@bare#1(#2)#3(@)#4\@nil#5{% 507 \if @#2% 508 \expandafter\NAT@apalk#1, , \@nil{#5}\else 509 \NAT@wrout{\the@bibitem}{#2}{#1}{#3}{#5}\fi} 510\def\NAT@apalk#1, #2, #3\@nil#4{% 511 \if\relax#2\relax\NAT@wrout{#1}{}{}{}{#4}\else\NAT@wrout{\the@bibitem}{#2}{#1}{}{#4}\fi} 512%%%% 513EOTeX 514# Sometimes, perversely, redefined, so re-redefine them now... 515DefPrimitiveI('\reset@natbib@cites', undef, sub { 516 Let('\citeauthoryear', '\natbib@citeauthoryear'); 517 Let('\astroncite', '\natbib@astroncite'); 518 Let('\citename', '\natbib@citename'); }); 519 520# By this time, \NAT@wrout should look like: 521# \NAT@wrout{number}{year}{authors}{fullauthors}{bibkey} 522# So, we'll do one extra step, and format the refnum form 523DefMacro('\NAT@wrout{}{}{}{} Semiverbatim', sub { 524 my ($gullet, $number, $year, $authors, $fullauthors, $key) = @_; 525 my ($style, $open, $close) = map { LookupValue($_) } qw(CITE_STYLE CITE_OPEN CITE_CLOSE); 526 $style = 'number' unless $authors->unlist && $year->unlist; 527 if ($style eq 'number') { 528 Invocation(T_CS('\NAT@@wrout'), $number, $year, $authors, $fullauthors, 529 Tokens($open, $number, $close), 530 $key)->unlist; } 531 else { 532 Invocation(T_CS('\NAT@@wrout'), $number, $year, $authors, $fullauthors, 533 Tokens($authors, T_SPACE, $open, $year, $close), 534 $key)->unlist; } }); 535 536DefConstructor('\NAT@@wrout{}{}{}{}{} Semiverbatim', 537 "<ltx:tags>" 538 . "?#1(<ltx:tag role='number'>#1</ltx:tag>)" 539 . "?#2(<ltx:tag role='year'>#2</ltx:tag>)" 540 . "?#3(<ltx:tag role='authors'>#3</ltx:tag>)" 541 . "?#4(<ltx:tag role='fullauthors'>#4</ltx:tag>)" 542 . "?#5(<ltx:tag role='refnum'>#5</ltx:tag>)" 543 . "?#6(<ltx:tag role='key'>#6</ltx:tag>)" 544 . "</ltx:tags>", 545 # Allow plain & in here ??? 546 bounded => 1, beforeDigest => sub { Let(T_ALIGN, '\&'); } 547); 548 549# see arXiv:cond-mat/0003435 for 550# an infinite loop we run into when this isn't locked 551# \@@lbibitem is a DefConstructor, so the connection should be kept 552DefMacro('\@lbibitem[]{}', '\@@lbibitem{#2}\NAT@ifcmd#1(@)(@)\@nil{#2}\newblock', locked => 1); 553 554# Similar to the one defined in LaTeX.pool, but the bibtag's have been setup above. 555DefConstructor('\@@lbibitem Semiverbatim', 556 "<ltx:bibitem key='#key' xml:id='#id'>", 557 afterDigest => sub { 558 my $key = CleanBibKey($_[1]->getArg(1)); 559 my $id = ToString(Expand(T_CS('\the@bibitem@ID'))); 560 $_[1]->setProperties(key => $key, id => $id); }); 561 562#====================================================================== 563# These macros allow you to get the pieces used in the current style 564# but don't seem to be used in natbib, so redefining them does nothing. 565DefMacro('\citestarts', sub { LookupValue('CITE_OPEN')->unlist; }); 566DefMacro('\citeends', sub { LookupValue('CITE_CLOSE')->unlist; }); 567DefMacro('\betweenauthors', 'and'); 568 569DefMacro('\harvardleft', sub { LookupValue('CITE_OPEN')->unlist; }); 570DefMacro('\harvardright', sub { LookupValue('CITE_CLOSE')->unlist; }); 571DefMacro('\harvardyearleft', sub { LookupValue('CITE_OPEN')->unlist; }); 572DefMacro('\harvardyearright', sub { LookupValue('CITE_CLOSE')->unlist; }); 573DefMacro('\harvardand', 'and'); 574 575DefConstructor('\harvardurl Semiverbatim', 576 "<ltx:ref href='#href'>#1</ltx:ref>", 577 properties => sub { (href => CleanURL(ToString($_[1]))); }); 578 579Let('\citeN', '\cite'); 580Let('\shortcite', '\cite'); 581Let('\citeasnoun', '\cite'); 582 583DefMacro('\natexlab{}', '#1'); # ???? 584 5851; 586