0
+ − 1 ;;; bibtex.el --- BibTeX mode for GNU Emacs
+ − 2
+ − 3 ;; Copyright (C) 1992 Free Software Foundation, Inc.
+ − 4
+ − 5 ;; Author: Bengt Martensson <ubrinf!mond!bengt>
+ − 6 ;; Mark Shapiro <shapiro@corto.inria.fr>
+ − 7 ;; Mike Newton <newton@gumby.cs.caltech.edu>
+ − 8 ;; Aaron Larson <alarson@src.honeywell.com>
+ − 9 ;; Version: 1.3.1
+ − 10 ;; Maintainer:Aaron Larson <alarson@src.honeywell.com>
+ − 11 ;; Adapted-By: ESR
+ − 12 ;; Keywords: tex, bib
+ − 13
+ − 14 ;; This file is part of XEmacs.
+ − 15
+ − 16 ;; XEmacs is free software; you can redistribute it and/or modify it
+ − 17 ;; under the terms of the GNU General Public License as published by
+ − 18 ;; the Free Software Foundation; either version 2, or (at your option)
+ − 19 ;; any later version.
+ − 20
+ − 21 ;; XEmacs is distributed in the hope that it will be useful, but
+ − 22 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ − 24 ;; General Public License for more details.
+ − 25
+ − 26 ;; You should have received a copy of the GNU General Public License
16
+ − 27 ;; along with XEmacs; see the file COPYING. If not, write to the
+ − 28 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 29 ;; Boston, MA 02111-1307, USA.
0
+ − 30
+ − 31 ;;; TODO distribute texinfo file.
+ − 32
+ − 33 ;;; LCD Archive Entry:
+ − 34 ;;; bibtex-mode|Bengt Martensson, Marc Shapiro, Aaron Larson|
+ − 35 ;;; alarson@src.honeywell.com|
+ − 36 ;;; Support for maintaining BibTeX format bibliography databases|
+ − 37 ;;; 93-03-29|version 1.3|~/modes/bibtex-mode.el.Z|
+ − 38
+ − 39 ;;; Commentary:
+ − 40
+ − 41 ;;; BUGS:
+ − 42 ;;; 1. using regular expressions to match the entire bibtex entry dies
+ − 43 ;;; on long bibtex entires (e.g. those containing abstracts) since
+ − 44 ;;; the length of regular expression matches is fairly limited.
+ − 45 ;;; 2. When inserting a string (with \C-C\C-E\s) hitting a TAB results
+ − 46 ;;; in the error message "Can't find enclosing Bibtex field" instead
+ − 47 ;;; of moving to the empty string. [reported by gernot@cs.unsw.oz.au]
+ − 48 ;;; 3. Function string-equalp should be in a library file, not in this
+ − 49 ;;; file.
+ − 50
+ − 51 ;;; (current keeper: alarson@src.honeywell.com
+ − 52 ;;; previous: shapiro@corto.inria.fr)
+ − 53
+ − 54 ;;; Change Log:
+ − 55
+ − 56 ;; Mon Mar 29 14:06:06 1993 Aaron Larson (alarson at gendibal)
+ − 57 ;;
+ − 58 ;; * bibtex.el: V1.3 released Mar 30, 1993
+ − 59 ;; (bibtex-field-name): Fix to match definition if latex manual,
+ − 60 ;; specifically letters, digits, and punctuation other than comma.
+ − 61 ;; Underscore is retained for historical reasons.
+ − 62 ;; (bibtex-make-field): Fix to work around bug in Lucid prin1-to-string
+ − 63 ;; function as reported by Martin Sjolin <marsj@ida.liu.se>.
+ − 64 ;; (bibtex-entry): minor code cleanup.
+ − 65 ;; (bibtex-mode-map): Remove key binding (C-c n) for
+ − 66 ;; narrow-to-bibtex-entry, previous binding violated emacs policy of
+ − 67 ;; reserving C-c followed by a letter for user customization.
+ − 68 ;; revise modification history to better conform to FSF changelog
+ − 69 ;; standards.
+ − 70 ;; (bibtex-refile-entry): Removed. Would need disclaimer papers to
+ − 71 ;; incorporate it into official sources, and unable to contact author.
+ − 72 ;; Fix minor "syntax" errors in documentation strings and such found
+ − 73 ;; by new byte compiler. Funs bibtex-mode, bibtex-remove-double-quotes
+ − 74 ;;
+ − 75 ;;
+ − 76 ;; Fri Jan 15 14:06:06 1993 Aaron Larson (alarson at gendibal)
+ − 77 ;;
+ − 78 ;; * bibtex.el: V1.2 released Feb 15 1993
+ − 79 ;; (find-bibtex-entry-location bibtex-make-field): Fixed placement of
+ − 80 ;; "interactive specification". [Bug report from
+ − 81 ;; mernst@theory.lcs.mit.edu]
+ − 82 ;; Fixed problem where bibtex-entry would fail if user typed entry
+ − 83 ;; name in wrong case.
+ − 84 ;; (bibtex-inside-field) Position the cursor _before_ the last comma
+ − 85 ;; on a line (the comma is not necessarily "inside" the field); this
+ − 86 ;; does not seem to break any existing code. ref sct@dcs.edinburgh.ac.uk
+ − 87 ;; (bibtex-enclosing-field, bibtex-enclosing-reference): leave
+ − 88 ;; point unmoved if no enclosing field/reference is found. As a
+ − 89 ;; result of changes (3) and (4) bibtex-next-field works properly,
+ − 90 ;; even when called from the entry key position.
+ − 91 ;; (bibtex-remove-OPT): realign the '=' after removing the 'opt'.
+ − 92 ;; (bibtex-clean-entry): always remove any trailing comma from the
+ − 93 ;; end of a bibtex entry (these commas get stripped automatically when
+ − 94 ;; optional fields are killed by bibtex-kill-optional-field, but can be
+ − 95 ;; left if optional fields are removed by other means).
+ − 96 ;; (bibtex-x-help) Replace tab with spaces in X menu as noted by
+ − 97 ;; khera@cs.duke.edu
+ − 98 ;; (bibtex-refile-entry): Added (from brannon@jove.cs.caltech.edu)
+ − 99 ;; (bibtex-sort-ignore-string-entries sort-bibtex-entries,
+ − 100 ;; map-bibtex-entries): Added variable as requested by
+ − 101 ;; gernot@cs.unsw.oz.au, required changes to funs.
+ − 102 ;; (bibtex-current-entry-label): Added at request of
+ − 103 ;; yasuro@maekawa.is.uec.ac.jp
+ − 104 ;; (bibtex-DEAthesis:) Deleted along with corresponding entry from
+ − 105 ;; bibtex-x-help per shapiro@corto.inria.fr
+ − 106 ;; Moved narrow-to-bibtex-entry from C-c C-n to C-c n (the previous
+ − 107 ;; binding was in conflict with the binding for bibtex-pop-next.
+ − 108 ;; bug report from [shapiro@corto.inria.fr]
+ − 109 ;;
+ − 110
+ − 111 ;;;
+ − 112 ;;; alarson@src.honeywell.com 92-Feb-13
+ − 113 ;;; 1. Made bibtex-entry user callable, now prompts for entry type (e.g.
+ − 114 ;;; Article), with completion, and bound it to a key. This is now my
+ − 115 ;;; preferred way to add most entries.
+ − 116 ;;; 2. Made fields of a bibtex entry derived from the alist bibtex-entry-
+ − 117 ;;; field-alist.
+ − 118 ;;; 3. Fixed handling of escaped double quotes, e.g. "Schr{\"o}dinger".
+ − 119 ;;; 4. Fixed bug where unhiding bibtex entries moved point.
+ − 120 ;;; 5. Made "field name" specs permit (name . value) for defaulting. E.g.
+ − 121 ;;; (setq bibtex-mode-user-optional-fields '(("library" . "alarson")))
+ − 122 ;;; will generate the field:
+ − 123 ;;; library = "alarson",
+ − 124 ;;; 6. Added binding for narrow-to-bibtex-entry
+ − 125 ;;; 7. Adding a bibtex entry now runs hook: bibtex-add-entry-hook
+ − 126 ;;; 8. Made bibtex-clean-entry fixup text alignment, and eliminated the
+ − 127 ;;; dependency on bibtex-enclosing-reference which has a problem with
+ − 128 ;;; long entries (e.g. those containing abstracts).
+ − 129 ;;;
+ − 130 ;;; alarson@src.honeywell.com 92-Jan-31
+ − 131 ;;; Added support for: ispell, beginning/end of entry movement, a simple
+ − 132 ;;; outline like mode (hide the bodies of bibtex entries), support for
+ − 133 ;;; sorting bibtex entries, and maintaining them in sorted order, and
+ − 134 ;;; simple buffer validation.
+ − 135 ;;; User visible functions added:
+ − 136 ;;; ispell-{abstract,bibtex-entry}, {beginning,end}-of-bibtex-entry
+ − 137 ;;; hide-bibtex-entry-bodies, sort-bibtex-entries, validate-bibtex-
+ − 138 ;;; buffer, find-bibtex-duplicates
+ − 139 ;;; user visible variables added:
+ − 140 ;;; bibtex-maintain-sorted-entries
+ − 141 ;;; new local keybindings:
+ − 142 ;;; " tex-insert-quote
+ − 143 ;;; C-c$ ispell-bibtex-entry
+ − 144 ;;; M-C-a beginning-of-bibtex-entry
+ − 145 ;;; M-C-e end-of-bibtex-entry
+ − 146 ;;; Mike Newton (newton@gumby.cs.caltech.edu) 90.11.17
+ − 147 ;;; * Handle items like
+ − 148 ;;; title = poft # "Fifth Tri-quarterly" # random-conf,
+ − 149 ;;; and title = {This title is inside curlies}
+ − 150 ;;; * added user settable, always present, optional fields
+ − 151 ;;; * fixed 'bibtex-find-it's doc string's location
+ − 152 ;;; * bibtex-field-text made more general (it wouldn't handle the # construct)
+ − 153 ;;; and it now handles a small subset of the {} cases
+ − 154
+ − 155 ;;; Bengt Martensson, March 6
+ − 156 ;;; Adapted to Bibtex 0.99 by updating the optional fields according
+ − 157 ;;; to the document BibTeXing, Oren Patashnik, dated January 31, 1988.
+ − 158 ;;; Updated documentation strings accordingly. Added (provide 'bibtex).
+ − 159 ;;; If bibtex-include-OPT-crossref is non-nil, every entry will have
+ − 160 ;;; an OPTcrossref field, analogously for bibtex-include-OPTkey and
+ − 161 ;;; bibtex-include-OPTannote. Added bibtex-preamble, bound to ^C^EP,
+ − 162 ;;; and also found in X- and sun-menus. Cleaned up the sun-menu
+ − 163 ;;; stuff, and made it more uniform with the X-menu stuff. Marc: I
+ − 164 ;;; strongly suspect that I broke your parsing... (Or, more
+ − 165 ;;; correctly, BibTeX 0.99 broke it.)
+ − 166 ;;; Added bibtex-clean-entry-zap-empty-opts, defvar'd to t. If it
+ − 167 ;;; is nil, bibtex-clean-entry will leave empty optional fields alone.
+ − 168
+ − 169 ;;; Marc Shapiro 1-feb-89: integrated changes by Bengt Martensson 88-05-06:
+ − 170 ;;; Added Sun menu support. Locally bound to right mouse button in
+ − 171 ;;; bibtex-mode. Emacs 18.49 allows local mouse bindings!!
+ − 172 ;;; Commented out DEAthesis.
+ − 173
+ − 174 ;;; Marc Shapiro 6-oct-88
+ − 175 ;;; * skip-whitespace replaced by skip-chars-forward
+ − 176 ;;; * use indent-to-column instead of inserting tabs (changes to
+ − 177 ;;; bibtex-entry, bibtex-make-entry, bibtex-make-OPT-entry, renamed to
+ − 178 ;;; bibtex-make-optional-entry)
+ − 179 ;;; * C-c C-k deletes the current OPT entry entirely
+ − 180 ;;; * C-c C-d replaces text of field with ""
+ − 181 ;;; * renamed bibtex-find-it to bibtex-find-text. With arg, now goes to
+ − 182 ;;; start of text. Fixed bugs in it.
+ − 183
+ − 184 ;;; Marc Shapiro 23-sep-88
+ − 185 ;;; * bibtex-clean-entry moves past end of entry.
+ − 186 ;;; * bibtex-clean-entry signals mandatory fields left empty.
+ − 187
+ − 188 ;;; Marc Shapiro 18-jul-88
+ − 189 ;;; * Fixed bug in bibtex-flash-entry
+ − 190 ;;; * Moved all the entry type keystrokes to "C-c C-e something" (instead of
+ − 191 ;;; "C-c something" previously) to make room for more. C-c C-e is
+ − 192 ;;; supposed to stand for "entry" [idea taken from mail-mode]. Moved
+ − 193 ;;; bibtex-pop-previous to C-c C-p and bibtex-pop-next to C-c C-n.
+ − 194 ;;; * removed binding for "\e[25~"
+ − 195 ;;; * replaced bibtex-clean-optionals by bibtex-clean-entry, bound to
+ − 196 ;;; C-c C-c
+ − 197
+ − 198 ;;; Marc Shapiro 13-jul-88 [based on ideas by Sacha Krakowiak of IMAG]
+ − 199 ;;; * bibtex-pop-previous replaces current field with value of
+ − 200 ;;; similar field in previous entry. May be called n times in a row
+ − 201 ;;; (or with arg n) to pop similar field of n'th previous entry.
+ − 202 ;;; There is also a bibtex-pop-next to get similar field of next
+ − 203 ;;; entry.
+ − 204 ;;; * C-c C-k now kills all empty optional fields of current entry, and
+ − 205 ;;; removes "OPT" for those optional fields which have text.
+ − 206
+ − 207 ;;; Marc Shapiro 14-dec-87
+ − 208 ;;; Cosmetic fixes. Fixed small bug in bibtex-move-outside-of-entry.
+ − 209 ;;; Skip Montanaro <steinmetz!sprite!montanaro> 7-dec-87, Shapiro 10-dec-87
+ − 210 ;;; before inserting an entry, make sure we are outside of a bib entry
+ − 211 ;;; Marc Shapiro 3-nov-87
+ − 212 ;;; addition for France: DEAthesis
+ − 213 ;;; Marc Shapiro 19-oct-1987
+ − 214 ;;; add X window menu option; bug fixes. TAB, LFD, C-c " and C-c C-o now
+ − 215 ;;; behave consistently; deletion never occurs blindly.
+ − 216 ;;; Marc Shapiro <shapiro@inria.inria.fr> 15-oct-1986
+ − 217 ;;; align long lines nicely; C-c C-o checks for the "OPT" string;
+ − 218 ;;; TAB goes to the end of the string; use lower case; use
+ − 219 ;;; run-hooks
+ − 220
+ − 221 ;;; Bengt Martensson <ubrinf!mond!bengt> 87-06-28
+ − 222 ;;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> 87-06-28
+ − 223 ;;; Original version
+ − 224
+ − 225 ;;; Code:
+ − 226
+ − 227 ;;; NOTE by Marc Shapiro, 14-dec-87:
+ − 228 ;;; (bibtex-x-environment) binds an X menu for bibtex mode to x-button-c-right.
+ − 229 ;;; Trouble is, in Emacs 18.44 you can't have a mode-specific mouse binding,
+ − 230 ;;; so it will remain active in all windows. Yuck!
+ − 231
+ − 232 (provide 'bibtex)
+ − 233
+ − 234 ;;; these guys typically don't have autoloads...[alarson:19920131.1548CST]
+ − 235 ;;; Check for fboundp first so that if user autoloads them from non standard
+ − 236 ;;; places, the users bindings will take precedence.
+ − 237 (if (not (fboundp 'tex-insert-quote))
+ − 238 (autoload 'tex-insert-quote "tex-mode"))
+ − 239 (if (not (fboundp 'sort-subr))
+ − 240 (autoload 'sort-subr "sort"))
+ − 241
+ − 242 ;;; These should be in a more generally accessible location.
+ − 243
+ − 244 (defun string-equalp (s1 s2)
+ − 245 "Like string= except differences in case are ignored."
+ − 246 (let ((ss1 (if (symbolp s1) (symbol-name s1) s1))
+ − 247 (ss2 (if (symbolp s2) (symbol-name s2) s2)))
+ − 248 (and (= (length ss1) (length ss2))
+ − 249 (string-equal (upcase ss1) (upcase ss2)))))
+ − 250
+ − 251 ;;; This should be moved into simple.el, and the functions there modified
+ − 252 ;;; to call it rather than doing it themselves.
+ − 253 (defun put-string-on-kill-ring (string)
+ − 254 "Make STRING be the first element of the kill ring."
+ − 255 (setq kill-ring (cons string kill-ring))
+ − 256 (if (> (length kill-ring) kill-ring-max)
+ − 257 (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
+ − 258 (setq kill-ring-yank-pointer kill-ring))
+ − 259
+ − 260
+ − 261
+ − 262
+ − 263 (defvar bibtex-clean-entry-zap-empty-opts t
+ − 264 "*If non-nil, bibtex-clean-entry will delete all empty optional fields.")
+ − 265
+ − 266 (defvar bibtex-include-OPTcrossref t
+ − 267 "*If non-nil, all entries will have an OPTcrossref field.")
+ − 268 (defvar bibtex-include-OPTkey t
+ − 269 "*If non-nil, all entries will have an OPTkey field.")
+ − 270 (defvar bibtex-include-OPTannote t
+ − 271 "*If non-nil, all entries will have an OPTannote field.")
+ − 272
+ − 273 ;; note: the user should be allowed to have their own list of always
+ − 274 ;; available optional fields. exs: "keywords" "categories"
+ − 275
+ − 276 (defvar bibtex-mode-user-optional-fields nil ;no default value
+ − 277 "*List of optional fields that user want to have as always present
+ − 278 when making a bibtex entry. One possibility is for ``keywords''.
+ − 279 Entries can be either strings or conses, in which case the car should be
+ − 280 string and the cdr the value to be inserted.")
+ − 281
+ − 282 (defvar bibtex-mode-syntax-table
+ − 283 (let ((st (make-syntax-table)))
+ − 284 ;; [alarson:19920214.1004CST] make double quote a string quote
+ − 285 (modify-syntax-entry ?\" "\"" st)
+ − 286 (modify-syntax-entry ?$ "$$ " st)
+ − 287 (modify-syntax-entry ?% "< " st)
+ − 288 (modify-syntax-entry ?' "w " st)
+ − 289 (modify-syntax-entry ?@ "w " st)
+ − 290 (modify-syntax-entry ?\\ "\\" st)
+ − 291 (modify-syntax-entry ?\f "> " st)
+ − 292 (modify-syntax-entry ?\n "> " st)
+ − 293 (modify-syntax-entry ?~ " " st)
+ − 294 st))
+ − 295
+ − 296 (defvar bibtex-mode-abbrev-table nil "")
+ − 297 (define-abbrev-table 'bibtex-mode-abbrev-table ())
+ − 298 (defvar bibtex-mode-map
+ − 299 (let ((km (make-sparse-keymap)))
+ − 300
+ − 301 (define-key km "\t" 'bibtex-find-text)
+ − 302 (define-key km "\n" 'bibtex-next-field)
+ − 303 (define-key km "\C-c\"" 'bibtex-remove-double-quotes)
+ − 304 (define-key km "\C-c\C-c" 'bibtex-clean-entry)
+ − 305 (define-key km "\C-c?" 'describe-mode)
+ − 306 (define-key km "\C-c\C-p" 'bibtex-pop-previous)
+ − 307 (define-key km "\C-c\C-n" 'bibtex-pop-next)
+ − 308 (define-key km "\C-c\C-k" 'bibtex-kill-optional-field)
+ − 309 (define-key km "\C-c\C-d" 'bibtex-empty-field)
+ − 310
+ − 311 ;; [alarson:19920131.1543CST]
+ − 312 (define-key km "\"" 'tex-insert-quote)
+ − 313 (define-key km "\C-c$" 'ispell-bibtex-entry)
+ − 314 (define-key km "\M-\C-a" 'beginning-of-bibtex-entry)
+ − 315 (define-key km "\M-\C-e" 'end-of-bibtex-entry)
+ − 316 (define-key km "\C-c\C-b" 'bibtex-entry)
+ − 317 ; (define-key km "\C-cn" 'narrow-to-bibtex-entry)
+ − 318
+ − 319 (define-key km "\C-c\C-e\C-a" 'bibtex-Article)
+ − 320 (define-key km "\C-c\C-e\C-b" 'bibtex-Book)
+ − 321 ; (define-key km "\C-c\C-e\C-d" 'bibtex-DEAthesis)
+ − 322 (define-key km "\C-c\C-e\C-c" 'bibtex-InProceedings)
+ − 323 (define-key km "\C-c\C-e\C-i" 'bibtex-InBook)
+ − 324 (define-key km "\C-c\C-ei" 'bibtex-InCollection)
+ − 325 (define-key km "\C-c\C-eI" 'bibtex-InProceedings)
+ − 326 (define-key km "\C-c\C-e\C-m" 'bibtex-Manual)
+ − 327 (define-key km "\C-c\C-em" 'bibtex-MastersThesis)
+ − 328 (define-key km "\C-c\C-eM" 'bibtex-Misc)
+ − 329 (define-key km "\C-c\C-o" 'bibtex-remove-OPT)
+ − 330 (define-key km "\C-c\C-e\C-p" 'bibtex-PhdThesis)
+ − 331 (define-key km "\C-c\C-ep" 'bibtex-Proceedings)
+ − 332 (define-key km "\C-c\C-eP" 'bibtex-preamble)
+ − 333 (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport)
+ − 334 (define-key km "\C-c\C-e\C-s" 'bibtex-string)
+ − 335 (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished)
+ − 336
+ − 337 (define-key km 'button3 'bibtex-menu)
+ − 338 km))
+ − 339
+ − 340 (defvar bibtex-pop-previous-search-point nil
+ − 341 "Next point where bibtex-pop-previous should start looking for a similar
+ − 342 entry.")
+ − 343
+ − 344 (defvar bibtex-pop-next-search-point nil
+ − 345 "Next point where bibtex-pop-next should start looking for a similar
+ − 346 entry.")
+ − 347
+ − 348 (defvar bibtex-entry-field-alist
+ − 349 '(
+ − 350 ("Article" . ((("author" "title" "journal" "year")
+ − 351 ("volume" "number" "pages" "month" "note"))
+ − 352 (("author" "title")
+ − 353 ("journal" "year" "volume" "number" "pages"
+ − 354 "month" "note"))))
+ − 355 ("Book" . ((("author" "title" "publisher" "year")
+ − 356 ("editor" "volume" "number" "series" "address"
+ − 357 "edition" "month" "note"))))
+ − 358 ("Booklet" . ((("title")
+ − 359 ("author" "howpublished" "address" "month" "year" "note"))))
+ − 360
+ − 361 ;; France: Dipl\^{o}me d'Etudes Approfondies (similar to Master's)
+ − 362 ; ("DEAthesis" . ((("author" "title" "school" "year")
+ − 363 ; ("address" "month" "note"))))
+ − 364
+ − 365 ("InBook" . ((("author" "title" "chapter" "publisher" "year")
+ − 366 ("editor" "pages" "volume" "number" "series" "address"
+ − 367 "edition" "month" "type" "note"))
+ − 368 (("author" "title" "chapter")
+ − 369 ("publisher" "year" "editor" "pages" "volume" "number"
+ − 370 "series" "address" "edition" "month" "type" "note"))))
+ − 371
+ − 372
+ − 373 ("InCollection" . ((("author" "title"
+ − 374 "booktitle" "publisher" "year")
+ − 375 ("editor" "volume" "number" "series" "type" "chapter"
+ − 376 "pages" "address" "edition" "month" "note"))
+ − 377 (("author" "title")
+ − 378 ("booktitle" "publisher" "year"
+ − 379 "editor" "volume" "number" "series" "type" "chapter"
+ − 380 "pages" "address" "edition" "month" "note"))))
+ − 381
+ − 382
+ − 383 ("InProceedings" . ((("author" "title" "booktitle" "year")
+ − 384 ("editor" "volume" "number" "series" "pages"
+ − 385 "organization" "publisher" "address" "month" "note"))
+ − 386 (("author" "title")
+ − 387 ("editor" "volume" "number" "series" "pages"
+ − 388 "booktitle" "year"
+ − 389 "organization" "publisher" "address" "month" "note"))))
+ − 390
+ − 391
+ − 392 ("Manual" . ((("title")
+ − 393 ("author" "organization" "address" "edition" "year"
+ − 394 "month" "note"))))
+ − 395
+ − 396 ("MastersThesis" . ((("author" "title" "school" "year")
+ − 397 ("address" "month" "note" "type"))))
+ − 398
+ − 399 ("Misc" . ((()
+ − 400 ("author" "title" "howpublished" "year" "month" "note"))))
+ − 401
+ − 402 ("PhdThesis" . ((("author" "title" "school" "year")
+ − 403 ("address" "month" "type" "note"))))
+ − 404
+ − 405 ("Proceedings" . ((("title" "year")
+ − 406 ("editor" "volume" "number" "series" "publisher"
+ − 407 "organization" "address" "month" "note"))))
+ − 408
+ − 409 ("TechReport" . ((("author" "title" "institution" "year")
+ − 410 ("type" "number" "address" "month" "note"))))
+ − 411
+ − 412 ("Unpublished" . ((("author" "title" "note")
+ − 413 ("year" "month"))))
+ − 414 )
+ − 415
+ − 416 "List of (entry-name (required optional) (crossref-required crossref-optional))
+ − 417 tripples. If the third element is nil, then the first pair can be used. Required
+ − 418 and optional are lists of strings. All entry creation functions use this variable
+ − 419 to generate entries, and bibtex-entry ensures the entry type is valid. This
+ − 420 variable can be used for example to make bibtex manipulate a different set of entry
+ − 421 types, e.g. a crossreference document of organization types.")
+ − 422
+ − 423
+ − 424 ;;; A bibtex file is a sequence of entries, either string definitions
+ − 425 ;;; or reference entries. A reference entry has a type part, a
+ − 426 ;;; key part, and a comma-separated sequence of fields. A string
+ − 427 ;;; entry has a single field. A field has a left and right part,
+ − 428 ;;; separated by a '='. The left part is the name, the right part is
+ − 429 ;;; the text. Here come the definitions allowing to create and/or parse
+ − 430 ;;; entries and fields:
+ − 431
+ − 432 ;;; fields
+ − 433 (defun bibtex-cfield (name text)
+ − 434 "Create a regexp for a bibtex field of name NAME and text TEXT"
+ − 435 (concat ",[ \t\n]*\\("
+ − 436 name
+ − 437 "\\)[ \t\n]*=[ \t\n]*\\("
+ − 438 text
+ − 439 "\\)"))
+ − 440 (defconst bibtex-name-in-cfield 1
+ − 441 "The regexp subexpression number of the name part in bibtex-cfield.")
+ − 442 (defconst bibtex-text-in-cfield 2
+ − 443 "The regexp subexpression number of the text part in bibtex-cfield.")
+ − 444
+ − 445 ;;; KAWATA Yasuro <yasuro@qqqq.maekawa.is.uec.ac.jp> reported bug that "/"
+ − 446 ;;; was not premitted in field names. The old value of this var was:
+ − 447 ;;; "[A-Za-z][---A-Za-z0-9:_+]*"
+ − 448 ;;; According to the LaTeX manual, page 71, the legal values are letters,
+ − 449 ;;; digits, and punctuation other than comma. Section 2.1 defines
+ − 450 ;;; punctuation as:
+ − 451 ;;; .:;,?!`'()[]-/*@
+ − 452 ;;; and says that += can be used in normal text. Specifically #$%&~_^\{}
+ − 453 ;;; are called out as special chars. Some experimentation with LaTeX
+ − 454 ;;; indicates that # and ~ definitely don't work, but that the following
+ − 455 ;;; citation does! \cite{a0.:;?!`'()[]-/*@_&$^+=|<>}. I chose here to
+ − 456 ;;; permit _ since it was previously allowed, but otherwise to only handle
+ − 457 ;;; punc and +=
+ − 458 ;;; Amendment: I couldn't get a regexp with both "[]"'s and hyphen to
+ − 459 ;;; work. It looks like you need them both to be the first entries in a
+ − 460 ;;; regexp pattern. [alarson:19930315.0900CST]
+ − 461
+ − 462 (defconst bibtex-field-name "[A-Za-z][---A-Za-z0-9.:;?!`'()/*@_+=]*"
+ − 463 "Regexp defining the name part of a bibtex field.")
+ − 464
+ − 465 ;; bibtex-field-text must be able to handle
+ − 466 ;; title = "Proc. Fifteenth Annual" # STOC,
+ − 467 ;; month = "10~" # jan,
+ − 468 ;; year = "{\noopsort{1973c}}1981",
+ − 469 ;; month = apr # "-" # may,
+ − 470 ;; key = {Volume-2},
+ − 471 ;; note = "Volume~2 is listed under Knuth \cite{book-full}"
+ − 472 ;; i have added a few of these, but not all! -- MON
+ − 473
+ − 474 (defconst bibtex-field-const
+ − 475 "[0-9A-Za-z][---A-Za-z0-9:_+]*"
+ − 476 "Format of a bibtex field constant.")
+ − 477
+ − 478 (defconst bibtex-field-string
+ − 479 (concat
+ − 480 "\"[^\"]*[^\\\\]\"\\|\"\"")
+ − 481 "Match either a string or an empty string.")
+ − 482
+ − 483 (defconst bibtex-field-string-or-const
+ − 484 (concat bibtex-field-const "\\|" bibtex-field-string)
+ − 485 "Match either bibtex-field-string or bibtex-field-const.")
+ − 486
+ − 487 (defconst bibtex-field-text
+ − 488 (concat
+ − 489 "\\(" bibtex-field-string-or-const "\\)"
+ − 490 "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*\\|"
+ − 491 "{[^{}]*[^\\\\]}")
+ − 492 "Regexp defining the text part of a bibtex field: either a string, or
+ − 493 an empty string, or a constant followed by one or more # / constant pairs.
+ − 494 Also matches simple {...} patterns.")
+ − 495
+ − 496 ;(defconst bibtex-field-text
+ − 497 ; "\"[^\"]*[^\\\\]\"\\|\"\"\\|[0-9A-Za-z][---A-Za-z0-9:_+]*"
+ − 498 ; "Regexp defining the text part of a bibtex field: either a string, or an empty string, or a constant.")
+ − 499
+ − 500 (defconst bibtex-field
+ − 501 (bibtex-cfield bibtex-field-name bibtex-field-text)
+ − 502 "Regexp defining the format of a bibtex field")
+ − 503
+ − 504 (defconst bibtex-name-in-field bibtex-name-in-cfield
+ − 505 "The regexp subexpression number of the name part in bibtex-field")
+ − 506 (defconst bibtex-text-in-field bibtex-text-in-cfield
+ − 507 "The regexp subexpression number of the text part in bibtex-field")
+ − 508
+ − 509 ;;; references
+ − 510 (defconst bibtex-reference-type
+ − 511 "@[A-Za-z]+"
+ − 512 "Regexp defining the type part of a bibtex reference entry")
+ − 513 (defconst bibtex-reference-head
+ − 514 (concat "^[ \t]*\\("
+ − 515 bibtex-reference-type
+ − 516 "\\)[ \t]*[({]\\("
+ − 517 bibtex-field-name
+ − 518 "\\)")
+ − 519 "Regexp defining format of the header line of a bibtex reference entry")
+ − 520 (defconst bibtex-type-in-head 1
+ − 521 "The regexp subexpression number of the type part in bibtex-reference-head")
+ − 522 (defconst bibtex-key-in-head 2
+ − 523 "The regexp subexpression number of the key part in
+ − 524 bibtex-reference-head")
+ − 525
+ − 526 (defconst bibtex-reference
+ − 527 (concat bibtex-reference-head
+ − 528 "\\([ \t\n]*" bibtex-field "\\)*"
+ − 529 "[ \t\n]*[})]")
+ − 530 "Regexp defining the format of a bibtex reference entry")
+ − 531 (defconst bibtex-type-in-reference bibtex-type-in-head
+ − 532 "The regexp subexpression number of the type part in bibtex-reference")
+ − 533 (defconst bibtex-key-in-reference bibtex-key-in-head
+ − 534 "The regexp subexpression number of the key part in
+ − 535 bibtex-reference")
+ − 536
+ − 537 ;;; strings
+ − 538 (defconst bibtex-string
+ − 539 (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\("
+ − 540 bibtex-field-name
+ − 541 "\\)[ \t\n]*=[ \t\n]*\\("
+ − 542 bibtex-field-text
+ − 543 "\\)[ \t\n]*[})]")
+ − 544 "Regexp defining the format of a bibtex string entry")
+ − 545 (defconst bibtex-name-in-string 1
+ − 546 "The regexp subexpression of the name part in bibtex-string")
+ − 547 (defconst bibtex-text-in-string 2
+ − 548 "The regexp subexpression of the text part in bibtex-string")
+ − 549
+ − 550 (defconst bibtex-name-alignment 2
+ − 551 "Alignment for the name part in BibTeX fields.
+ − 552 Chosen on aesthetic grounds only.")
+ − 553
+ − 554 (defconst bibtex-text-alignment (length " organization = ")
+ − 555 "Alignment for the text part in BibTeX fields.
+ − 556 Equal to the space needed for the longest name part.")
+ − 557
+ − 558 (defun bibtex-current-entry-label (&optional include-cite kill)
+ − 559 "Return the label of the bibtex entry containing, or preceding point.
+ − 560 Optional argument INCLUDE-CITE, if true means put a '\\cite{}' around the
+ − 561 returned value. Second optional argument KILL, if true, means place the
+ − 562 returned value in the kill buffer. Interactively; providing prefix
+ − 563 argument makes INCLUDE-CITE true, and kill is true by default.
+ − 564
+ − 565 Rationale:
+ − 566 The intention is that someone will write a function that can be bound to
+ − 567 a mouse key so that people entering TeX can just mouse on the bibtex entry
+ − 568 and have the citation key inserted at the current point (which will almost
+ − 569 certainly be in some other buffer). In the interim this function is
+ − 570 marginally useful for keyboard binding and is not bound by default.
+ − 571 Suggested binding is ^C-k."
+ − 572 (interactive (list current-prefix-arg t))
+ − 573 (save-excursion
+ − 574 (beginning-of-bibtex-entry)
+ − 575 (re-search-forward bibtex-reference-head (save-excursion (end-of-bibtex-entry) (point)))
+ − 576 (let* ((key (buffer-substring (match-beginning bibtex-key-in-head)
+ − 577 (match-end bibtex-key-in-head)))
+ − 578 (val (if include-cite
+ − 579 (format "\\cite{%s}" key)
+ − 580 key)))
+ − 581 (if kill
+ − 582 (put-string-on-kill-ring val))
+ − 583 val)))
+ − 584
+ − 585 ;;; bibtex mode:
+ − 586
+ − 587 ;;;###autoload
+ − 588 (defun bibtex-mode ()
+ − 589 "Major mode for editing bibtex files.
+ − 590
+ − 591 \\{bibtex-mode-map}
+ − 592
+ − 593 A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry.
+ − 594
+ − 595 The optional fields start with the string OPT, and thus ignored by BibTeX.
+ − 596 The OPT string may be removed from a field with \\[bibtex-remove-OPT].
+ − 597 \\[bibtex-kill-optional-field] kills the current optional field entirely.
+ − 598 \\[bibtex-remove-double-quotes] removes the double-quotes around the text of
+ − 599 the current field. \\[bibtex-empty-field] replaces the text of the current
+ − 600 field with the default \"\".
+ − 601
+ − 602 The command \\[bibtex-clean-entry] cleans the current entry, i.e. (i) removes
+ − 603 double-quotes from entirely numerical fields, (ii) removes OPT from all
+ − 604 non-empty optional fields, (iii) removes all empty optional fields, and (iv)
+ − 605 checks that no non-optional fields are empty.
+ − 606
+ − 607 Use \\[bibtex-find-text] to position the dot at the end of the current field.
+ − 608 Use \\[bibtex-next-field] to move to end of the next field.
+ − 609
+ − 610 The following may be of interest as well:
+ − 611
+ − 612 Functions:
+ − 613 find-bibtex-duplicates
+ − 614 find-bibtex-entry-location
+ − 615 hide-bibtex-entry-bodies
+ − 616 sort-bibtex-entries
+ − 617 validate-bibtex-buffer
+ − 618
+ − 619 Variables:
+ − 620 bibtex-clean-entry-zap-empty-opts
+ − 621 bibtex-entry-field-alist
+ − 622 bibtex-include-OPTannote
+ − 623 bibtex-include-OPTcrossref
+ − 624 bibtex-include-OPTkey
+ − 625 bibtex-maintain-sorted-entries
+ − 626 bibtex-mode-user-optional-fields
+ − 627
+ − 628 Fields:
+ − 629 address
+ − 630 Publisher's address
+ − 631 annote
+ − 632 Long annotation used for annotated bibliographies (begins sentence)
+ − 633 author
+ − 634 Name(s) of author(s), in BibTeX name format
+ − 635 booktitle
+ − 636 Book title when the thing being referenced isn't the whole book.
+ − 637 For book entries, the title field should be used instead.
+ − 638 chapter
+ − 639 Chapter number
+ − 640 crossref
+ − 641 The database key of the entry being cross referenced.
+ − 642 edition
+ − 643 Edition of a book (e.g., \"second\")
+ − 644 editor
+ − 645 Name(s) of editor(s), in BibTeX name format.
+ − 646 If there is also an author field, then the editor field should be
+ − 647 for the book or collection that the work appears in
+ − 648 howpublished
+ − 649 How something strange has been published (begins sentence)
+ − 650 institution
+ − 651 Sponsoring institution
+ − 652 journal
+ − 653 Journal name (macros are provided for many)
+ − 654 key
+ − 655 Alphabetizing and labeling key (needed when no author or editor)
+ − 656 month
+ − 657 Month (macros are provided)
+ − 658 note
+ − 659 To help the reader find a reference (begins sentence)
+ − 660 number
+ − 661 Number of a journal or technical report
+ − 662 organization
+ − 663 Organization (sponsoring a conference)
+ − 664 pages
+ − 665 Page number or numbers (use `--' to separate a range)
+ − 666 publisher
+ − 667 Publisher name
+ − 668 school
+ − 669 School name (for theses)
+ − 670 series
+ − 671 The name of a series or set of books.
2
+ − 672 An individual book will also have its own title
0
+ − 673 title
+ − 674 The title of the thing being referenced
+ − 675 type
+ − 676 Type of a technical report (e.g., \"Research Note\") to be used
+ − 677 instead of the default \"Technical Report\"
+ − 678 volume
+ − 679 Volume of a journal or multivolume work
+ − 680 year
+ − 681 Year---should contain only numerals
+ − 682 ---------------------------------------------------------
+ − 683 Entry to this mode calls the value of bibtex-mode-hook if that value is
+ − 684 non-nil."
+ − 685 (interactive)
+ − 686 (kill-all-local-variables)
+ − 687 (set-syntax-table bibtex-mode-syntax-table)
+ − 688 (use-local-map bibtex-mode-map)
+ − 689 (setq major-mode 'bibtex-mode)
+ − 690 (setq mode-name "BibTeX")
+ − 691 (set-syntax-table bibtex-mode-syntax-table)
+ − 692 (setq local-abbrev-table bibtex-mode-abbrev-table)
+ − 693 (make-local-variable 'paragraph-start)
+ − 694 (setq paragraph-start "^[ \f\n\t]*$")
+ − 695 (auto-fill-mode 1) ; nice alignments
+ − 696 (setq left-margin (+ bibtex-text-alignment 1))
+ − 697
+ − 698 (run-hooks 'bibtex-mode-hook))
+ − 699
+ − 700 (defun bibtex-move-outside-of-entry ()
+ − 701 "Make sure we are outside of a bib entry"
+ − 702 (cond ((or
+ − 703 (= (point) (point-max))
+ − 704 (= (point) (point-min))
+ − 705 (looking-at "[ \n]*@")
+ − 706 )
+ − 707 t)
+ − 708 (t
+ − 709 (backward-paragraph)
+ − 710 (forward-paragraph)))
+ − 711 (re-search-forward "[ \t\n]*" (point-max) t))
+ − 712
+ − 713 (defun ispell-abstract ()
+ − 714 (interactive)
+ − 715 (beginning-of-bibtex-entry)
+ − 716 (re-search-forward "^[ \t]*[OPT]*abstract[ \t]*=")
+ − 717 (ispell-region (point)
+ − 718 (save-excursion (forward-sexp) (point))))
+ − 719
+ − 720 (defun beginning-of-bibtex-entry ()
+ − 721 (interactive)
+ − 722 (re-search-backward "^@" nil 'move))
+ − 723
+ − 724 (defun skip-whitespace-and-comments ()
+ − 725 ;; It might be a good idea to have forward-sexp with argument 0 do what
+ − 726 ;; this function tries to do, namely skip whitespace and comments.
+ − 727 ;; Maybe a better name for this would be skip-to-next-sexp.
+ − 728 ;; alternative implementation:
+ − 729 ;; (let ((parse-sexp-ignore-comments t))
+ − 730 ;; (forward-sexp 1)
+ − 731 ;; (forward-sexp -1))
+ − 732 ;; but I've had problems with this not getting the parse of comments
+ − 733 ;; right going backward if they contain unbalanced expressions or string
+ − 734 ;; quotes. [alarson:19920217.1021CST]
+ − 735 (let ((md (match-data)))
+ − 736 (unwind-protect
+ − 737 (while (cond ((looking-at "\\s>+\\|\\s +")
+ − 738 ;; was whitespace
+ − 739 ;; NOTE: also checked end-comment. In latex and
+ − 740 ;; lisp modes, newline is an end comment, but it
+ − 741 ;; should also be a whitespace char.
+ − 742 (goto-char (match-end 0)))
+ − 743 ;; If looking at beginning of comment, skip to end.
+ − 744 ((looking-at "\\s<")
+ − 745 (re-search-forward "\\s>"))))
+ − 746 (store-match-data md))))
+ − 747
+ − 748 ;;; [alarson:19920214.1007CST]
+ − 749 (defun end-of-bibtex-entry ()
+ − 750 "If inside an entry, move to the end of it, otherwise move to the end
+ − 751 of the next entry."
+ − 752 (interactive)
+ − 753 ;; if point was previously at the end of an entry, this puts us
+ − 754 ;; inside the next entry, otherwise we remain in the current one.
+ − 755 (progn
+ − 756 (skip-whitespace-and-comments)
+ − 757 ;;; (skip-chars-forward " \t\n")
+ − 758 (end-of-line))
+ − 759 (beginning-of-bibtex-entry)
+ − 760 (let ((parse-sexp-ignore-comments t))
+ − 761 (forward-sexp) ; skip entry type
+ − 762 (forward-sexp) ; skip entry body
+ − 763 ))
+ − 764 ;(defun end-of-bibtex-entry ()
+ − 765 ; (interactive)
+ − 766 ; (re-search-forward "}$" nil 'move))
+ − 767
+ − 768 (defun ispell-bibtex-entry ()
+ − 769 (interactive)
+ − 770 (ispell-region (progn (beginning-of-bibtex-entry) (point))
+ − 771 (progn (end-of-bibtex-entry) (point))))
+ − 772
+ − 773 (defun narrow-to-bibtex-entry ()
+ − 774 (interactive)
+ − 775 (save-excursion
+ − 776 (narrow-to-region (progn (beginning-of-bibtex-entry) (point))
+ − 777 (progn (end-of-bibtex-entry) (point)))))
+ − 778
+ − 779
+ − 780 (defun beginning-of-first-bibtex-entry ()
+ − 781 (goto-char (point-min))
+ − 782 (cond
+ − 783 ((re-search-forward "^@" nil 'move)
+ − 784 (beginning-of-line))
+ − 785 ((and (bobp) (eobp))
+ − 786 nil)
+ − 787 (t
+ − 788 (message "Warning: No bibtex entries found!"))))
+ − 789
+ − 790 (defun hide-bibtex-entry-bodies (&optional arg)
+ − 791 "Hide all lines between first and last bibtex entries not beginning with @.
+ − 792 With argument, show all text."
+ − 793 (interactive "P")
+ − 794 (save-excursion
+ − 795 (beginning-of-first-bibtex-entry)
+ − 796 ;; subst-char-in-region modifies the buffer, despite what the
+ − 797 ;; documentation says...
+ − 798 (let ((modifiedp (buffer-modified-p))
+ − 799 (buffer-read-only nil))
+ − 800 (if arg
+ − 801 (subst-char-in-region (point) (point-max) ?\r ?\n t)
+ − 802 (while (save-excursion (re-search-forward "\n[^@]" (point-max) t))
+ − 803 (save-excursion (replace-regexp "\n\\([^@]\\)" "\r\\1"))))
+ − 804 (setq selective-display (not arg))
+ − 805 (set-buffer-modified-p modifiedp))))
+ − 806
+ − 807 (defvar bibtex-sort-ignore-string-entries nil
+ − 808 "*If true, bibtex @STRING entries are ignored when determining ordering
+ − 809 of the buffer (e.g. sorting, locating alphabetical position for new entries,
+ − 810 etc.)")
+ − 811
+ − 812 (defun sort-bibtex-entries ()
+ − 813 "Sort bibtex entries alphabetically by key.
+ − 814 Text before the first bibtex entry, and following the last is not affected.
+ − 815 If bibtex-sort-ignore-string-entries is true, @string entries will be ignored.
+ − 816
+ − 817 Bugs:
+ − 818 1. Text between the closing brace ending one bibtex entry, and the @ starting
+ − 819 the next, is considered part of the PRECEDING entry. Perhaps it should be
+ − 820 part of the following entry."
+ − 821 (interactive)
+ − 822 (save-restriction
+ − 823 (beginning-of-first-bibtex-entry)
+ − 824 (narrow-to-region (point)
+ − 825 (save-excursion
+ − 826 (goto-char (point-max))
+ − 827 (beginning-of-bibtex-entry)
+ − 828 (end-of-bibtex-entry)
+ − 829 (point)))
+ − 830 (sort-subr nil ; reversep
+ − 831 ;; beginning of record function
+ − 832 'forward-line
+ − 833 ;; end of record function
+ − 834 (function (lambda () (and (re-search-forward "}\\s-*\n[\n \t]*@" nil 'move)
+ − 835 (forward-char -2))))
+ − 836 ;; start of key function
+ − 837 (if bibtex-sort-ignore-string-entries
+ − 838 (function (lambda ()
+ − 839 (while (and (re-search-forward "^\\s-*\\([@a-zA-Z]*\\)\\s-*{\\s-*")
+ − 840 (string-equalp "@string"
+ − 841 (buffer-substring (match-beginning 1)
+ − 842 (match-end 1)))))
+ − 843 nil))
+ − 844 (function (lambda () (re-search-forward "{\\s-*") nil)))
+ − 845 ;; end of key function
+ − 846 (function (lambda () (search-forward ",")))
+ − 847 )))
+ − 848
+ − 849 (defun map-bibtex-entries (fun)
+ − 850 "Call FUN for each bibtex entry starting with the current, to the end of the file.
+ − 851 FUN is called with one argument, the key of the entry, and with point inside the entry.
+ − 852 If bibtex-sort-ignore-string-entries is true, FUN will not be called for @string entries."
+ − 853 (beginning-of-bibtex-entry)
+ − 854 (while (re-search-forward "^@[^{]*{[ \t]*\\([^, ]*\\)" nil t)
+ − 855 (if (and bibtex-sort-ignore-string-entries
+ − 856 (string-equalp "@string{"
+ − 857 (buffer-substring (match-beginning 0)
+ − 858 (match-beginning 1))))
+ − 859 nil ; ignore the @string entry.
+ − 860 (funcall fun (buffer-substring (match-beginning 1) (match-end 1))))))
+ − 861
+ − 862 (defun find-bibtex-entry-location (entry-name)
+ − 863 "Searches from beginning of current buffer looking for place to put the
+ − 864 bibtex entry named ENTRY-NAME. Buffer is assumed to be in sorted order,
+ − 865 without duplicates (see \\[sort-bibtex-entries]), if it is not, an error will
+ − 866 be signalled."
+ − 867 (interactive "sBibtex entry key: ")
+ − 868 (let ((previous nil)
+ − 869 point)
+ − 870 (beginning-of-first-bibtex-entry)
+ − 871 (or (catch 'done
+ − 872 (map-bibtex-entries (function (lambda (current)
+ − 873 (cond
+ − 874 ((string-equal entry-name current)
+ − 875 (error "Entry duplicates existing!"))
+ − 876 ((or (null previous)
+ − 877 (string< previous current))
+ − 878 (setq previous current
+ − 879 point (point))
+ − 880 (if (string< entry-name current)
+ − 881 (progn
+ − 882 (beginning-of-bibtex-entry)
+ − 883 ;; Many schemes append strings to
+ − 884 ;; existing entries to resolve them,
+ − 885 ;; so initial substring matches may
+ − 886 ;; indicate a duplicate entry.
+ − 887 (let ((idx (string-match (regexp-quote entry-name) current)))
+ − 888 (if (and (integerp idx)
+ − 889 (zerop idx))
+ − 890 (progn
+ − 891 (message "Warning: Entry %s may be a duplicate of %s!"
+ − 892 entry-name current)
+ − 893 (ding t))))
+ − 894 (throw 'done t))))
+ − 895 ((string-equal previous current)
+ − 896 (error "Duplicate here with previous!"))
+ − 897 (t (error "Entries out of order here!")))))))
+ − 898 (end-of-bibtex-entry))))
+ − 899
+ − 900 (defun validate-bibtex-buffer ()
+ − 901 "Find some typical errors in bibtex files.
+ − 902 1. At signs (@) not as first char of a line.
+ − 903 2. Double quotes (\") inside strings.
+ − 904 3. Closing braces (}) not the last character of a line."
+ − 905 (interactive)
+ − 906 (let ((point (point)))
+ − 907 (while (re-search-forward ".@" nil t)
+ − 908 (let* ((foo (parse-partial-sexp (save-excursion (beginning-of-bibtex-entry)
+ − 909 (point))
+ − 910 (point)))
+ − 911 (in-a-string (nth 3 foo)))
+ − 912 (if (not in-a-string)
+ − 913 (error "At sign (@) out of place!"))))
+ − 914 (goto-char point)
+ − 915 (while (search-forward "\"" nil t)
+ − 916 (or (looking-at "[,}][ \t]*$")
+ − 917 (char-equal (preceding-char) ?\")
+ − 918 ;; some versions put closing brace on separate line.
+ − 919 (looking-at "[ \t]*\n}")
+ − 920 (save-excursion
+ − 921 (save-restriction
+ − 922 (narrow-to-region (point)
+ − 923 (progn (beginning-of-line) (point)))
+ − 924 (looking-at "^[ \t]*[a-zA-Z]+[ \t]*=[ \t]*\"$")))
+ − 925 (error "Quote out of place, or missing \",\" or \"}\"!")))
+ − 926 (goto-char point)
+ − 927 ;; This is only approximate, should actually search for close braces,
+ − 928 ;; then see if they are inside a string, or at the end of a line.
+ − 929 ;; This just gets the typical case of whitespace after a closing brace.
+ − 930 (while (search-forward "}[ \t]+$" nil t)
+ − 931 (error "Brace not last char of line!"))
+ − 932 (goto-char point)
+ − 933 (message "Bibtex buffer appears o.k.")))
+ − 934
+ − 935 (defun find-bibtex-duplicates ()
+ − 936 "Searches forward in current buffer looking for duplicate bibtex entries.
+ − 937 Buffer is assumed to be sorted, see \\[sort-bibtex-entries]"
+ − 938 (interactive)
+ − 939 (let ((point (point)))
+ − 940 ;; errors if things are not right...
+ − 941 (find-bibtex-entry-location (make-string 10 255))
+ − 942 (goto-char point)
+ − 943 (message "No duplicates found!")))
+ − 944
+ − 945
+ − 946 ;;; assoc doesn't ignore case, so we need an assoc that does...
+ − 947 (defun assoc-string-equalp (thing alist)
+ − 948 (or (assoc thing alist)
+ − 949 (while (and alist
+ − 950 (not (string-equalp thing (car (car alist)))))
+ − 951 (setq alist (cdr alist)))
+ − 952 (car alist)))
+ − 953
+ − 954 (defvar bibtex-maintain-sorted-entries nil
+ − 955 "*If true, bibtex-mode will attempt to maintain all bibtex entries in
+ − 956 sorted order.
+ − 957
+ − 958 Note that this is more a property of a file than a personal preference and
+ − 959 as such should normally be set via a file local variable entry.")
+ − 960
+ − 961 (defun bibtex-entry (entry-type &optional required optional)
+ − 962 (interactive (let* ((completion-ignore-case t)
+ − 963 (e-t (completing-read "Entry Type: " bibtex-entry-field-alist
+ − 964 nil t)))
+ − 965 (list e-t)))
+ − 966 (if (and (null required) (null optional))
+ − 967 (let* ((e (assoc-string-equalp entry-type bibtex-entry-field-alist))
+ − 968 (r-n-o (elt e 1))
+ − 969 (c-ref (elt e 2)))
+ − 970 (if (null e)
+ − 971 (error "Bibtex entry type %s not defined!"))
+ − 972 (if (and bibtex-include-OPTcrossref c-ref)
+ − 973 (setq required (elt c-ref 0)
+ − 974 optional (elt c-ref 1))
+ − 975 (setq required (elt r-n-o 0)
+ − 976 optional (elt r-n-o 1)))))
+ − 977 (let ((key (if bibtex-maintain-sorted-entries
+ − 978 (read-string (format "%s key: " entry-type)))))
+ − 979 (if key
+ − 980 (find-bibtex-entry-location key))
+ − 981 (bibtex-move-outside-of-entry)
+ − 982 (insert "@" entry-type "{")
+ − 983 (if key
+ − 984 (insert key))
+ − 985 (save-excursion
+ − 986 (mapcar 'bibtex-make-field required)
+ − 987 (if bibtex-include-OPTcrossref
+ − 988 (bibtex-make-optional-field "crossref"))
+ − 989 (if bibtex-include-OPTkey
+ − 990 (bibtex-make-optional-field "key"))
+ − 991 (mapcar 'bibtex-make-optional-field optional)
+ − 992 (mapcar 'bibtex-make-optional-field
+ − 993 bibtex-mode-user-optional-fields)
+ − 994 (if bibtex-include-OPTannote
+ − 995 (bibtex-make-optional-field "annote"))
+ − 996 (insert "\n}\n\n"))
+ − 997 (if key
+ − 998 (bibtex-next-field t))
+ − 999 (run-hooks 'bibtex-add-entry-hook)))
+ − 1000
+ − 1001 ;; (defun bibtex-entry (entry-type required optional)
+ − 1002 ;; (bibtex-move-outside-of-entry)
+ − 1003 ;; (insert (concat "@" entry-type "{,\n\n}\n\n"))
+ − 1004 ;; (previous-line 3)
+ − 1005 ;; (insert (mapconcat 'bibtex-make-entry required ",\n"))
+ − 1006 ;; (if required
+ − 1007 ;; (if optional
+ − 1008 ;; (insert ",\n")))
+ − 1009 ;; (insert (mapconcat 'bibtex-make-OPT-entry optional ",\n"))
+ − 1010 ;; (if bibtex-mode-user-optional-fields ;MON...
+ − 1011 ;; (progn
+ − 1012 ;; (if optional
+ − 1013 ;; (insert ",\n"))
+ − 1014 ;; (insert (mapconcat 'bibtex-make-OPT-entry
+ − 1015 ;; bibtex-mode-user-optional-fields
+ − 1016 ;; ",\n")))) ;MON
+ − 1017 ;; (up-list -1)
+ − 1018 ;; (forward-char 1))
+ − 1019
+ − 1020
+ − 1021 (defun bibtex-make-field (e-t)
+ − 1022 (interactive "sBibTeX entry type: ")
+ − 1023 (let ((name (if (consp e-t) (car e-t) e-t))
+ − 1024 (value (if (consp e-t) (cdr e-t) "")))
+ − 1025 (insert ",\n")
+ − 1026 (indent-to-column bibtex-name-alignment)
+ − 1027 (insert name " = ")
+ − 1028 (indent-to-column bibtex-text-alignment)
+ − 1029 ;; lucid emacs prin1-to-string breaks the undo chain. When they fix
+ − 1030 ;; that, the hack can be removed. [alarson:19930316.0805CST]
+ − 1031 ; (insert (prin1-to-string value))
+ − 1032 ;; begin hack
+ − 1033 (insert (format (if (stringp value) "\"%s\"" "%s")
+ − 1034 value))
+ − 1035 ;; end hack
+ − 1036 nil))
+ − 1037
+ − 1038 (defun bibtex-make-optional-field (e-t)
+ − 1039 (interactive "sOptional BibTeX entry type: ")
+ − 1040 (if (consp e-t)
+ − 1041 (setq e-t (cons (concat "OPT" (car e-t)) (cdr e-t)))
+ − 1042 (setq e-t (concat "OPT" e-t)))
+ − 1043 (bibtex-make-field e-t))
+ − 1044
+ − 1045 ;; What to do about crossref? if present, journal and year are
+ − 1046 ;; both optional. Due to this, i move all of them into optional. -- MON
+ − 1047
+ − 1048 (defun bibtex-Article ()
+ − 1049 (interactive)
+ − 1050 (bibtex-entry "Article"))
+ − 1051
+ − 1052 (defun bibtex-Book ()
+ − 1053 (interactive)
+ − 1054 (bibtex-entry "Book"))
+ − 1055
+ − 1056 (defun bibtex-Booklet ()
+ − 1057 (interactive)
+ − 1058 (bibtex-entry "Booklet"))
+ − 1059
+ − 1060 ;(defun bibtex-DEAthesis ()
+ − 1061 ; (interactive)
+ − 1062 ; (bibtex-entry "DEAthesis"))
+ − 1063
+ − 1064 (defun bibtex-InBook ()
+ − 1065 (interactive)
+ − 1066 (bibtex-entry "InBook"))
+ − 1067
+ − 1068 (defun bibtex-InCollection ()
+ − 1069 (interactive)
+ − 1070 (bibtex-entry "InCollection"))
+ − 1071
+ − 1072 (defun bibtex-InProceedings ()
+ − 1073 (interactive)
+ − 1074 (bibtex-entry "InProceedings"))
+ − 1075
+ − 1076 (defun bibtex-Manual ()
+ − 1077 (interactive)
+ − 1078 (bibtex-entry "Manual"))
+ − 1079
+ − 1080 (defun bibtex-MastersThesis ()
+ − 1081 (interactive)
+ − 1082 (bibtex-entry "MastersThesis"))
+ − 1083
+ − 1084 (defun bibtex-Misc ()
+ − 1085 (interactive)
+ − 1086 (bibtex-entry "Misc"))
+ − 1087
+ − 1088 (defun bibtex-PhdThesis ()
+ − 1089 (interactive)
+ − 1090 (bibtex-entry "PhdThesis"))
+ − 1091
+ − 1092 (defun bibtex-Proceedings ()
+ − 1093 (interactive)
+ − 1094 (bibtex-entry "Proceedings"))
+ − 1095
+ − 1096 (defun bibtex-TechReport ()
+ − 1097 (interactive)
+ − 1098 (bibtex-entry "TechReport"))
+ − 1099
+ − 1100 (defun bibtex-Unpublished ()
+ − 1101 (interactive)
+ − 1102 (bibtex-entry "Unpublished"))
+ − 1103
+ − 1104 (defun bibtex-string ()
+ − 1105 (interactive)
+ − 1106 (bibtex-move-outside-of-entry)
+ − 1107 (insert "@string{ = \"\"}\n")
+ − 1108 (previous-line 1)
+ − 1109 (forward-char 8))
+ − 1110
+ − 1111 (defun bibtex-preamble ()
+ − 1112 (interactive)
+ − 1113 (bibtex-move-outside-of-entry)
+ − 1114 (insert "@Preamble{}\n")
+ − 1115 (previous-line 1)
+ − 1116 (forward-char 10))
+ − 1117
+ − 1118 (defun bibtex-next-field (arg)
+ − 1119 "Finds end of text of next BibTeX field; with arg, to its beginning"
+ − 1120 (interactive "P")
+ − 1121 (bibtex-inside-field)
+ − 1122 (let ((start (point)))
+ − 1123 (condition-case ()
+ − 1124 (progn
+ − 1125 (bibtex-enclosing-field)
+ − 1126 (goto-char (match-end 0))
+ − 1127 (forward-char 2))
+ − 1128 (error
+ − 1129 (goto-char start)
+ − 1130 (end-of-line)
+ − 1131 (forward-char 1))))
+ − 1132 (bibtex-find-text arg))
+ − 1133
+ − 1134 ;; (defun bibtex-next-field ()
+ − 1135 ;; "Finds end of text of next field."
+ − 1136 ;; (interactive)
+ − 1137 ;; (condition-case ()
+ − 1138 ;; (progn
+ − 1139 ;; (bibtex-inside-field)
+ − 1140 ;; (re-search-forward ",[ \t\n]*" (point-max) 1)
+ − 1141 ;; (bibtex-enclosing-field)
+ − 1142 ;; (bibtex-inside-field))
+ − 1143 ;; (error nil)))
+ − 1144
+ − 1145 (defun bibtex-find-text (arg)
+ − 1146 "Go to end of text of current field; with arg, go to beginning."
+ − 1147 (interactive "P")
+ − 1148 (bibtex-inside-field)
+ − 1149 (bibtex-enclosing-field)
+ − 1150 (if arg
+ − 1151 (progn
+ − 1152 (goto-char (match-beginning bibtex-text-in-field))
+ − 1153 (if (looking-at "\"")
+ − 1154 (forward-char 1)))
+ − 1155 (goto-char (match-end bibtex-text-in-field))
+ − 1156 (if (= (preceding-char) ?\")
+ − 1157 (forward-char -1))))
+ − 1158
+ − 1159 ;; (defun bibtex-find-text ()
+ − 1160 ;; "Go to end of text of current field."
+ − 1161 ;; (interactive)
+ − 1162 ;; (condition-case ()
+ − 1163 ;; (progn
+ − 1164 ;; (bibtex-inside-field)
+ − 1165 ;; (bibtex-enclosing-field)
+ − 1166 ;; (goto-char (match-end bibtex-text-in-field))
+ − 1167 ;; (bibtex-inside-field))
+ − 1168 ;; (error nil)))
+ − 1169
+ − 1170 (defun bibtex-remove-OPT ()
+ − 1171 "Removes the 'OPT' starting optional arguments and goes to end of text"
+ − 1172 (interactive)
+ − 1173 (bibtex-inside-field)
+ − 1174 (bibtex-enclosing-field)
+ − 1175 (save-excursion
+ − 1176 (goto-char (match-beginning bibtex-name-in-field))
+ − 1177 (if (looking-at "OPT")
+ − 1178 ;; sct@dcs.edinburgh.ac.uk
+ − 1179 (progn
+ − 1180 (delete-char (length "OPT"))
+ − 1181 (search-forward "=")
+ − 1182 (delete-horizontal-space)
+ − 1183 (indent-to-column bibtex-text-alignment))))
+ − 1184 (bibtex-inside-field))
+ − 1185
+ − 1186 (defun bibtex-inside-field ()
+ − 1187 "Try to avoid point being at end of a bibtex field."
+ − 1188 (interactive)
+ − 1189 (end-of-line)
+ − 1190 (skip-chars-backward " \t") ;MON - maybe delete these chars?
+ − 1191 (cond ((= (preceding-char) ?,)
+ − 1192 (forward-char -2))) ; -1 --> -2 sct@dcs.edinburgh.ac.uk
+ − 1193 (cond ((= (preceding-char) ?\")
+ − 1194 (forward-char -1)))) ;MON - only go back if quote
+ − 1195
+ − 1196 (defun bibtex-remove-double-quotes ()
+ − 1197 "Removes \"\" around string."
+ − 1198 (interactive)
+ − 1199 (save-excursion
+ − 1200 (bibtex-inside-field)
+ − 1201 (bibtex-enclosing-field)
+ − 1202 (let ((start (match-beginning bibtex-text-in-field))
+ − 1203 (stop (match-end bibtex-text-in-field)))
+ − 1204 (goto-char stop)
+ − 1205 (forward-char -1)
+ − 1206 (if (looking-at "\"")
+ − 1207 (delete-char 1))
+ − 1208 (goto-char start)
+ − 1209 (if (looking-at "\"")
+ − 1210 (delete-char 1)))))
+ − 1211
+ − 1212 (defun bibtex-kill-optional-field ()
+ − 1213 "Kill the entire enclosing optional BibTeX field"
+ − 1214 (interactive)
+ − 1215 (bibtex-inside-field)
+ − 1216 (bibtex-enclosing-field)
+ − 1217 (goto-char (match-beginning bibtex-name-in-field))
+ − 1218 (let ((the-end (match-end 0))
+ − 1219 (the-beginning (match-beginning 0)))
+ − 1220 (if (looking-at "OPT")
+ − 1221 (progn
+ − 1222 (goto-char the-end)
+ − 1223 (skip-chars-forward " \t\n,")
+ − 1224 (kill-region the-beginning the-end))
+ − 1225 (error "Mandatory fields can't be killed"))))
+ − 1226
+ − 1227 (defun bibtex-empty-field ()
+ − 1228 "Delete the text part of the current field, replace with empty text"
+ − 1229 (interactive)
+ − 1230 (bibtex-inside-field)
+ − 1231 (bibtex-enclosing-field)
+ − 1232 (goto-char (match-beginning bibtex-text-in-field))
+ − 1233 (kill-region (point) (match-end bibtex-text-in-field))
+ − 1234 (insert "\"\"")
+ − 1235 (bibtex-find-text t))
+ − 1236
+ − 1237
+ − 1238 (defun bibtex-pop-previous (arg)
+ − 1239 "Replace text of current field with the text of similar field in previous entry.
+ − 1240 With arg, go up ARG entries. Repeated, goes up so many times. May be
+ − 1241 intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
+ − 1242 (interactive "p")
+ − 1243 (bibtex-inside-field)
+ − 1244 (save-excursion
+ − 1245 ; parse current field
+ − 1246 (bibtex-enclosing-field)
+ − 1247 (let ((start-old-text (match-beginning bibtex-text-in-field))
+ − 1248 (stop-old-text (match-end bibtex-text-in-field))
+ − 1249 (start-name (match-beginning bibtex-name-in-field))
+ − 1250 (stop-name (match-end bibtex-name-in-field))
+ − 1251 (new-text))
+ − 1252 (goto-char start-name)
+ − 1253 ; construct regexp for previous field with same name as this one
+ − 1254 (let ((matching-entry
+ − 1255 (bibtex-cfield
+ − 1256 (buffer-substring (if (looking-at "OPT")
+ − 1257 (+ (point) (length "OPT"))
+ − 1258 (point))
+ − 1259 stop-name)
+ − 1260 bibtex-field-text)))
+ − 1261
+ − 1262 ; if executed several times in a row, start each search where the
+ − 1263 ; last one finished
+ − 1264 (cond ((or (eq last-command 'bibtex-pop-previous)
+ − 1265 (eq last-command 'bibtex-pop-next))
+ − 1266 t
+ − 1267 )
+ − 1268 (t
+ − 1269 (bibtex-enclosing-reference)
+ − 1270 (setq bibtex-pop-previous-search-point (match-beginning 0))
+ − 1271 (setq bibtex-pop-next-search-point (match-end 0))))
+ − 1272 (goto-char bibtex-pop-previous-search-point)
+ − 1273
+ − 1274 ; Now search for arg'th previous similar field
+ − 1275 (cond
+ − 1276 ((re-search-backward matching-entry (point-min) t arg)
+ − 1277 (setq new-text
+ − 1278 (buffer-substring (match-beginning bibtex-text-in-cfield)
+ − 1279 (match-end bibtex-text-in-cfield)))
+ − 1280 ; Found a matching field. Remember boundaries.
+ − 1281 (setq bibtex-pop-next-search-point (match-end 0))
+ − 1282 (setq bibtex-pop-previous-search-point (match-beginning 0))
+ − 1283 (bibtex-flash-head)
+ − 1284 ; Go back to where we started, delete old text, and pop new.
+ − 1285 (goto-char stop-old-text)
+ − 1286 (delete-region start-old-text stop-old-text)
+ − 1287 (insert new-text))
+ − 1288 (t ; search failed
+ − 1289 (error "No previous matching BibTeX field."))))))
+ − 1290 (setq this-command 'bibtex-pop-previous))
+ − 1291
+ − 1292 (defun bibtex-pop-next (arg)
+ − 1293 "Replace text of current field with the text of similar field in next entry.
+ − 1294 With arg, go up ARG entries. Repeated, goes up so many times. May be
+ − 1295 intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
+ − 1296 (interactive "p")
+ − 1297 (bibtex-inside-field)
+ − 1298 (save-excursion
+ − 1299 ; parse current field
+ − 1300 (bibtex-enclosing-field)
+ − 1301 (let ((start-old-text (match-beginning bibtex-text-in-field))
+ − 1302 (stop-old-text (match-end bibtex-text-in-field))
+ − 1303 (start-name (match-beginning bibtex-name-in-field))
+ − 1304 (stop-name (match-end bibtex-name-in-field))
+ − 1305 (new-text))
+ − 1306 (goto-char start-name)
+ − 1307 ; construct regexp for next field with same name as this one,
+ − 1308 ; ignoring possible OPT's
+ − 1309 (let ((matching-entry
+ − 1310 (bibtex-cfield
+ − 1311 (buffer-substring (if (looking-at "OPT")
+ − 1312 (+ (point) (length "OPT"))
+ − 1313 (point))
+ − 1314 stop-name)
+ − 1315 bibtex-field-text)))
+ − 1316
+ − 1317 ; if executed several times in a row, start each search where the
+ − 1318 ; last one finished
+ − 1319 (cond ((or (eq last-command 'bibtex-pop-next)
+ − 1320 (eq last-command 'bibtex-pop-previous))
+ − 1321 t
+ − 1322 )
+ − 1323 (t
+ − 1324 (bibtex-enclosing-reference)
+ − 1325 (setq bibtex-pop-previous-search-point (match-beginning 0))
+ − 1326 (setq bibtex-pop-next-search-point (match-end 0))))
+ − 1327 (goto-char bibtex-pop-next-search-point)
+ − 1328
+ − 1329 ; Now search for arg'th next similar field
+ − 1330 (cond
+ − 1331 ((re-search-forward matching-entry (point-max) t arg)
+ − 1332 (setq new-text
+ − 1333 (buffer-substring (match-beginning bibtex-text-in-cfield)
+ − 1334 (match-end bibtex-text-in-cfield)))
+ − 1335 ; Found a matching field. Remember boundaries.
+ − 1336 (setq bibtex-pop-next-search-point (match-end 0))
+ − 1337 (setq bibtex-pop-previous-search-point (match-beginning 0))
+ − 1338 (bibtex-flash-head)
+ − 1339 ; Go back to where we started, delete old text, and pop new.
+ − 1340 (goto-char stop-old-text)
+ − 1341 (delete-region start-old-text stop-old-text)
+ − 1342 (insert new-text))
+ − 1343 (t ; search failed
+ − 1344 (error "No next matching BibTeX field."))))))
+ − 1345 (setq this-command 'bibtex-pop-next))
+ − 1346
+ − 1347 (defun bibtex-flash-head ()
+ − 1348 "Flash at BibTeX reference head before point, if exists. (Moves point)."
+ − 1349 (let ((flash))
+ − 1350 (cond ((re-search-backward bibtex-reference-head (point-min) t)
+ − 1351 (goto-char (match-beginning bibtex-type-in-head))
+ − 1352 (setq flash (match-end bibtex-key-in-reference)))
+ − 1353 (t
+ − 1354 (end-of-line)
+ − 1355 (skip-chars-backward " \t")
+ − 1356 (setq flash (point))
+ − 1357 (beginning-of-line)
+ − 1358 (skip-chars-forward " \t")))
+ − 1359 (if (pos-visible-in-window-p (point))
+ − 1360 (sit-for 1)
+ − 1361 (message "From: %s"
+ − 1362 (buffer-substring (point) flash)))))
+ − 1363
+ − 1364
+ − 1365
+ − 1366 (defun bibtex-enclosing-field ()
+ − 1367 "Search for BibTeX field enclosing point.
+ − 1368 Point moves to end of field; also, use match-beginning and match-end
+ − 1369 to parse the field."
+ − 1370 ;; sct@dcs.edinburgh.ac.uk
+ − 1371 (let ((old-point (point)))
+ − 1372 (condition-case errname
+ − 1373 (bibtex-enclosing-regexp bibtex-field)
+ − 1374 (search-failed
+ − 1375 (goto-char old-point)
+ − 1376 (error "Can't find enclosing BibTeX field.")))))
+ − 1377
+ − 1378 (defun bibtex-enclosing-reference ()
+ − 1379 "Search for BibTeX reference enclosing point.
+ − 1380 Point moves to end of reference; also, use match-beginning and match-end
+ − 1381 to parse the reference."
+ − 1382 ;; sct@dcs.edinburgh.ac.uk
+ − 1383 (let ((old-point (point)))
+ − 1384 (condition-case errname
+ − 1385 (bibtex-enclosing-regexp bibtex-reference)
+ − 1386 (search-failed
+ − 1387 (goto-char old-point)
+ − 1388 (error "Can't find enclosing BibTeX reference.")))))
+ − 1389
+ − 1390 (defun bibtex-enclosing-regexp (regexp)
+ − 1391 "Search for REGEXP enclosing point.
+ − 1392 Point moves to end of REGEXP. See also match-beginning and match-end.
+ − 1393 If an enclosing REGEXP is not found, signals search-failed; point is left in
+ − 1394 an undefined location.
+ − 1395
+ − 1396 [Doesn't something like this exist already?]"
+ − 1397
+ − 1398 (interactive "sRegexp: ")
+ − 1399 ; compute reasonable limits for the loop
+ − 1400 (let* ((initial (point))
+ − 1401 (right (if (re-search-forward regexp (point-max) t)
+ − 1402 (match-end 0)
+ − 1403 (point-max)))
+ − 1404 (left
+ − 1405 (progn
+ − 1406 (goto-char initial)
+ − 1407 (if (re-search-backward regexp (point-min) t)
+ − 1408 (match-beginning 0)
+ − 1409 (point-min)))))
+ − 1410 ; within the prescribed limits, loop until a match is found
+ − 1411 (goto-char left)
+ − 1412 (re-search-forward regexp right nil 1)
+ − 1413 (if (> (match-beginning 0) initial)
+ − 1414 (signal 'search-failed (list regexp)))
+ − 1415 (while (<= (match-end 0) initial)
+ − 1416 (re-search-forward regexp right nil 1)
+ − 1417 (if (> (match-beginning 0) initial)
+ − 1418 (signal 'search-failed (list regexp))))
+ − 1419 ))
+ − 1420
+ − 1421 (defun bibtex-clean-entry ()
+ − 1422 "For all optional fields of current BibTeX entry: if empty, kill the whole field; otherwise, remove the \"OPT\" string in the name; if text numerical, remove double-quotes. For all mandatory fields: if empty, signal error."
+ − 1423 (interactive)
+ − 1424 (beginning-of-bibtex-entry)
+ − 1425 (let ((start (point)))
+ − 1426 (save-restriction
+ − 1427 (narrow-to-region start (save-excursion (end-of-bibtex-entry) (point)))
+ − 1428 (while (re-search-forward bibtex-field (point-max) t 1)
+ − 1429 (let ((begin-field (match-beginning 0))
+ − 1430 (end-field (match-end 0))
+ − 1431 (begin-name (match-beginning bibtex-name-in-field))
+ − 1432 (end-name (match-end bibtex-name-in-field))
+ − 1433 (begin-text (match-beginning bibtex-text-in-field))
+ − 1434 (end-text (match-end bibtex-text-in-field))
+ − 1435 )
+ − 1436 (goto-char begin-name)
+ − 1437 (cond ((and
+ − 1438 (looking-at "OPT")
+ − 1439 bibtex-clean-entry-zap-empty-opts)
+ − 1440 (goto-char begin-text)
+ − 1441 (if (looking-at "\"\"") ; empty: delete whole field
+ − 1442 (delete-region begin-field end-field)
+ − 1443 ; otherwise: not empty, delete "OPT"
+ − 1444 (goto-char begin-name)
+ − 1445 (delete-char (length "OPT"))
+ − 1446 (progn
+ − 1447 ;; fixup alignment. [alarson:19920309.2047CST]
+ − 1448 (search-forward "=")
+ − 1449 (delete-horizontal-space)
+ − 1450 (indent-to-column bibtex-text-alignment))
+ − 1451 (goto-char begin-field) ; and loop to go through next test
+ − 1452 ))
+ − 1453 (t
+ − 1454 (goto-char begin-text)
+ − 1455 (cond ((looking-at "\"[0-9]+\"") ; if numerical,
+ − 1456 (goto-char end-text)
+ − 1457 (delete-char -1) ; delete enclosing double-quotes
+ − 1458 (goto-char begin-text)
+ − 1459 (delete-char 1)
+ − 1460 (goto-char end-field) ; go to end for next search
+ − 1461 (forward-char -2) ; to compensate for the 2 quotes deleted
+ − 1462 )
+ − 1463 ((looking-at "\"\"") ; if empty quotes, complain
+ − 1464 (forward-char 1)
+ − 1465 (if (not (or (equal (buffer-substring
+ − 1466 begin-name
+ − 1467 (+ begin-name 3))
+ − 1468 "OPT")
+ − 1469 (equal (buffer-substring
+ − 1470 begin-name
+ − 1471 (+ begin-name 3))
+ − 1472 "opt")))
+ − 1473 (error "Mandatory field ``%s'' is empty"
+ − 1474 (buffer-substring begin-name end-name))))
+ − 1475 (t
+ − 1476 (goto-char end-field))))))))
+ − 1477 (goto-char start)
+ − 1478 (end-of-bibtex-entry)
+ − 1479 ;; sct@dcs.edinburgh.ac.uk
+ − 1480 (save-excursion
+ − 1481 (previous-line 1)
+ − 1482 (end-of-line)
+ − 1483 (if (eq (preceding-char) ?,)
+ − 1484 (backward-delete-char 1)))
+ − 1485 (skip-whitespace-and-comments)))
+ − 1486
+ − 1487
+ − 1488 ;;; Menus for bibtex mode
+ − 1489
+ − 1490 (defconst bibtex-menu
+ − 1491 '("BibTeX Commands"
+ − 1492 "Entry Types"
+ − 1493 "---"
+ − 1494 ["Article in Conference Proceedings" bibtex-InProceedings t]
+ − 1495 ["Article in Journal" bibtex-Article t]
+ − 1496 ["Book" bibtex-Book t]
+ − 1497 ["Booklet" bibtex-Booklet t]
+ − 1498 ["Conference" bibtex-InProceedings t]
+ − 1499 ["Master's Thesis" bibtex-MastersThesis t]
+ − 1500 ["DEA Thesis" bibtex-DEAthesis t]
+ − 1501 ["Phd. Thesis" bibtex-PhdThesis t]
+ − 1502 ["Technical Report" bibtex-TechReport t]
+ − 1503 ["Technical Manual" bibtex-Manual t]
+ − 1504 ["Conference Proceedings" bibtex-Proceedings t]
+ − 1505 ["A Chapter in a Book" bibtex-InBook t]
+ − 1506 ["An Article in a Collection" bibtex-InCollection t]
+ − 1507 ["Miscellaneous" bibtex-Misc t]
+ − 1508 ["Unpublished" bibtex-Unpublished t]
+ − 1509 ["String" bibtex-string t]
+ − 1510 ["Preamble" bibtex-preamble t]
+ − 1511 "---"
+ − 1512 "Bibtex Edit"
+ − 1513 "---"
+ − 1514 ["Next Field" bibtex-next-field t]
+ − 1515 ["To End of Field" bibtex-find-text t]
+ − 1516 ["Snatch From Similar Preceding Field" bibtex-pop-previous t]
+ − 1517 ["Snatch From Similar Following Field" bibtex-pop-next t]
+ − 1518 ["Remove OPT" bibtex-remove-OPT t]
+ − 1519 ["Remove Quotes" bibtex-remove-double-quotes t]
+ − 1520 ["Clean Up Entry" bibtex-clean-entry t]
+ − 1521 ["Find Duplicates" find-bibtex-duplicates t]
+ − 1522 ["Sort Entries" sort-bibtex-entries t]
+ − 1523 ["Validate Entries" validate-bibtex-buffer t]
+ − 1524 ))
+ − 1525
+ − 1526 (defun bibtex-menu ()
+ − 1527 (interactive)
+ − 1528 (let ((popup-menu-titles nil))
+ − 1529 (popup-menu bibtex-menu)))
+ − 1530
+ − 1531 ;;; bibtex.el ends here