]> code.delx.au - gnu-emacs/blobdiff - lisp/textmodes/bibtex.el
Auto-commit of loaddefs files.
[gnu-emacs] / lisp / textmodes / bibtex.el
index 741b6cd904cf0d1d5b081fda98b3b265110898a7..8a99ff2926dda2b20e1dcaaffe1385c59b78bf54 100644 (file)
@@ -1,6 +1,7 @@
 ;;; bibtex.el --- BibTeX mode for GNU Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992, 1994-1999, 2001-2011  Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994-1999, 2001-2014 Free Software Foundation,
+;; Inc.
 
 ;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
 ;;      Bengt Martensson <bengt@mathematik.uni-Bremen.de>
@@ -443,6 +444,7 @@ which is called to determine the initial content of the field.
 ALTERNATIVE if non-nil is an integer that numbers sets of
 alternatives, starting from zero."
   :group 'BibTeX
+  :version "24.1"
   :type 'bibtex-entry-alist)
 (put 'bibtex-BibTeX-entry-alist 'risky-local-variable t)
 
@@ -466,7 +468,7 @@ alternatives, starting from zero."
      nil
      (("editor") ("editora") ("editorb") ("editorc")
       ("translator") ("annotator") ("commentator")
-      ("introduction") ("foreword") ("afterword") ("titleaddon")
+      ("introduction") ("foreword") ("afterword") ("subtitle") ("titleaddon")
       ("maintitle") ("mainsubtitle") ("maintitleaddon")
       ("language") ("origlanguage") ("volume") ("part") ("edition") ("volumes")
       ("series") ("number") ("note") ("publisher") ("location") ("isbn")
@@ -544,9 +546,9 @@ alternatives, starting from zero."
       ("location") ("isbn") ("pagetotal") ("addendum") ("pubstate") ("doi")
       ("eprint") ("eprintclass") ("eprinttype") ("url") ("urldate")))
     ("InCollection" "Article in a Collection"
-     (("author") ("editor") ("title") ("year" nil nil 0) ("date" nil nil 0))
+     (("author") ("title") ("year" nil nil 0) ("date" nil nil 0))
      (("booktitle"))
-     (("editora") ("editorb") ("editorc") ("translator") ("annotator")
+     (("editor") ("editora") ("editorb") ("editorc") ("translator") ("annotator")
       ("commentator") ("introduction") ("foreword") ("afterword")
       ("subtitle") ("titleaddon") ("maintitle") ("mainsubtitle")
       ("maintitleaddon") ("booksubtitle") ("booktitleaddon")
@@ -614,10 +616,11 @@ alternatives, starting from zero."
       ("addendum") ("pubstate") ("doi") ("eprint") ("eprintclass")
       ("eprinttype") ("url") ("urldate")))
     ("Proceedings" "Single-Volume Conference Proceedings"
-     (("editor") ("title") ("year" nil nil 0) ("date" nil nil 0))
+     (("title") ("year" nil nil 0) ("date" nil nil 0))
      nil
      (("subtitle") ("titleaddon") ("maintitle") ("mainsubtitle")
       ("maintitleaddon") ("eventtitle") ("eventdate") ("venue") ("language")
+      ("editor")
       ("volume") ("part") ("volumes") ("series") ("number") ("note")
       ("organization") ("publisher") ("location") ("month")
       ("isbn") ("chapter") ("pages") ("pagetotal") ("addendum") ("pubstate")
@@ -631,9 +634,9 @@ alternatives, starting from zero."
       ("isbn") ("pagetotal") ("addendum") ("pubstate")
       ("doi") ("eprint") ("eprintclass") ("eprinttype") ("url") ("urldate")))
     ("InProceedings" "Article in Conference Proceedings"
-     (("author") ("editor") ("title") ("year" nil nil 0) ("date" nil nil 0))
+     (("author") ("title") ("year" nil nil 0) ("date" nil nil 0))
      (("booktitle"))
-     (("subtitle") ("titleaddon") ("maintitle") ("mainsubtitle")
+     (("editor") ("subtitle") ("titleaddon") ("maintitle") ("mainsubtitle")
       ("maintitleaddon") ("booksubtitle") ("booktitleaddon")
       ("eventtitle") ("eventdate") ("venue") ("language")
       ("volume") ("part") ("volumes") ("series") ("number") ("note")
@@ -696,6 +699,7 @@ alternatives, starting from zero."
   "Alist of biblatex entry types and their associated fields.
 It has the same format as `bibtex-BibTeX-entry-alist'."
   :group 'bibtex
+  :version "24.1"
   :type 'bibtex-entry-alist)
 (put 'bibtex-biblatex-entry-alist 'risky-local-variable t)
 
@@ -717,6 +721,7 @@ It has the same format as `bibtex-BibTeX-entry-alist'."
 Each element is a list (FIELD COMMENT).  COMMENT is used as a default
 if `bibtex-BibTeX-entry-alist' does not define a comment for FIELD."
   :group 'bibtex
+  :version "24.1"
   :type 'bibtex-field-alist)
 
 (defcustom bibtex-biblatex-field-alist
@@ -814,6 +819,7 @@ if `bibtex-BibTeX-entry-alist' does not define a comment for FIELD."
     "Alist of biblatex fields.
 It has the same format as `bibtex-BibTeX-entry-alist'."
   :group 'bibtex
+  :version "24.1"
   :type 'bibtex-field-alist)
 
 (defcustom bibtex-dialect-list '(BibTeX biblatex)
@@ -822,12 +828,14 @@ For each DIALECT (a symbol) a variable bibtex-DIALECT-entry-alist defines
 the allowed entries and bibtex-DIALECT-field-alist defines known field types.
 Predefined dialects include BibTeX and biblatex."
   :group 'bibtex
+  :version "24.1"
   :type '(repeat (symbol :tag "Dialect")))
 
 (defcustom bibtex-dialect 'BibTeX
   "Current BibTeX dialect.  For allowed values see `bibtex-dialect-list'.
-During a session change it via `bibtex-set-dialect'."
+To interactively change the dialect use the command `bibtex-set-dialect'."
   :group 'bibtex
+  :version "24.1"
   :set '(lambda (symbol value)
           (set-default symbol value)
           ;; `bibtex-set-dialect' is undefined during loading (no problem)
@@ -836,11 +844,13 @@ During a session change it via `bibtex-set-dialect'."
   :type '(choice (const BibTeX)
                  (const biblatex)
                  (symbol :tag "Custom")))
+(put 'bibtex-dialect 'safe-local-variable 'symbolp)
 
 (defcustom bibtex-no-opt-remove-re "\\`option"
   "If a field name matches this regexp, the prefix OPT is not removed.
 If nil prefix OPT is always removed"
   :group 'bibtex
+  :version "24.1"
   :type '(choice (regexp) (const nil)))
 
 (defcustom bibtex-comment-start "@Comment"
@@ -908,8 +918,10 @@ to the directories specified in `bibtex-string-file-path'."
   :group 'bibtex
   :type '(repeat file))
 
-(defvar bibtex-string-file-path (getenv "BIBINPUTS")
-  "*Colon separated list of paths to search for `bibtex-string-files'.")
+(defcustom bibtex-string-file-path (getenv "BIBINPUTS")
+  "Colon-separated list of paths to search for `bibtex-string-files'."
+  :group 'bibtex
+  :type 'string)
 
 (defcustom bibtex-files nil
   "List of BibTeX files that are searched for entry keys.
@@ -922,13 +934,16 @@ See also `bibtex-search-entry-globally'."
   :type '(repeat (choice (const :tag "bibtex-file-path" bibtex-file-path)
                          directory file)))
 
-(defvar bibtex-file-path (getenv "BIBINPUTS")
-  "*Colon separated list of paths to search for `bibtex-files'.")
+(defcustom bibtex-file-path (getenv "BIBINPUTS")
+  "Colon separated list of paths to search for `bibtex-files'."
+  :group 'bibtex
+  :type 'string)
 
 (defcustom bibtex-search-entry-globally nil
   "If non-nil, interactive calls of `bibtex-search-entry' search globally.
 A global search includes all files in `bibtex-files'."
   :group 'bibtex
+  :version "24.1"
   :type 'boolean)
 
 (defcustom bibtex-help-message t
@@ -989,6 +1004,7 @@ See `bibtex-generate-autokey' for details."
     ("\\\\`\\|\\\\'\\|\\\\\\^\\|\\\\~\\|\\\\=\\|\\\\\\.\\|\\\\u\\|\\\\v\\|\\\\H\\|\\\\t\\|\\\\c\\|\\\\d\\|\\\\b" . "")
     ;; braces, quotes, concatenation.
     ("[`'\"{}#]" . "")
+    ("\\\\-" . "")                        ; \-            ->
     ;; spaces
     ("\\\\?[ \t\n]+\\|~" . " "))
   "Alist of (OLD-REGEXP . NEW-STRING) pairs.
@@ -1209,7 +1225,10 @@ Used by `bibtex-complete-crossref-cleanup' and `bibtex-copy-summary-as-kill'."
                  (function :tag "Personalized function")))
 
 (defcustom bibtex-generate-url-list
-  '((("url" . ".*:.*")))
+  '((("url" . ".*:.*"))
+    (("doi" . "10\\.[0-9]+/.+")
+     "http://dx.doi.org/%s"
+     ("doi" ".*" 0)))
   "List of schemes for generating the URL of a BibTeX entry.
 These schemes are used by `bibtex-url'.
 
@@ -1246,6 +1265,7 @@ The following is a complex example, see URL `http://link.aps.org/'.
      (\"volume\" \".*\" 0)
      (\"pages\" \"\\`[A-Z]?[0-9]+\" 0)))"
   :group 'bibtex
+  :version "24.4"
   :type '(repeat
           (cons :tag "Scheme"
                 (cons :tag "Matcher" :extra-offset 4
@@ -1290,6 +1310,7 @@ Set this variable before loading BibTeX mode."
 (defcustom bibtex-search-buffer "*BibTeX Search*"
   "Buffer for BibTeX search results."
   :group 'bibtex
+  :version "24.1"
   :type 'string)
 
 ;; `bibtex-font-lock-keywords' is a user option, too.  But since the
@@ -1442,21 +1463,23 @@ Set this variable before loading BibTeX mode."
 \f
 ;; Internal Variables
 
-(defvar bibtex-entry-alist bibtex-BibTeX-entry-alist
-  "Alist of currently active entry types.")
+(defvar bibtex-entry-alist nil
+  "Alist of currently active entry types.
+Initialized by `bibtex-set-dialect'.")
 
-(defvar bibtex-field-alist bibtex-BibTeX-field-alist
-  "Alist of currently active field types.")
+(defvar bibtex-field-alist nil
+  "Alist of currently active field types.
+Initialized by `bibtex-set-dialect'.")
 
 (defvar bibtex-field-braces-opt nil
   "Optimized value of `bibtex-field-braces-alist'.
 Created by `bibtex-field-re-init'.
-It is a an alist with elements (FIELD . REGEXP).")
+It is an alist with elements (FIELD . REGEXP).")
 
 (defvar bibtex-field-strings-opt nil
   "Optimized value of `bibtex-field-strings-alist'.
 Created by `bibtex-field-re-init'.
-It is a an alist with elements (FIELD RULE1 RULE2 ...),
+It is an alist with elements (FIELD RULE1 RULE2 ...),
 where each RULE is (REGEXP . TO-STR).")
 
 (defvar bibtex-pop-previous-search-point nil
@@ -1602,7 +1625,7 @@ Initialized by `bibtex-set-dialect'.")
     ,@(mapcar (lambda (matcher)
                 `((lambda (bound) (bibtex-font-lock-cite ',matcher bound))))
               bibtex-cite-matcher-alist))
-  "*Default expressions to highlight in BibTeX mode.")
+  "Default expressions to highlight in BibTeX mode.")
 
 (defvar bibtex-font-lock-url-regexp
   ;; Assume that field names begin at the beginning of a line.
@@ -2188,6 +2211,10 @@ Optional arg COMMA is as in `bibtex-enclosing-field'."
   (let ((fun (lambda (kryp kr) ; adapted from `current-kill'
                (car (set kryp (nthcdr (mod (- n (length (eval kryp)))
                                            (length kr)) kr))))))
+    ;; We put the mark at the beginning of the inserted field or entry
+    ;; and point at its end - a behavior similar to what `yank' does.
+    ;; The mark is then used by `bibtex-yank-pop', which needs to know
+    ;; what we have inserted.
     (if (eq bibtex-last-kill-command 'field)
         (progn
           ;; insert past the current field
@@ -2216,7 +2243,7 @@ Optional arg COMMA is as in `bibtex-enclosing-field'."
   (aset vec idx (cons newelt (aref vec idx))))
 
 (defsubst bibtex-vec-incr (vec idx)
-  "Add NEWELT to the list stored in VEC at index IDX."
+  "Increment by 1 the counter which is stored in VEC at index IDX."
   (aset vec idx (1+ (aref vec idx))))
 
 (defun bibtex-format-entry ()
@@ -2998,11 +3025,14 @@ Parsing initializes `bibtex-reference-keys' and `bibtex-strings'."
 Visit the BibTeX files defined by `bibtex-files' and return a list
 of corresponding buffers.
 Initialize in these buffers `bibtex-reference-keys' if not yet set.
-List of BibTeX buffers includes current buffer if CURRENT is non-nil.
+List of BibTeX buffers includes current buffer if CURRENT is non-nil
+and the current buffer visits a file using `bibtex-mode'.
 If FORCE is non-nil, (re)initialize `bibtex-reference-keys' even if
 already set.  If SELECT is non-nil interactively select a BibTeX buffer.
-When called interactively, FORCE is t, CURRENT is t if current buffer uses
-`bibtex-mode', and SELECT is t if current buffer does not use `bibtex-mode',"
+
+When called interactively, FORCE is t, CURRENT is t if current buffer
+visits a file using `bibtex-mode', and SELECT is t if current buffer
+does not use `bibtex-mode',"
   (interactive (list (eq major-mode 'bibtex-mode) t
                      (not (eq major-mode 'bibtex-mode))))
   (let ((file-path (split-string (or bibtex-file-path default-directory) ":+"))
@@ -3040,10 +3070,12 @@ When called interactively, FORCE is t, CURRENT is t if current buffer uses
       (if (file-readable-p file)
         (push (find-file-noselect file) buffer-list)))
     ;; Include current buffer iff we want it.
-    ;; Exclude current buffer if it doesn't use `bibtex-mode'.
-    ;; Thus calling `bibtex-initialize' gives meaningful results for
-    ;; any current buffer.
-    (unless (and current (eq major-mode 'bibtex-mode)) (setq current nil))
+    ;; Exclude current buffer if it does not visit a file using `bibtex-mode'.
+    ;; This way we exclude BibTeX buffers such as `bibtex-search-buffer'
+    ;; that are not visiting a BibTeX file.  Also, calling `bibtex-initialize'
+    ;; gives meaningful results for any current buffer.
+    (unless (and current (eq major-mode 'bibtex-mode) buffer-file-name)
+      (setq current nil))
     (cond ((and current (not (memq (current-buffer) buffer-list)))
            (push (current-buffer) buffer-list))
           ((and (not current) (memq (current-buffer) buffer-list))
@@ -3373,107 +3405,127 @@ if that value is non-nil.
   (set (make-local-variable 'syntax-propertize-function)
        (syntax-propertize-via-font-lock
         bibtex-font-lock-syntactic-keywords))
-  (setq imenu-generic-expression
-        (list (list nil bibtex-entry-head bibtex-key-in-head))
-        imenu-case-fold-search t)
-  (bibtex-set-dialect bibtex-dialect))
-
-(defun bibtex-set-dialect (dialect)
-  "Select BibTeX mode DIALECT.
-This sets the variable `bibtex-dialect' which holds the currently active
-dialect.  Dialects are listed in `bibtex-dialect-list'."
+  ;; Allow `bibtex-dialect' as a file-local variable.
+  (add-hook 'hack-local-variables-hook 'bibtex-set-dialect nil t))
+
+(defun bibtex-entry-alist (dialect)
+  "Return entry-alist for DIALECT."
+  (let ((var (intern (format "bibtex-%s-entry-alist" dialect)))
+        entry-alist)
+    (if (boundp var)
+        (setq entry-alist (symbol-value var))
+      (error "BibTeX dialect `%s' undefined" dialect))
+    (if (not (consp (nth 1 (car entry-alist))))
+        ;; new format
+        entry-alist
+      ;; Convert old format of `bibtex-entry-field-alist'
+      (unless (get var 'entry-list-format)
+        (put var 'entry-list-format "pre-24")
+        (message "Old format of `%s' (pre GNU Emacs 24).
+Please convert to the new format."
+                 (if (eq (indirect-variable 'bibtex-entry-field-alist) var)
+                     'bibtex-entry-field-alist var))
+        (sit-for 3))
+      (let (lst)
+        (dolist (entry entry-alist)
+          (let ((fl (nth 1 entry)) req xref opt)
+            (dolist (field (copy-tree (car fl)))
+              (if (nth 3 field) (setcar (nthcdr 3 field) 0))
+              (if (or (not (nth 2 entry))
+                      (assoc-string (car field) (car (nth 2 entry)) t))
+                  (push field req)
+                (push field xref)))
+            (dolist (field (nth 1 fl))
+              (push field opt))
+            (push (list (car entry) nil (nreverse req)
+                        (nreverse xref) (nreverse opt))
+                  lst)))
+        (nreverse lst)))))
+
+(defun bibtex-set-dialect (&optional dialect local)
+  "Select BibTeX DIALECT for editing BibTeX files.
+This sets the user variable `bibtex-dialect' as well as the dialect-dependent
+internal variables.  Allowed dialects are listed in `bibtex-dialect-list'.
+If DIALECT is nil use current value of `bibtex-dialect'.
+If LOCAL is non-nil make buffer-local bindings for these variables rather than
+setting the global values.  The dialect-dependent internal variables
+are also bound buffer-locally if `bibtex-dialect' is already buffer-local
+in the current buffer (for example, as a file-local variable).
+LOCAL is t for interactive calls."
   (interactive (list (intern (completing-read "Dialect: "
                                               (mapcar 'list bibtex-dialect-list)
-                                              nil t))))
-  (unless (eq dialect (get 'bibtex-dialect 'dialect))
-    (put 'bibtex-dialect 'dialect dialect)
-    (setq bibtex-dialect dialect)
-
-  ;; Bind variables
-    (setq bibtex-entry-alist
-          (let ((var (intern (format "bibtex-%s-entry-alist" dialect)))
-                entry-alist)
-            (if (boundp var)
-                (setq entry-alist (symbol-value var))
-              (error "BibTeX dialect `%s' undefined" dialect))
-            (if (not (consp (nth 1 (car entry-alist))))
-                ;; new format
-                entry-alist
-              ;; Convert old format
-              (unless (get var 'entry-list-format)
-                (put var 'entry-list-format "pre-24")
-                (message "Old format of `%s' (pre GNU Emacs 24).
-Please convert to the new format."
-                         (if (eq (indirect-variable 'bibtex-entry-field-alist) var)
-                             'bibtex-entry-field-alist var))
-                (sit-for 3))
-              (let (lst)
-                (dolist (entry entry-alist)
-                  (let ((fl (nth 1 entry)) req xref opt)
-                    (dolist (field (copy-tree (car fl)))
-                      (if (nth 3 field) (setcar (nthcdr 3 field) 0))
-                      (if (or (not (nth 2 entry))
-                              (assoc-string (car field) (car (nth 2 entry)) t))
-                          (push field req)
-                        (push field xref)))
-                    (dolist (field (nth 1 fl))
-                      (push field opt))
-                    (push (list (car entry) nil (nreverse req)
-                                (nreverse xref) (nreverse opt))
-                          lst)))
-                (nreverse lst))))
-          bibtex-field-alist
-          (let ((var (intern (format "bibtex-%s-field-alist" dialect))))
-            (if (boundp var)
-                (symbol-value var)
-              (error "Field types for BibTeX dialect `%s' undefined" dialect)))
-          bibtex-entry-type
-          (concat "@[ \t]*\\(?:"
-                  (regexp-opt (mapcar 'car bibtex-entry-alist)) "\\)")
-          bibtex-entry-head (concat "^[ \t]*\\("
-                                    bibtex-entry-type
-                                    "\\)[ \t]*[({][ \t\n]*\\("
-                                    bibtex-reference-key
-                                    "\\)")
-          bibtex-entry-maybe-empty-head (concat bibtex-entry-head "?")
-          bibtex-any-valid-entry-type
-          (concat "^[ \t]*@[ \t]*\\(?:"
-                  (regexp-opt (append '("String" "Preamble")
-                                      (mapcar 'car bibtex-entry-alist))) "\\)"))
-    ;; Define entry commands
-    (dolist (elt bibtex-entry-alist)
-      (let* ((entry (car elt))
-             (fname (intern (concat "bibtex-" entry))))
-        (unless (fboundp fname)
-          (eval (list 'defun fname nil
-                      (format "Insert a new BibTeX @%s entry; see also `bibtex-entry'."
-                              entry)
-                      '(interactive "*")
-                      `(bibtex-entry ,entry))))))
-    ;; Define menu
-    ;; We use the same keymap for all BibTeX buffers.  So all these buffers
-    ;; have the same BibTeX dialect.  To define entry types buffer-locally,
-    ;; it would be necessary to give each BibTeX buffer a new keymap that
-    ;; becomes a child of `bibtex-mode-map'.  Useful??
-    (easy-menu-define
-      nil bibtex-mode-map "Entry-Types Menu in BibTeX mode"
-      (apply 'list "Entry-Types"
-             (append
-              (mapcar (lambda (entry)
-                        (vector (or (nth 1 entry) (car entry))
-                                (intern (format "bibtex-%s" (car entry))) t))
-                      bibtex-entry-alist)
-              `("---"
-                ["String" bibtex-String t]
-                ["Preamble" bibtex-Preamble t]
-                "---"
-                ,(append '("BibTeX dialect")
-                         (mapcar (lambda (dialect)
-                                   (vector (symbol-name dialect)
-                                           `(lambda () (interactive)
-                                              (bibtex-set-dialect ',dialect))
-                                           t))
-                                 bibtex-dialect-list))))))))
+                                              nil t)) t))
+  (let ((setfun (if (or local (local-variable-p 'bibtex-dialect))
+                    (lambda (var val) (set (make-local-variable var) val))
+                  'set)))
+    (if dialect (funcall setfun 'bibtex-dialect dialect))
+
+    ;; Set internal variables
+    (funcall setfun 'bibtex-entry-alist (bibtex-entry-alist bibtex-dialect))
+    (funcall setfun 'bibtex-field-alist
+             (let ((var (intern (format "bibtex-%s-field-alist"
+                                        bibtex-dialect))))
+               (if (boundp var)
+                   (symbol-value var)
+                 (error "Field types for BibTeX dialect `%s' undefined"
+                        bibtex-dialect))))
+    (funcall setfun 'bibtex-entry-type
+             (concat "@[ \t]*\\(?:"
+                     (regexp-opt (mapcar 'car bibtex-entry-alist)) "\\)"))
+    (funcall setfun 'bibtex-entry-head
+             (concat "^[ \t]*\\(" bibtex-entry-type "\\)[ \t]*[({][ \t\n]*\\("
+                     bibtex-reference-key "\\)"))
+    (funcall setfun 'bibtex-entry-maybe-empty-head
+             (concat bibtex-entry-head "?"))
+    (funcall setfun 'bibtex-any-valid-entry-type
+             (concat "^[ \t]*@[ \t]*\\(?:"
+                     (regexp-opt
+                      (append '("String" "Preamble")
+                              (mapcar 'car bibtex-entry-alist))) "\\)"))
+    (setq imenu-generic-expression
+          (list (list nil bibtex-entry-head bibtex-key-in-head))
+          imenu-case-fold-search t)))
+
+;; Entry commands and menus for BibTeX dialects
+;; We do not use `easy-menu-define' here because this gets confused
+;; if we want to have multiple versions of the "same" menu.
+(let ((select-map (make-sparse-keymap)))
+  ;; Submenu for selecting the dialect
+  (dolist (dialect (reverse bibtex-dialect-list))
+    (define-key select-map (vector dialect)
+      `(menu-item ,(symbol-name dialect)
+                  (lambda () (interactive) (bibtex-set-dialect ',dialect t))
+                  :button (:radio . (eq bibtex-dialect ',dialect)))))
+  ;; We define a menu for each dialect.
+  ;; Then we select the menu we want via the :visible keyword
+  (dolist (dialect bibtex-dialect-list)
+    (let ((entry-alist (bibtex-entry-alist dialect))
+          (menu-map (make-sparse-keymap)))
+      (define-key menu-map [select]
+        `(menu-item "BibTeX dialect" ,select-map))
+      (define-key menu-map [nil-2] '(menu-item "--"))
+      (define-key menu-map [bibtex-preamble]
+        '(menu-item "Preamble" bibtex-Preamble))
+      (define-key menu-map [bibtex-String]
+        '(menu-item "String" bibtex-String))
+      (define-key menu-map [nil-1] '(menu-item "--"))
+      (dolist (elt (reverse entry-alist))
+        ;; Entry commands
+        (let* ((entry (car elt))
+               (fname (intern (format "bibtex-%s" entry))))
+          (unless (fboundp fname)
+            (eval (list 'defun fname nil
+                        (format "Insert a template for a @%s entry; see also `bibtex-entry'."
+                                entry)
+                        '(interactive "*")
+                        `(bibtex-entry ,entry))))
+          ;; Menu entries
+          (define-key menu-map (vector fname)
+            `(menu-item ,(or (nth 1 elt) (car elt)) ,fname))))
+      (define-key bibtex-mode-map
+        (vector 'menu-bar dialect)
+        `(menu-item "Entry-Types" ,menu-map
+                    :visible (eq bibtex-dialect ',dialect))))))
 
 (defun bibtex-field-list (entry-type)
   "Return list of allowed fields for entry ENTRY-TYPE.
@@ -3505,7 +3557,7 @@ and `bibtex-user-optional-fields'."
     (cons required optional)))
 
 (defun bibtex-entry (entry-type)
-  "Insert a new BibTeX entry of type ENTRY-TYPE.
+  "Insert a template for a BibTeX entry of type ENTRY-TYPE.
 After insertion call the value of `bibtex-add-entry-hook' if that value
 is non-nil."
   (interactive
@@ -3595,7 +3647,7 @@ If optional arg CONTENT is non-nil extract content of text fields."
 (defun bibtex-autofill-entry ()
   "Try to fill fields of current BibTeX entry based on neighboring entries.
 The current entry must have a key.  Determine the neighboring entry
-\(previouse or next\) whose key is more similar to the key of the current
+\(previous or next\) whose key is more similar to the key of the current
 entry.  For all empty fields of the current entry insert the corresponding
 field contents of the neighboring entry.  Finally try to update the text
 based on the difference between the keys of the neighboring and the current
@@ -3941,7 +3993,7 @@ If `bibtex-files' is non-nil, search all these files.
 Otherwise the search is limited to the current buffer.
 Return position of entry if CROSSREF-KEY is found or nil otherwise.
 If CROSSREF-KEY is in the same buffer like current entry but before it
-an error is signaled.  If NOERRER is non-nil this error is suppressed.
+an error is signaled.  If NOERROR is non-nil this error is suppressed.
 Optional arg PNT is the position of the referencing entry.  It defaults
 to position of point.  If optional arg SPLIT is non-nil, split window
 so that both the referencing and the crossrefed entry are displayed.
@@ -4853,21 +4905,22 @@ If mark is active reformat entries in region, if not in whole buffer."
                  (if use-previous-options
                      bibtex-reformat-previous-options
                    (setq bibtex-reformat-previous-options
-                         (mapcar (lambda (option)
-                                   (if (y-or-n-p (car option)) (cdr option)))
-                                 `(("Realign entries (recommended)? " . 'realign)
-                                   ("Remove empty optional and alternative fields? " . 'opts-or-alts)
-                                   ("Remove delimiters around pure numerical fields? " . 'numerical-fields)
-                                   (,(concat (if bibtex-comma-after-last-field "Insert" "Remove")
-                                             " comma at end of entry? ") . 'last-comma)
-                                   ("Replace double page dashes by single ones? " . 'page-dashes)
-                                   ("Delete whitespace at the beginning and end of fields? " . 'whitespace)
-                                   ("Inherit booktitle? " . 'inherit-booktitle)
-                                   ("Force delimiters? " . 'delimiters)
-                                   ("Unify case of entry types and field names? " . 'unify-case)
-                                   ("Enclose parts of field entries by braces? " . 'braces)
-                                   ("Replace parts of field entries by string constants? " . 'strings)
-                                   ("Sort fields? " . 'sort-fields))))))
+                         (delq nil
+                               (mapcar (lambda (option)
+                                         (if (y-or-n-p (car option)) (cdr option)))
+                                       `(("Realign entries (recommended)? " . realign)
+                                         ("Remove empty optional and alternative fields? " . opts-or-alts)
+                                         ("Remove delimiters around pure numerical fields? " . numerical-fields)
+                                         (,(concat (if bibtex-comma-after-last-field "Insert" "Remove")
+                                                   " comma at end of entry? ") . last-comma)
+                                         ("Replace double page dashes by single ones? " . page-dashes)
+                                         ("Delete whitespace at the beginning and end of fields? " . whitespace)
+                                         ("Inherit booktitle? " . inherit-booktitle)
+                                         ("Force delimiters? " . delimiters)
+                                         ("Unify case of entry types and field names? " . unify-case)
+                                         ("Enclose parts of field entries by braces? " . braces)
+                                         ("Replace parts of field entries by string constants? " . strings)
+                                         ("Sort fields? " . sort-fields)))))))
                 ;; Do not include required-fields because `bibtex-reformat'
                 ;; cannot handle the error messages of `bibtex-format-entry'.
                 ;; Use `bibtex-validate' to check for required fields.
@@ -5120,6 +5173,9 @@ Return the URL or nil if none can be generated."
                     (if (stringp (car scheme))
                         (setq fmt (pop scheme)))
                     (dolist (step scheme)
+                      ;; In the first STEP, if the field contains multiple
+                      ;; matches, we want the match the closest to point.
+                      ;; (if (eq step (car scheme))
                       (setq text (cdr (assoc-string (car step) fields-alist t)))
                       (if (string-match (nth 1 step) text)
                           (push (cond ((functionp (nth 2 step))
@@ -5140,7 +5196,7 @@ Return the URL or nil if none can be generated."
          (message "No URL known."))
       url)))
 
-;; We could combine multiple seach results with set operations
+;; We could combine multiple search results with set operations
 ;; AND, OR, MINUS, and NOT.  Would this be useful?
 ;; How complicated are searches in real life?
 ;; We could also have other searches such as "publication year newer than...".
@@ -5190,19 +5246,22 @@ where FILE is the BibTeX file of ENTRY."
           (if (string= "" field)
               ;; Unrestricted search.
               (while (re-search-forward regexp nil t)
-                (let ((beg (bibtex-beginning-of-entry))
-                      (end (bibtex-end-of-entry))
-                      key)
-                  (if (and (<= beg (match-beginning 0))
-                           (<= (match-end 0) end)
-                           (save-excursion
-                             (goto-char beg)
-                             (and (looking-at bibtex-entry-head)
-                                  (setq key (bibtex-key-in-head))))
-                           (not (assoc key entries)))
-                      (push (list key file
-                                  (buffer-substring-no-properties beg end))
-                            entries))))
+                (save-excursion
+                  (let ((mbeg (match-beginning 0))
+                        (mend (match-end 0))
+                        (beg (bibtex-beginning-of-entry))
+                        (end (bibtex-end-of-entry))
+                        key)
+                    (if (and (<= beg mbeg)
+                             (<= mend end)
+                             (progn
+                               (goto-char beg)
+                               (looking-at bibtex-entry-head))
+                             (setq key (bibtex-key-in-head))
+                             (not (assoc key entries)))
+                        (push (list key file
+                                    (buffer-substring-no-properties beg end))
+                              entries)))))
             ;; The following is slow.  But it works reliably even in more
             ;; complicated cases with BibTeX string constants and crossrefed
             ;; entries.  If you prefer speed over reliability, perform an