bibtex.el 98 KB
Newer Older
Eric S. Raymond's avatar
Eric S. Raymond committed
1 2
;;; bibtex.el --- BibTeX mode for GNU Emacs

3
;; Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
4

5
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
Richard M. Stallman's avatar
Richard M. Stallman committed
6
;;      Bengt Martensson <bengt@mathematik.uni-Bremen.de>
Eric S. Raymond's avatar
Eric S. Raymond committed
7 8 9
;;	Mark Shapiro <shapiro@corto.inria.fr>
;;	Mike Newton <newton@gumby.cs.caltech.edu>
;;	Aaron Larson <alarson@src.honeywell.com>
10
;; Maintainer: Stefan Schoef <schoef@offis.uni-oldenburg.de>
11
;; Keywords: BibTeX, LaTeX, TeX
Eric S. Raymond's avatar
Eric S. Raymond committed
12

Jim Blandy's avatar
Jim Blandy committed
13 14 15 16
;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
Richard M. Stallman's avatar
Richard M. Stallman committed
17
;; the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
18 19 20 21 22 23 24 25
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
Erik Naggum's avatar
Erik Naggum committed
26 27 28
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
Jim Blandy's avatar
Jim Blandy committed
29

30
;;; Commentary:
Erik Naggum's avatar
Erik Naggum committed
31

32
;;  Major mode for editing and validating BibTeX files.
Eric S. Raymond's avatar
Eric S. Raymond committed
33

34
;;  Usage:
35 36
;;  See documentation for function bibtex-mode (or type "\M-x describe-mode"
;;  when you are in bibtex-mode).
Eric S. Raymond's avatar
Eric S. Raymond committed
37

38 39
;;  Todo:
;;  Distribute texinfo file.
40

41
;;  Known Bugs:
42 43 44 45 46 47
;;   1. using regular expressions to match the entire BibTeX entry dies
;;      on long entries (e.g. those containing abstracts) since
;;      the length of regular expression matches is fairly limited.
;;   2. Calling bibtex-find-text in a string entry results in the
;;      error message "Can't find enclosing Bibtex field" instead of
;;      moving to the empty string. [reported by gernot@cs.unsw.oz.au]
Eric S. Raymond's avatar
Eric S. Raymond committed
48

49
;; (current keeper: schoef@offis.uni-oldenburg.de
50 51 52
;;  previous: alarson@src.honeywell.com)

;;; Code:
Erik Naggum's avatar
Erik Naggum committed
53

54
;; User Options:
Eric S. Raymond's avatar
Eric S. Raymond committed
55

56
(defvar bibtex-field-left-delimiter "{"
57 58 59
  "*Set this to { or \" according to your personal preferences.
This variable is buffer local.")
(make-variable-buffer-local 'bibtex-field-left-delimiter)
Jim Blandy's avatar
Jim Blandy committed
60

61
(defvar bibtex-field-right-delimiter "}"
62 63 64
  "*Set this to } or \" according to your personal preferences.
This variable is buffer local.")
(make-variable-buffer-local 'bibtex-field-right-delimiter)
65 66 67

(defvar bibtex-include-OPTcrossref '("InProceedings" "InCollection")
  "*All entries listed here will have an OPTcrossref field.")
Eric S. Raymond's avatar
Eric S. Raymond committed
68

Jim Blandy's avatar
Jim Blandy committed
69
(defvar bibtex-include-OPTkey t
Jim Blandy's avatar
Jim Blandy committed
70
  "*If non-nil, all entries will have an OPTkey field.")
71

Jim Blandy's avatar
Jim Blandy committed
72
(defvar bibtex-include-OPTannote t
Jim Blandy's avatar
Jim Blandy committed
73
  "*If non-nil, all entries will have an OPTannote field.")
Jim Blandy's avatar
Jim Blandy committed
74

75 76 77 78 79 80 81 82 83
(defvar bibtex-mode-user-optional-fields nil
  "*List of optional fields the user wants to have always present.
Entries should be lists of strings with two elements (first element =
name of the field, second element = comment to appear in the echo area).")

(defvar bibtex-clean-entry-zap-empty-opts t
  "*If non-nil, bibtex-clean-entry will delete all empty optional fields.")

(defvar bibtex-sort-ignore-string-entries t
84
  "*If non-nil, BibTeX @STRING entries are not sort-significant.
85
That means they are ignored when determining ordering of the buffer
86 87 88
(e.g. sorting, locating alphabetical position for new entries, etc.).
This variable is buffer local.")
(make-variable-buffer-local 'bibtex-sort-ignore-string-entries)
Eric S. Raymond's avatar
Eric S. Raymond committed
89

90
(defvar bibtex-maintain-sorted-entries nil
91
  "*If non-nil, bibtex-mode maintains all BibTeX entries in sorted order.
92
Setting this variable to nil will strip off some comfort (e.g. TAB
93 94 95 96
completion for reference keys in minibuffer, automatic detection of
duplicates) from bibtex-mode. See also bibtex-sort-ignore-string-entries.
This variable is buffer local.")
(make-variable-buffer-local 'bibtex-maintain-sorted-entries)
97

98 99 100 101 102 103 104
(defvar bibtex-parse-keys-timeout auto-save-timeout
  "*Specifies interval for parsing buffer for keys.
The buffer is checked every bibtex-parse-keys-timeout seconds if it is
modified since last parsing and is parsed if necessary. This is needed
only if buffer is maintained sorted (bibtex-maintain-sorted-entries
non-nil).")

105 106 107
(defvar bibtex-entry-field-alist
  '(
    ("Article" . (((("author" "Author1 [and Author2 ...] [and others]")
108
                    ("title" "Title of the article (BibTeX converts it to lowercase)")
109 110 111 112 113 114 115 116
                    ("journal" "Name of the journal (use string, remove braces)")
                    ("year" "Year of publication"))
		   (("volume" "Volume of the journal")
                    ("number" "Number of the journal")
                    ("month" "Month of the publication as a string (remove braces)")
                    ("pages" "Pages in the journal")
                    ("note" "Remarks to be put at the end of the \\bibitem")))
		  ((("author" "Author1 [and Author2 ...] [and others]")
117
                    ("title" "Title of the article (BibTeX converts it to lowercase)"))
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
		   (("journal" "Name of the journal (use string, remove braces)") 
                    ("year" "Year of publication")
                    ("volume" "Volume of the journal")
                    ("number" "Number of the journal")
		    ("month" "Month of the publication as a string (remove braces)")
                    ("pages" "Pages in the journal")
                    ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("Book" . (((("author" "Author1 [and Author2 ...] [and others]")
                 ("title" "Title of the book")
                 ("publisher" "Publishing company")
                 ("year" "Year of publication"))
		(("editor" "Editor1 [and Editor2 ...] [and others]")
                 ("volume" "Volume of the book in the series")
                 ("number" "Number of the book in a small series (overwritten by volume)")
                 ("series" "Series in which the book appeared")
                 ("address" "Address of the publisher")
		 ("edition" "Edition of the book as a capitalized English word")
                 ("month" "Month of the publication as a string (remove braces)")
                 ("note" "Remarks to be put at the end of the \\bibitem")))))
137
    ("Booklet" . (((("title" "Title of the booklet (BibTeX converts it to lowercase)"))
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
		   (("author" "Author1 [and Author2 ...] [and others]")
                    ("howpublished" "The way in which the booklet was published")
                    ("address" "Address of the publisher")
                    ("year" "Year of publication")
                    ("month" "Month of the publication as a string (remove braces)")
                    ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("InBook" . (((("author" "Author1 [and Author2 ...] [and others]")
                   ("title" "Title of the book")
                   ("chapter" "Chapter in the book")
                   ("publisher" "Publishing company")
                   ("year" "Year of publication"))
		  (("editor" "Editor1 [and Editor2 ...] [and others]")
                   ("volume" "Volume of the book in the series")
                   ("number" "Number of the book in a small series (overwritten by volume)")
                   ("series" "Series in which the book appeared")
                   ("address" "Address of the publisher")
		   ("edition" "Edition of the book as a capitalized English word")
                   ("month" "Month of the publication as a string (remove braces)")
                   ("pages" "Pages in the book")
                   ("type" "Word to use instead of \"chapter\"")
                   ("note" "Remarks to be put at the end of the \\bibitem")))
		 ((("author" "Author1 [and Author2 ...] [and others]")
                   ("title" "Title of the book")
                   ("chapter" "Chapter in the book"))
		  (("publisher" "Publishing company")
                   ("year" "Year of publication")
                   ("editor" "Editor1 [and Editor2 ...] [and others]")
                   ("volume" "Volume of the book in the series")
                   ("number" "Number of the book in a small series (overwritten by volume)")
		   ("series" "Series in which the book appeared")
                   ("address" "Address of the publisher")
                   ("edition" "Edition of the book as a capitalized English word")
                   ("month" "Month of the publication as a string (remove braces)")
                   ("pages" "Pages in the book")
                   ("type" "Word to use instead of \"chapter\"")
                   ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("InCollection" . (((("author" "Author1 [and Author2 ...] [and others]")
175
                         ("title" "Title of the article in book (BibTeX converts it to lowercase)")
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
			 ("booktitle" "Name of the book")
                         ("publisher" "Publishing company")
                         ("year" "Year of publication"))
			(("editor" "Editor1 [and Editor2 ...] [and others]")
                         ("volume" "Volume of the book in the series")
                         ("number" "Number of the book in a small series (overwritten by volume)")
                         ("series" "Series in which the book appeared")
                         ("chapter" "Chapter in the book")
                         ("type" "Word to use instead of \"chapter\"")
                         ("address" "Address of the publisher")
                         ("edition" "Edition of the book as a capitalized English word")
                         ("month" "Month of the publication as a string (remove braces)")
			 ("pages" "Pages in the book")
                         ("note" "Remarks to be put at the end of the \\bibitem")))
		       ((("author" "Author1 [and Author2 ...] [and others]")
191
                         ("title" "Title of the article in book (BibTeX converts it to lowercase)")
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
                         ("booktitle" "Name of the book"))
			(("publisher" "Publishing company")
                         ("year" "Year of publication")
			 ("editor" "Editor1 [and Editor2 ...] [and others]")
                         ("volume" "Volume of the book in the series")
                         ("number" "Number of the book in a small series (overwritten by volume)")
                         ("series" "Series in which the book appeared")
                         ("chapter" "Chapter in the book")
                         ("type" "Word to use instead of \"chapter\"")
                         ("address" "Address of the publisher")
                         ("edition" "Edition of the book as a capitalized English word")
                         ("month" "Month of the publication as a string (remove braces)")
			 ("pages" "Pages in the book")
                         ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("InProceedings" . (((("author" "Author1 [and Author2 ...] [and others]")
207
                          ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")
208 209 210 211 212 213 214 215 216 217 218 219 220
                          ("booktitle" "Name of the conference proceedings")
                          ("year" "Year of publication"))
			 (("editor" "Editor1 [and Editor2 ...] [and others]")
                          ("volume" "Volume of the conference proceedings in the series")
                          ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
                          ("series" "Series in which the conference proceedings appeared")
			  ("organization" "Sponsoring organization of the conference")
                          ("publisher" "Publishing company, its location")
                          ("address" "Location of the Proceedings")
                          ("month" "Month of the publication as a string (remove braces)")
                          ("pages" "Pages in the conference proceedings")
                          ("note" "Remarks to be put at the end of the \\bibitem")))
			((("author" "Author1 [and Author2 ...] [and others]")
221
                          ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
			  ("booktitle" "Name of the conference proceedings"))
			 (("editor" "Editor1 [and Editor2 ...] [and others]")
                          ("volume" "Volume of the conference proceedings in the series")
                          ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
                          ("series" "Series in which the conference proceedings appeared")
                          ("year" "Year of publication")
			  ("organization" "Sponsoring organization of the conference")
                          ("publisher" "Publishing company, its location")
                          ("address" "Location of the Proceedings")
                          ("month" "Month of the publication as a string (remove braces)")
                          ("pages" "Pages in the conference proceedings")
                          ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("Manual" . (((("title" "Title of the manual"))
		  (("author" "Author1 [and Author2 ...] [and others]")
                   ("organization" "Publishing organization of the manual")
                   ("address" "Address of the organization")
                   ("edition" "Edition of the manual as a capitalized English word")
                   ("year" "Year of publication")
		   ("month" "Month of the publication as a string (remove braces)")
                   ("note" "Remarks to be put at the end of the \\bibitem")))))

    ("MastersThesis" . (((("author" "Author1 [and Author2 ...] [and others]")
244
                          ("title" "Title of the master\'s thesis (BibTeX converts it to lowercase)")
245 246 247 248 249 250 251 252
                          ("school" "School where the master\'s thesis was written")
                          ("year" "Year of publication"))
			 (("address" "Address of the school (if not part of field \"school\") or country")
                          ("type" "Type of the master\'s thesis")
                          ("month" "Month of the publication as a string (remove braces)")
                          ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("Misc" . ((()
		(("author" "Author1 [and Author2 ...] [and others]")
253
                 ("title" "Title of the reference (BibTeX converts it to lowercase)")
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
                 ("howpublished" "The way in which the reference was published")
                 ("year" "Year of publication")
                 ("month" "Month of the publication as a string (remove braces)")
                 ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("PhdThesis" . (((("author" "Author1 [and Author2 ...] [and others]")
                      ("title" "Title of the PhD. thesis")
                      ("school" "School where the PhD. thesis was written")
                      ("year" "Year of publication"))
		     (("address" "Address of the school (if not part of field \"school\") or country")
                      ("type" "Type of the PhD. thesis")
                      ("month" "Month of the publication as a string (remove braces)")
                      ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("Proceedings" . (((("title" "Title of the conference proceedings")
                        ("year" "Year of publication"))
		       (("editor" "Editor1 [and Editor2 ...] [and others]")
                        ("volume" "Volume of the conference proceedings in the series")
                        ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
                        ("series" "Series in which the conference proceedings appeared")
                        ("publisher" "Publishing company, its location")
			("organization" "Sponsoring organization of the conference")
                        ("address" "Location of the Proceedings")
                        ("month" "Month of the publication as a string (remove braces)")
                        ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("TechReport" . (((("author" "Author1 [and Author2 ...] [and others]")
278
                       ("title" "Title of the technical report (BibTeX converts it to lowercase)")
279 280 281 282 283 284 285 286
                       ("institution" "Sponsoring institution of the report")
                       ("year" "Year of publication"))
		      (("type" "Type of the report (if other than \"technical report\")")
                       ("number" "Number of the technical report")
                       ("address" "Address of the institution (if not part of field \"institution\") or country")
                       ("month" "Month of the publication as a string (remove braces)")
                       ("note" "Remarks to be put at the end of the \\bibitem")))))
    ("Unpublished" . (((("author" "Author1 [and Author2 ...] [and others]")
287
                        ("title" "Title of the unpublished reference (BibTeX converts it to lowercase)")
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
                        ("note" "Remarks to be put at the end of the \\bibitem"))
		       (("year" "Year of publication")
                        ("month" "Month of the publication as a string (remove braces)")))))
    )

  "Defines reference types and their associated fields.
List of
(entry-name (required optional) (crossref-required crossref-optional))
triples.
If the third element is nil, the first pair is always to be used.
If not, the second pair is to be used in the case of presence of a
crossref field and the third in the case of absence.
Required , optional, crossref-required and crossref-optional are lists. 
Each element of these lists is a list of strings with two elements
(first element  = name of the field, 
 second element = comment to appear in the echo area).")

(defvar bibtex-predefined-strings
  '(
    ("jan") ("feb") ("mar") ("apr") ("may") ("jun") ("jul") ("aug")
    ("sep") ("oct") ("nov") ("dec")
    ("acmcs") ("acta") ("cacm") ("ibmjrd") ("ibmsj") ("ieeese")
    ("ieeetc") ("ieeetcad") ("ipl") ("jacm") ("jcss") ("scp")
    ("sicomp") ("tcs") ("tocs") ("tods") ("tog") ("toms") ("toois")
    ("toplas")
    )
  "Alist of string definitions.
Should contain the strings defined in the BibTeX style files. Each
element is a list with just one element: the string.")

(defvar bibtex-string-files nil
  "*List of BibTeX files containing string definitions.
Those files must be specified using pathnames relative to the
directories specified in $BIBINPUTS. This variable is only evaluated
when bibtex-mode is entered (i. e. when loading the BibTeX file).")

(defvar bibtex-help-message t
  "*If not nil print help messages in the echo area on entering a new field.")

(defvar bibtex-autokey-names 1
  "*Number of names to use for the automatically generated reference key.
If this is set to anything but a number, all names are used.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-name-change-strings
  '(("\\\\\\\"a" "ae") ("\\\\\\\"o" "oe") ("\\\\\\\"u" "ue")
    ("\\\\\\\"s" "ss")
    ("\\\\\\\"A" "Ae") ("\\\\\\\"O" "Oe") ("\\\\\\\"U" "Ue")
336 337
    ("\\\"a" "ae") ("\\\"o" "oe") ("\\\"u" "ue") ("\\\"s" "ss")
    ("\\\"A" "Ae") ("\\\"O" "Oe") ("\\\"U" "Ue")
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
    ("{" "") ("}" ""))
  "Alist of (old-regexp new-string) pairs.
Any part of name matching a old-regexp is replaced by new-string.
Case of the old-regexp is significant. All regexps are tried in the
order in which they appear in the list, so be sure to avoid recursion here.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-name-length 'infty
  "*Number of characters from name to incorporate into key.
If this is set to anything but a number, all characters are used.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-name-separator ""
  "*String that comes between any two names in the key.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-year-length 2
  "*Number of rightmost digits from the year field yo incorporate into key.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titlewords 5
  "*Number of title words to use for the automatically generated reference key.
If this is set to anything but a number, all title words are used.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-title-terminators
  '("\\." "!"  "\\?" ":" ";" "---")
  "*Regexp list defining the termination of the main part of the title.
Case of the regexps is ignored.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titlewords-stretch 2
  "*Number of words that can additionally be used from the title.
These words are used only, if a sentence from the title can be ended then.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titleword-first-ignore
  '("a" "an" "on" "the" "eine?" "der" "die" "das")
  "*Determines words that may begin a title but are not to be used in the key.
Each item of the list is a regexp. If the first word of the title matchs a
regexp from that list, it is not included in the title, even if it is
capitalized. Regexps in the list must be entered using lowercase letters.")

(defvar bibtex-autokey-titleword-abbrevs nil
  "*Determines exceptions to the usual abbreviation mechanism.
A list of (old-regexp new-string) pairs. 
Use all lowercase letters for old-regexp.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titleword-change-strings
  '(("\\\\\\\"a" "ae") ("\\\\\\\"o" "oe") ("\\\\\\\"u" "ue")
    ("\\\\\\\"s" "ss")
    ("\\\\\\\"A" "Ae") ("\\\\\\\"O" "Oe") ("\\\\\\\"U" "Ue")
391 392
    ("\\\"a" "ae") ("\\\"o" "oe") ("\\\"u" "ue") ("\\\"s" "ss")
    ("\\\"A" "Ae") ("\\\"O" "Oe") ("\\\"U" "Ue")
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
    ("{" "") ("}" ""))
  "Alist of (old-regexp new-string) pairs.
Any part of title word matching a old-regexp is replaced by new-string.
Case of the old-regexp is significant.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titleword-length 5
  "*Number of characters from title words to incorporate into key.
If this is set to anything but a number, all characters are used.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-titleword-separator "_"
  "*String to be put between the title words.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-name-year-separator ""
  "*String to be put between name part and year part of key.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-year-title-separator ":_"
  "*String to be put between name part and year part of key.
See the documentation of function bibtex-generate-autokey for further detail.")

(defvar bibtex-autokey-edit-before-use t
  "*If non-nil, user is allowed to edit the generated key before it is used.")

419 420 421 422
;; bibtex-font-lock-keywords is a user option as well, but since the
;; patterns used to define this variable are defined in a later
;; section of this file, its definition comes later.

423

424
;; Syntax Table, Keybindings and BibTeX Entry List
425 426
(defvar bibtex-mode-syntax-table
  (let ((st (make-syntax-table)))
427 428
    (modify-syntax-entry ?\" "w" st)
    ;; this was formerly "\"". Does this cause any problems? 
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
    (modify-syntax-entry ?$ "$$  " st)
    (modify-syntax-entry ?% "<   " st)
    (modify-syntax-entry ?'  "w   " st)
    (modify-syntax-entry ?@  "w   " st)
    (modify-syntax-entry ?\\ "\\" st)
    (modify-syntax-entry ?\f ">   " st)
    (modify-syntax-entry ?\n ">   " st)
    (modify-syntax-entry ?~ " " st)
    st))

(defvar bibtex-mode-map
  (let ((km (make-sparse-keymap)))
    
    (define-key km "\t" 'bibtex-find-text)
    (define-key km "\n" 'bibtex-next-field)
444 445 446 447
    (define-key km "\M-\t" 'bibtex-complete-string)
    (define-key km "\C-c\"" 'bibtex-remove-double-quotes-or-braces)
    (define-key km "\C-c{" 'bibtex-remove-double-quotes-or-braces)
    (define-key km "\C-c}" 'bibtex-remove-double-quotes-or-braces)
448
    (define-key km "\C-c\C-c" 'bibtex-clean-entry)
449
    (define-key km "\C-c?" 'bibtex-print-help-message)
450 451 452 453
    (define-key km "\C-c\C-p" 'bibtex-pop-previous)
    (define-key km "\C-c\C-n" 'bibtex-pop-next)
    (define-key km "\C-c\C-k" 'bibtex-kill-optional-field)
    (define-key km "\C-c\C-d" 'bibtex-empty-field)
454 455 456
    (define-key km "\C-c$"   'bibtex-ispell-entry)
    (define-key km "\M-\C-a"   'bibtex-beginning-of-entry)
    (define-key km "\M-\C-e"   'bibtex-end-of-entry)
457
    (define-key km "\C-c\C-b"   'bibtex-entry)
458 459 460 461
    (define-key km "\C-c\C-q" 'bibtex-hide-entry-bodies)
    (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry)
    (define-key km "\C-c\C-rw" 'widen)
    (define-key km "\C-c\C-o" 'bibtex-remove-OPT)
462

463
    (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings)
464
    (define-key km "\C-c\C-ei" 'bibtex-InCollection)
465 466 467 468 469 470
    (define-key km "\C-c\C-eI" 'bibtex-InBook)
    (define-key km "\C-c\C-e\C-a" 'bibtex-Article)
    (define-key km "\C-c\C-e\C-b" 'bibtex-InBook)
    (define-key km "\C-c\C-eb" 'bibtex-Book)
    (define-key km "\C-c\C-eB" 'bibtex-Booklet)
    (define-key km "\C-c\C-e\C-c" 'bibtex-InCollection)
471 472 473
    (define-key km "\C-c\C-e\C-m" 'bibtex-Manual)
    (define-key km "\C-c\C-em" 'bibtex-MastersThesis)
    (define-key km "\C-c\C-eM" 'bibtex-Misc)
474
    (define-key km "\C-c\C-e\C-p" 'bibtex-InProceedings)
475
    (define-key km "\C-c\C-ep" 'bibtex-Proceedings)
476 477
    (define-key km "\C-c\C-eP" 'bibtex-PhdThesis)
    (define-key km "\C-c\C-e\M-p" 'bibtex-preamble)
478
    (define-key km "\C-c\C-e\C-s" 'bibtex-string)
479
    (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport)
480 481 482
    (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished)
    km))

483
(define-key bibtex-mode-map [menu-bar bibtex-edit]
484
  (cons "BibTeX-Edit" (make-sparse-keymap "BibTeX-Edit")))
485
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-print-help-message]
486
  '("Help about Current Field" . bibtex-print-help-message))
487
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-complete-string]
488
  '("String Complete" . bibtex-complete-string))
489
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-next-field]
490
  '("Next Field" . bibtex-next-field))
491
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-find-text]
492
  '("End of Field" . bibtex-find-text))
493
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-pop-previous]
494
  '("Snatch from Similar Preceding Field" . bibtex-pop-previous))
495
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-pop-next]
496
  '("Snatch from Similar Following Field" . bibtex-pop-next))
497
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-remove-OPT]
498
  '("Remove OPT" . bibtex-remove-OPT))
499
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-remove-double-quotes-or-braces]
500
  '("Remove Quotes or Braces" . bibtex-remove-double-quotes-or-braces))
501
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-clean-entry]
502
  '("Clean Up Entry" . bibtex-clean-entry))
503
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-sort-entries]
504
  '("Sort Entries" . bibtex-sort-entries))
505 506 507 508 509 510
(define-key bibtex-mode-map
  [menu-bar bibtex-edit bibtex-validate-buffer-from-point]
  '("Validate Entries Starting at Point" .
    (lambda ()
      (interactive)
      (bibtex-validate-buffer t))))
511
(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-validate-buffer]
512
  '("Validate Entries" . bibtex-validate-buffer))
513

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
(define-key bibtex-mode-map [menu-bar entry-types]
  (cons "Entry-Types" (make-sparse-keymap "Entry-Types")))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-preamble]
  '("Preamble" . bibtex-preamble))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-string]
  '("String" . bibtex-string))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Misc]
  '("Miscellaneous" . bibtex-Misc))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Unpublished]
  '("Unpublished" . bibtex-Unpublished))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Manual]
  '("Technical Manual" . bibtex-Manual))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-TechReport]
  '("Technical Report" . bibtex-TechReport))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-MastersThesis]
  '("Master's Thesis" . bibtex-MastersThesis))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-PhdThesis]
  '("PhD. Thesis" . bibtex-PhdThesis))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Booklet]
  '("Booklet (Bound, but no Publisher/Institution)" . bibtex-Booklet))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Book]
  '("Book" . bibtex-Book))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Proceedings]
  '("Conference Proceedings" . bibtex-Proceedings))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-InBook]
  '("Chapter or Pages in a Book" . bibtex-InBook))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-InCollection]
  '("Article in a Collection" . bibtex-InCollection))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-InProceedings]
  '("Article in Conference Proceedings" . bibtex-InProceedings))
(define-key bibtex-mode-map [menu-bar entry-types bibtex-Article]
  '("Article in Journal" . bibtex-Article))
546

547 548 549 550 551 552

;; Bug Reporting

(defconst
  bibtex-maintainer-address "Stefan Schoef <schoef@offis.uni-oldenburg.de>")
;; current maintainer
553

554

555
;; Internal Variables
556

557 558 559
(defvar bibtex-pop-previous-search-point nil)
;; Next point where bibtex-pop-previous starts looking for a similar
;; entry.
560

561 562
(defvar bibtex-pop-next-search-point nil)
;; Next point where bibtex-pop-next starts looking for a similar entry.
Jim Blandy's avatar
Jim Blandy committed
563

564 565 566 567 568
(defvar bibtex-completion-candidates nil)
;; Candidates for bibtex-complete-string. Initialized from
;; bibtex-predefined-strings and bibtex-string-files. This variable is
;; buffer-local.
(make-variable-buffer-local 'bibtex-completion-candidates)
Jim Blandy's avatar
Jim Blandy committed
569

570 571 572 573 574 575 576 577 578 579 580
(defvar bibtex-keys nil)
;; Candidates for TAB completion when entering a reference key using
;; the minibuffer. Initialized in bibtex-mode and updated for each
;; new entry. This variable is buffer-local.
(make-variable-buffer-local 'bibtex-keys)

(defvar bibtex-buffer-last-parsed-for-keys-tick nil)
;; Remembers the value returned by buffer-modified-tick when buffer
;; was parsed for keys the last time.
(make-variable-buffer-local 'bibtex-keys)

581

582
;; Functions to Parse the BibTeX Entries
Jim Blandy's avatar
Jim Blandy committed
583 584

(defun bibtex-cfield (name text)
585
  ;; Create a regexp for a BibTeX field of name NAME and text TEXT.
Jim Blandy's avatar
Jim Blandy committed
586 587 588 589 590
  (concat ",[ \t\n]*\\("
	  name
	  "\\)[ \t\n]*=[ \t\n]*\\("
	  text
	  "\\)"))
591 592 593 594 595 596
(defconst bibtex-name-in-cfield 1)
;; The regexp subexpression number of the name part in bibtex-cfield.

(defconst bibtex-text-in-cfield 2)
;; The regexp subexpression number of the text part in bibtex-cfield.

597
(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*")
598 599
;; Regexp defining the name part of a BibTeX field.

600 601
(defconst bibtex-field-const "[][A-Za-z0-9.:;?!`'()/*@_+=|<>-]+")
;; Format of a bibtex field constant (same as bibtex-reference-key (see below))
Jim Blandy's avatar
Jim Blandy committed
602

603 604 605 606 607 608 609 610 611 612 613 614
(defconst bibtex-field-string-part-not-braced
  "[^{}]")
;; Match field string part without braces

(defconst bibtex-field-string-part-no-inner-braces
  (concat
   "{"
   "\\(" bibtex-field-string-part-not-braced "\\)*"
   "}"))
;; Match field string part with no inner braces

(defconst bibtex-field-string-part-1-inner-brace
Jim Blandy's avatar
Jim Blandy committed
615
  (concat
616
   "{"
617
   "\\("
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
     "\\(" bibtex-field-string-part-not-braced "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-no-inner-braces "\\)"
   "\\)*"
   "}"))
;; Match field string part with at most 1 inner brace

(defconst bibtex-field-string-part-2-inner-braces
  (concat
   "{"
   "\\("
     "\\(" bibtex-field-string-part-not-braced "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-no-inner-braces "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-1-inner-brace "\\)"
   "\\)*"
   "}"))
;; Match field string part with at most 2 inner braces

(defconst bibtex-field-string-part-3-inner-braces
  (concat
   "{"
   "\\("
     "\\(" bibtex-field-string-part-not-braced "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-no-inner-braces "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-1-inner-brace "\\)"
     "\\|"
     "\\(" bibtex-field-string-part-2-inner-braces "\\)"
   "\\)*"
   "}"))
;; Match field string part with at most 3 inner braces

(defconst bibtex-field-string-braced
  bibtex-field-string-part-3-inner-braces)
;; Match braced field string with inner nesting level of braces at most 3

(defconst bibtex-field-string-quoted
  (concat
   "\""
   "\\("
     "\\(" "[^\"\\]" "\\)"      ;; every character except quote or backslash
     "\\|"
663 664 665 666 667
;;     "\\(" "\"[A-Za-z-]" "\\)"  ;; a quote followed by a letter or dash 
;;     "\\|"
;; last two lines commented out until lines like
;;   author = "Stefan Sch"of"
;; are supported by BibTeX
668 669 670 671 672 673 674 675 676 677 678
     "\\(" "\\\\.\\|\n"  "\\)"  ;; a backslash followed by any character
   "\\)*"
   "\""))
;; Match quoted field string

(defconst bibtex-field-string
  (concat
   "\\(" bibtex-field-string-braced "\\)"
   "\\|"
   "\\(" bibtex-field-string-quoted "\\)"))
;; Match a braced or quoted string
Eric S. Raymond's avatar
Eric S. Raymond committed
679

Jim Blandy's avatar
Jim Blandy committed
680
(defconst bibtex-field-string-or-const
681 682
  (concat bibtex-field-const "\\|" bibtex-field-string))
;; Match either bibtex-field-string or bibtex-field-const.
Jim Blandy's avatar
Jim Blandy committed
683 684 685 686

(defconst bibtex-field-text
  (concat
    "\\(" bibtex-field-string-or-const "\\)"
687
    "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*"))
688 689
;; Regexp defining the text part of a BibTeX field: either a string,
;; or an empty string, or a constant followed by one or more # /
690
;; constant pairs.
Jim Blandy's avatar
Jim Blandy committed
691 692

(defconst bibtex-field
693 694 695 696 697
  (bibtex-cfield bibtex-field-name bibtex-field-text))
;; Regexp defining the format of a BibTeX field.

(defconst bibtex-name-in-field bibtex-name-in-cfield)
;; The regexp subexpression number of the name part in BibTeX-field.
Jim Blandy's avatar
Jim Blandy committed
698

699 700
(defconst bibtex-text-in-field bibtex-text-in-cfield)
;; The regexp subexpression number of the text part in BibTeX-field.
Jim Blandy's avatar
Jim Blandy committed
701

702
(defconst bibtex-reference-type "@[A-Za-z]+")
703 704
;; Regexp defining the type part of a BibTeX reference entry.

705 706 707
(defconst bibtex-reference-key "[][A-Za-z0-9.:;?!`'()/*@_+=|<>-]+")
;; Regexp defining the label part of a BibTeX reference entry (same as
;; bibtex-field-const (see above))
708

Jim Blandy's avatar
Jim Blandy committed
709
(defconst bibtex-reference-head
710
  (concat "^[ \t]*\\("
Jim Blandy's avatar
Jim Blandy committed
711
	  bibtex-reference-type
712
	  "\\)[ \t]*[({][ \t]*\\("
713
	  bibtex-reference-key
714 715 716 717
	  "\\)"))
;; Regexp defining format of the header line of a BibTeX reference
;; entry.

718 719 720 721 722
(defconst bibtex-reference-maybe-empty-head
  (concat bibtex-reference-head "?"))
;; Regexp defining format of the header line of a maybe empty
;; BibTeX reference entry (without reference key).

723
(defconst bibtex-type-in-head 1)
724 725 726
;; The regexp subexpression number of the type part in
;; bibtex-reference-head.

727
(defconst bibtex-key-in-head 2)
728 729
;; The regexp subexpression number of the key part in
;; bibtex-reference-head.
Jim Blandy's avatar
Jim Blandy committed
730 731

(defconst bibtex-reference
732 733
  (concat bibtex-reference-head
	  "\\([ \t\n]*" bibtex-field "\\)*"
734
	  "[ \t\n]*,?[ \t\n]*[})]"))
735 736 737 738 739 740 741 742 743 744
;; Regexp defining the format of a BibTeX reference entry.

(defconst bibtex-type-in-reference bibtex-type-in-head)
;; The regexp subexpression number of the type part in
;; bibtex-reference.

(defconst bibtex-key-in-reference bibtex-key-in-head)
;; The regexp subexpression number of the key part in
;; bibtex-reference.

Jim Blandy's avatar
Jim Blandy committed
745 746
(defconst bibtex-string
  (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\("
747
	  bibtex-reference-key
Jim Blandy's avatar
Jim Blandy committed
748 749
	  "\\)[ \t\n]*=[ \t\n]*\\("
	  bibtex-field-text
750 751
	  "\\)[ \t\n]*[})]"))
;; Regexp defining the format of a BibTeX string entry.
Jim Blandy's avatar
Jim Blandy committed
752

753
(defconst bibtex-key-in-string 1)
754
;; The regexp subexpression of the name part in bibtex-string.
Jim Blandy's avatar
Jim Blandy committed
755

756 757
(defconst bibtex-text-in-string 2)
;; The regexp subexpression of the text part in bibtex-string.
Jim Blandy's avatar
Jim Blandy committed
758

759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
(defvar bibtex-font-lock-keywords
  (list
   (list bibtex-reference-maybe-empty-head
         (list bibtex-type-in-head 'font-lock-function-name-face)
         (list bibtex-key-in-head 'font-lock-reference-face nil t))
   ;; reference type and reference label
   (list (concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
         1 'font-lock-comment-face)
   ;; optional field names (treated as comments)
   (list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
         1 'font-lock-variable-name-face)
   ;; field names
   "*Default expressions to highlight in BibTeX mode."))
;; now all needed patterns are defined

774 775 776
(defconst bibtex-name-alignment 2)
;; Alignment for the name part in BibTeX fields. Chosen on aesthetic
;; grounds only.
777

778 779 780
(defconst bibtex-text-alignment (length "  organization = "))
;; Alignment for the text part in BibTeX fields. Equal to the space
;; needed for the longest name part.
Jim Blandy's avatar
Jim Blandy committed
781

782

783
;; Helper Functions
Eric S. Raymond's avatar
Eric S. Raymond committed
784

785
(defun bibtex-member-of-regexp (string list)
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
  ;; Return non-nil if STRING is exactly matched by an element of
  ;; LIST. This function is influenced by the actual value of
  ;; `case-fold-search'. The value is actually the tail of LIST whose
  ;; car matches STRING.
  (while
      (and
       list
       (not
        (string-match
         (concat "^" (car list) "$")
         string)))
    (setq list (cdr list)))
  list)

(defun assoc-of-regexp (string alist)
  ;; Return non-nil if STRING is exactly matched by the car of an
  ;; element of LIST. This function is influenced by the actual value
  ;; of `case-fold-search'. The value is actually the element of LIST
  ;; whose car matches STRING.
  (while
      (and
       alist
       (not
        (string-match
         (concat "^" (car (car alist)) "$")
         string)))
    (setq alist (cdr alist)))
  (car alist))
Eric S. Raymond's avatar
Eric S. Raymond committed
814

815 816 817 818 819 820 821 822 823 824 825 826 827 828
(defun skip-whitespace-and-comments ()
  (let ((md (match-data)))
    (unwind-protect
	(while (cond ((looking-at "\\s>+\\|\\s +")
		      ;; was whitespace
		      ;; NOTE: also checked end-comment.  In latex and
		      ;; lisp modes, newline is an end comment, but it
		      ;; should also be a whitespace char.
		      (goto-char (match-end 0)))
		     ;; If looking at beginning of comment, skip to end.
		     ((looking-at "\\s<")
		      (re-search-forward "\\s>"))))		      
      (store-match-data md))))

829 830 831 832
(defun map-bibtex-entries (fun)
  ;; Call FUN for each BibTeX entry starting with the current. Do this
  ;; to the end of the file. FUN is called with one argument, the key
  ;; of the entry, and with point inside the entry. If
833
  ;; bibtex-sort-ignore-string-entries is non-nil, FUN will not be called
834 835
  ;; for @string entries.
  (bibtex-beginning-of-entry)
836
  (while (re-search-forward bibtex-reference-head nil t)
837
    (if (and bibtex-sort-ignore-string-entries
838
	     (string-equal "@string"
839
                           (downcase (buffer-substring-no-properties
840 841
                                      (match-beginning bibtex-type-in-head)
                                      (match-end bibtex-type-in-head)))))
842
	nil
843
      (funcall fun (buffer-substring-no-properties
844 845
                    (match-beginning bibtex-key-in-head)
                    (match-end bibtex-key-in-head))))))
Eric S. Raymond's avatar
Eric S. Raymond committed
846

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
(defun bibtex-flash-head ()
  ;; Flash at BibTeX reference head before point, if exists.
  (let ((flash))
    (cond ((re-search-backward bibtex-reference-head (point-min) t)
	   (goto-char (match-beginning bibtex-type-in-head))
	   (setq flash (match-end bibtex-key-in-reference)))
	  (t
	   (end-of-line)
	   (skip-chars-backward " \t")
	   (setq flash (point))
	   (beginning-of-line)
	   (skip-chars-forward " \t")))
    (if (pos-visible-in-window-p (point))
	(sit-for 1)
      (message "From: %s"
	       (buffer-substring (point) flash)))))
Eric S. Raymond's avatar
Eric S. Raymond committed
863

864 865 866 867 868 869 870 871 872 873 874 875
(defun bibtex-move-outside-of-entry ()
  ;; Make sure we are outside of a BibTeX entry.
  (cond ((or
	  (= (point) (point-max))
	  (= (point) (point-min))
	  (looking-at "[ \n]*@")
	  )
	 t)
	(t
	 (backward-paragraph)
	 (forward-paragraph)))
  (re-search-forward "[ \t\n]*" (point-max) t))
Eric S. Raymond's avatar
Eric S. Raymond committed
876 877

(defun beginning-of-first-bibtex-entry ()
878
  ;; Go to the beginning of the first BibTeX entry in buffer.
Eric S. Raymond's avatar
Eric S. Raymond committed
879
  (goto-char (point-min))
880 881 882 883 884 885 886
   (cond
    ((re-search-forward "^@" nil 'move)
     (beginning-of-line))
    ((and (bobp) (eobp))
     nil)
    (t
     (message "Warning: No BibTeX entries found!"))))
Eric S. Raymond's avatar
Eric S. Raymond committed
887

888 889 890
(defun bibtex-inside-field ()
  ;; Try to avoid point being at end of a BibTeX field.
  (end-of-line)
891
  (skip-chars-backward " \t")
892
  (cond ((= (preceding-char) ?,)
893 894 895 896 897
	 (forward-char -2)))
  (cond ((or
          (= (preceding-char) ?})
          (= (preceding-char) ?\"))
         (forward-char -1))))
898

899 900 901 902 903 904 905 906 907 908
(defun bibtex-enclosing-field ()
  ;; Search for BibTeX field enclosing point. Point moves to end of
  ;; field; also, use match-beginning and match-end to parse the field.
  ;; sct@dcs.edinburgh.ac.uk
  (let ((old-point (point)))
    (condition-case errname
 	(bibtex-enclosing-regexp bibtex-field)
      (search-failed
       (goto-char old-point)
       (error "Can't find enclosing BibTeX field.")))))
Eric S. Raymond's avatar
Eric S. Raymond committed
909

910
(defun bibtex-enclosing-reference ()
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
  ;; Search for BibTeX reference enclosing point. Point moves to
  ;; beginning of reference. Beginning/end of reference is given by
  ;; (match-beginning/match-end 0).
  (let ((old-point (point)))
    (if (not
         (re-search-backward bibtex-reference-head (point-min) t))
        (progn
          (error "Can't find enclosing BibTeX reference.")
          (goto-char old-point)))
    (goto-char (match-beginning bibtex-type-in-head))
    (let ((pnt (point)))
      (if (not
           (re-search-forward bibtex-reference (point-max) t))
          (progn
            (error "Can't find enclosing BibTeX reference.")
            (goto-char old-point))
        (goto-char pnt)))))

(defun bibtex-enclosing-reference-maybe-empty-head ()
  ;; Search for BibTeX reference enclosing point. Point moves to
  ;; beginning of reference. Beginning/end of reference is given by
  ;; (match-beginning/match-end 0).
933 934 935
  (let ((old-point (point)))
    (if (not
         (re-search-backward
936
          bibtex-reference-maybe-empty-head (point-min) t))
937 938 939
        (progn
          (error "Can't find enclosing BibTeX reference.")
          (goto-char old-point)))
940
    (goto-char (match-beginning bibtex-type-in-head))
941 942
    (let ((pnt (point)))
      (if (not
943 944 945 946 947 948
           (re-search-forward
            (concat
             bibtex-reference-maybe-empty-head
             "\\([ \t\n]*" bibtex-field "\\)*"
             "[ \t\n]*,?[ \t\n]*[})]")
            (point-max) t))
949 950 951 952
          (progn
            (error "Can't find enclosing BibTeX reference.")
            (goto-char old-point))
        (goto-char pnt)))))
953

954 955 956 957 958 959
(defun bibtex-enclosing-regexp (regexp)
  ;; Search for REGEXP enclosing point. Point moves to end of
  ;; REGEXP. See also match-beginning and match-end. If an enclosing
  ;; REGEXP is not found, signals search-failed; point is left in an
  ;; undefined location.
  ;; Doesn't something like this exist already?
960
  ;; compute reasonable limits for the loop
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
  (let* ((initial (point))
	 (right (if (re-search-forward regexp (point-max) t)
		    (match-end 0)
		  (point-max)))
	 (left
	  (progn
	    (goto-char initial)
	    (if (re-search-backward regexp (point-min) t)
		(match-beginning 0)
	      (point-min)))))
    ; within the prescribed limits, loop until a match is found
    (goto-char left)
    (re-search-forward regexp right nil 1)
    (if (> (match-beginning 0) initial)
	(signal 'search-failed (list regexp)))	  
    (while (<= (match-end 0) initial)
      (re-search-forward regexp right nil 1)
      (if (> (match-beginning 0) initial)
	  (signal 'search-failed (list regexp))))
    ))
Eric S. Raymond's avatar
Eric S. Raymond committed
981

982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
(defun bibtex-autokey-change (string change-list)
  ;; Returns a string where some regexps are changed according to
  ;; change-list. Every item of change-list is an (old-regexp
  ;; new-string) pair.
  (let ((return-string string)
        case-fold-search
        (index 0)
        (len (length change-list))
        change-item)
    (while (< index len)
      (setq change-item (elt change-list index))
      (while (string-match (car change-item) return-string)
        (setq
         return-string
         (concat (substring return-string 0 (match-beginning 0))
                 (elt change-item 1)
                 (substring return-string (match-end 0)))))
      (setq index (1+ index)))
    return-string))

(defun bibtex-autokey-abbrev (string len)
  ;; Returns an abbreviation of string with at least len
  ;; characters. String is aborted only after a consonant or at the
  ;; word end. If len is not a number, string is returned unchanged.
  (let* ((string-length (length string))
         (len (if (numberp len)
                  (min len string-length)
                len))
         (return-string (if (numberp len)
                            (substring string 0 len)))
         (index len)
         (vowels '(?a ?e ?i ?o ?u ?A ?E ?I ?O ?U)))
    (if (numberp len)
        (progn
          (while (and
                  (< index string-length) 
                  (member (elt return-string
                               (1- (length return-string)))
                          vowels))
            (setq return-string (concat return-string
                                        (substring
                                         string index (1+ index)))
                  index (1+ index)))
          return-string)
      string)))        

(defun bibtex-generate-autokey ()
  "Generates automatically a key from the author/editor and the title field.
The generation algorithm works as follows:
  1. If there is a non-empty author (preferred) or editor field,
     use it for the name part of the key.
  2. Change any substring found in `bibtex-autokey-name-change-strings' 
     to the corresponding new one (see documentation of this variable
     for further detail).
  3. For every of the first `bibtex-autokey-names' names in the
     \"name\" field, determine the last name.
  4. From every last name, take at least `bibtex-autokey-name-length'
     characters (abort only after a consonant or at a word end).
  5. Build the name part of the key by concatenating all abbreviated last
     names with the string `bibtex-autokey-name-separator' between
     any two.
  6. Build the year part of the key by truncating the contents of the
     \"year\" field to the rightmost `bibtex-autokey-year-length'
     digits (useful values are 2 and 4).
  7. For the title part of the key change the contents of the \"title\"
     field of the reference according to
     `bibtex-autokey-titleword-change-strings' to the corresponding
     new one (see documentation of this variable for further detail).
  8. Abbreviate the result to the string up to (but not including) the
1051
     first occurrence of a regexp matched by the items of
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
     `bibtex-autokey-title-terminators' and delete the first
     word if it appears in `bibtex-autokey-titleword-first-ignore'. 
     Build the title part of the key by using at least the first
     `bibtex-autokey-titlewords' capitalized words from this
     abbreviated title. If the abbreviated title ends after maximal
     `bibtex-autokey-titlewords' + `bibtex-autokey-titlewords-stretch'
     capitalized words, all capitalized words from the abbreviated title
     are used. 
  9. For every used title word that appears in
     `bibtex-autokey-titleword-abbrevs' use the corresponding abbreviation
     (see documentation of this variable for further detail).
 10. From every title word not generated by an abbreviation, take at
     least `bibtex-autokey-titleword-length' characters (abort only after
     a consonant or at a word end).
 11. Build the title part of the key by concatenating all abbreviated
     title words with the string `bibtex-autokey-titleword-separator'
     between any two.
 12. At least, to get the key, concatenate the name part, the year part
     and the title part with `bibtex-autokey-name-year-separator'
     between the name and the year if both are non-empty and
     `bibtex-autokey-year-title-separator' between the year and
     the title if both are non-empty."

  (let* ((pnt (point))
         (min
          (progn
            (bibtex-beginning-of-entry)
            (point)))
         (max
          (progn
            (bibtex-end-of-entry)
            (point)))
         (namefield
          (progn
            (goto-char min)
            (if (or
1088 1089
                 (re-search-forward "^[ \t]*author[ \t]*=" max t)
                 (re-search-forward "^[ \t]*editor[ \t]*=" max t))
1090 1091 1092 1093 1094 1095 1096 1097
                (let* (bibtex-help-message
                       (start (progn
                                (bibtex-find-text t)
                                (point)))
                       (end (progn
                              (bibtex-find-text nil)
                              (point))))
                  (bibtex-autokey-change
1098
                   (buffer-substring-no-properties start end)
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
                   bibtex-autokey-name-change-strings))
              "")))
         (namelist
          (mapcar
           (function
            (lambda (fullname)
              (bibtex-autokey-abbrev
               (if (string-match "," fullname)
                   (substring fullname 0 (match-beginning 0))
                 (progn
                   (if (string-match " [^ ]*$" fullname)
                       (substring
                        fullname (1+ (match-beginning 0)))
                     fullname)))
               bibtex-autokey-name-length)))
           ;; Gather all names into a list
           (let (names
                 (counter 0))
             (while (and
                     (not (equal namefield ""))
                     (or
                      (not (numberp bibtex-autokey-names))
                      (< counter bibtex-autokey-names)))
               (if (string-match " and " namefield)
                   (progn
                     (setq
                      names
                      (append names
                              (list
                               (downcase
                                (substring
                                 namefield 0 (match-beginning 0)))))
                      namefield
                      (substring namefield (match-end 0))))
                 (setq names
                       (append names (list (downcase namefield)))
                       namefield ""))
               (setq counter (1+ counter)))
             names)))
         (namepart (mapconcat (function (lambda (name) name))
                              namelist
                              bibtex-autokey-name-separator))
         (yearfield
          (progn
            (goto-char min)
1144
            (if (re-search-forward
1145
                 "^[ \t]*year[ \t]*=[ \t]*\\([0-9]*\\)" max t)
1146 1147
                (buffer-substring-no-properties
                 (match-beginning 1) (match-end 1))
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
              "")))
         (yearpart
          (if (equal yearfield "")
              ""
            (substring yearfield
                       (- (length yearfield)
                          bibtex-autokey-year-length))))
         (titlestring
          (let ((case-fold-search t)
                (titlefield
                 (progn
                   (goto-char min)
1160
                   (if (re-search-forward
1161 1162 1163 1164 1165 1166 1167 1168 1169
                        "^[ \t]*title[ \t]*=" max t)
                       (let* (bibtex-help-message
                              (start (progn
                                       (bibtex-find-text t)
                                       (point)))
                              (end (progn
                                     (bibtex-find-text nil)
                                     (point))))
                         (bibtex-autokey-change
1170
                          (buffer-substring-no-properties start end)
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
                          bibtex-autokey-titleword-change-strings))
                     "")))
                case-fold-search
                (index 0)
                (numberofitems
                 (length bibtex-autokey-title-terminators)))
            (while (< index numberofitems)
              (if (string-match
                   (elt bibtex-autokey-title-terminators index)
                   titlefield)
                  (setq titlefield
                        (substring titlefield 0 (match-beginning 0))))
              (setq index (1+ index)))
            titlefield))
         (titlelist
          (mapcar
           (function
            (lambda (titleword)
              (let ((abbrev
                     (assoc-of-regexp
                      titleword bibtex-autokey-titleword-abbrevs)))
                (if abbrev
                    (elt abbrev 1)
                  (bibtex-autokey-abbrev
                   titleword
                   bibtex-autokey-titleword-length)))))
           ;; Gather all titlewords into a list
           (let (titlewords
                 titlewords-extra
                 case-fold-search
                 (counter 0)
                 (first t))
             (while (and
                     (not (equal titlestring ""))
                     (or
                      (not (numberp bibtex-autokey-titlewords))
                      (< counter (+
                                  bibtex-autokey-titlewords
                                  bibtex-autokey-titlewords-stretch))))
               (if (string-match "\\b[A-Z][A-Za-z0-9]*" titlestring)
                   (let* ((end-match (match-end 0))
                          (titleword
                           (downcase (substring titlestring
                                                (match-beginning 0)
                                                end-match))))
                     (if (or
                          (not (numberp bibtex-autokey-titlewords))
                          (< counter bibtex-autokey-titlewords))
                         (if (and
                              first
1221
                              (bibtex-member-of-regexp
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
                               titleword
                               bibtex-autokey-titleword-first-ignore))
                             (setq counter -1)