;;; bibtex.el --- BibTeX mode for GNU Emacs
-;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002,
-;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994-1999, 2001-2011 Free Software Foundation, Inc.
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
;; Bengt Martensson <bengt@mathematik.uni-Bremen.de>
;; Mike Newton <newton@gumby.cs.caltech.edu>
;; Aaron Larson <alarson@src.honeywell.com>
;; Dirk Herrmann <D.Herrmann@tu-bs.de>
-;; Maintainer: Roland Winkler <roland.winkler@physik.uni-erlangen.de>
+;; Maintainer: Roland Winkler <winkler@gnu.org>
;; Keywords: BibTeX, LaTeX, TeX
;; This file is part of GNU Emacs.
(const unify-case)
(const braces)
(const strings))))
+(put 'bibtex-entry-format 'safe-local-variable
+ (lambda (x)
+ (or (eq x t)
+ (let ((OK t))
+ (while (consp x)
+ (unless (memq (pop x)
+ '(opts-or-alts required-fields numerical-fields
+ page-dashes whitespace inherit-booktitle realign
+ last-comma delimiters unify-case braces strings))
+ (setq OK nil)))
+ (unless (null x) (setq OK nil))
+ OK))))
(defcustom bibtex-field-braces-alist nil
"Alist of field regexps that \\[bibtex-clean-entry] encloses by braces.
Each element has the form (FIELDS REGEXP), where FIELDS is a list
of BibTeX field names and REGEXP is a regexp.
-Whitespace in REGEXP will be replaced by \"[ \\t\\n]+\"."
+Space characters in REGEXP will be replaced by \"[ \\t\\n]+\"."
:group 'bibtex
:type '(repeat (list (repeat (string :tag "field name"))
(choice (regexp :tag "regexp")
Each element has the form (FIELDS REGEXP TO-STR), where FIELDS is a list
of BibTeX field names. In FIELDS search for REGEXP, which are replaced
by the BibTeX string constant TO-STR.
-Whitespace in REGEXP will be replaced by \"[ \\t\\n]+\"."
+Space characters in REGEXP will be replaced by \"[ \\t\\n]+\"."
:group 'bibtex
:type '(repeat (list (repeat (string :tag "field name"))
(regexp :tag "From regexp")
entries are ordered according to the classes they belong to. Each
class contains a list of entry types. An entry `catch-all' applies
to all entries not explicitly mentioned."
- :group 'BibTeX
+ :group 'bibtex
:type '(repeat (choice :tag "Class"
(const :tag "catch-all" (catch-all))
(repeat :tag "Entry type" string))))
(defcustom bibtex-autokey-titleword-ignore
'("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
- "[^[:upper:]].*" ".*[^[:upper:]0-9].*")
+ "[^[:upper:]].*" ".*[^[:upper:][:lower:]0-9].*")
"Determines words from the title that are not to be used in the key.
Each item of the list is a regexp. If a word of the title matches a
regexp from that list, it is not included in the title part of the key.
-See `bibtex-generate-autokey' for details."
+Case is significant. See `bibtex-generate-autokey' for details."
:group 'bibtex-autokey
:type '(repeat regexp))
:type 'string)
(defcustom bibtex-autokey-year-title-separator ":_"
- "String to be put between name part and year part of key.
+ "String to be put between year part and title part of key.
See `bibtex-generate-autokey' for details."
:group 'bibtex-autokey
:type 'string)
Case is always ignored. Always remove the field delimiters.
If `bibtex-expand-strings' is non-nil, BibTeX strings are expanded
for generating the URL.
+Set this variable before loading BibTeX mode.
-The following is a complex example, see http://link.aps.org/linkfaq.html.
+The following is a complex example, see URL `http://link.aps.org/'.
(((\"journal\" . \"\\\\=<\\(PR[ABCDEL]?\\|RMP\\)\\\\=>\")
\"http://link.aps.org/abstract/%s/v%s/p%s\"
Each rule should be of the form (REGEXP . SUBEXP), where SUBEXP
specifies which parenthesized expression in REGEXP is a cited key.
Case is significant.
-Used by `bibtex-search-crossref' and for font-locking."
+Used by `bibtex-search-crossref' and for font-locking.
+Set this variable before loading BibTeX mode."
:group 'bibtex
:type '(repeat (cons (regexp :tag "Regexp")
- (integer :tag "Number"))))
+ (integer :tag "Number")))
+ :version "23.1")
(defcustom bibtex-expand-strings nil
"If non-nil, expand strings when extracting the content of a BibTeX field."
(save-excursion
(goto-char (bibtex-start-of-text-in-field bounds))
(let ((epoint (bibtex-end-of-text-in-field bounds))
- content opoint)
- (while (< (setq opoint (point)) epoint)
+ content)
+ (while (< (point) epoint)
(if (looking-at bibtex-field-const)
(let ((mtch (match-string-no-properties 0)))
(push (or (if bibtex-expand-strings
see regexp `bibtex-entry-head'. If `bibtex-sort-ignore-string-entries'
is non-nil, FUN is not called for @String entries."
(let ((case-fold-search t)
+ (end-marker (make-marker))
found)
+ ;; Use marker to keep track of the buffer position of the end of
+ ;; a BibTeX entry as this position may change during reformatting.
+ (set-marker-insertion-type end-marker t)
(save-excursion
(goto-char (point-min))
(while (setq found (bibtex-skip-to-valid-entry))
+ (set-marker end-marker (cdr found))
(looking-at bibtex-any-entry-maybe-empty-head)
- (funcall fun (bibtex-key-in-head "") (car found) (cdr found))
- (goto-char (cdr found))))))
+ (funcall fun (bibtex-key-in-head "") (car found) end-marker)
+ (goto-char end-marker)))))
(defun bibtex-progress-message (&optional flag interval)
"Echo a message about progress of current buffer.
"Search for BibTeX field enclosing point.
For `bibtex-mode''s internal algorithms, a field begins at the comma
following the preceding field. Usually, this is not what the user expects.
-Thus if COMMA is non-nil, the \"current field\" includes the terminating comma.
+Thus if COMMA is non-nil, the \"current field\" includes the terminating comma
+as well as the entry delimiter if it appears on the same line.
Unless NOERR is non-nil, signal an error if no enclosing field is found.
On success return bounds, nil otherwise. Do not move point."
(save-excursion
(when comma
(end-of-line)
(skip-chars-backward " \t")
+ ;; Ignore entry delimiter and comma at end of line.
+ (if (memq (preceding-char) '(?} ?\))) (forward-char -1))
(if (= (preceding-char) ?,) (forward-char -1)))
(let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
(bibtex-skip-to-valid-entry)
(push-mark)
(insert (funcall fun 'bibtex-entry-kill-ring-yank-pointer
- bibtex-entry-kill-ring)))))
+ bibtex-entry-kill-ring))
+ (unless (functionp bibtex-reference-keys)
+ ;; update `bibtex-reference-keys'
+ (save-excursion
+ (goto-char (mark t))
+ (looking-at bibtex-any-entry-maybe-empty-head)
+ (let ((key (bibtex-key-in-head)))
+ (if key (push (cons key t) bibtex-reference-keys))))))))
(defun bibtex-format-entry ()
"Helper function for `bibtex-clean-entry'.
last-comma delimiters unify-case braces
strings)
bibtex-entry-format))
+ (left-delim-re (regexp-quote (bibtex-field-left-delimiter)))
bounds crossref-key req-field-list default-field-list field-list
alt-fields error-field-name)
(unwind-protect
;; Do we have a crossref key?
(goto-char (point-min))
- (if (setq bounds (bibtex-search-forward-field "crossref"))
+ (if (setq bounds (bibtex-search-forward-field
+ "\\(OPT\\)?crossref"))
(let ((text (bibtex-text-in-field-bounds bounds t)))
(unless (equal "" text)
(setq crossref-key text))))
(unless deleted
(push field-name field-list)
+ ;; Remove whitespace at beginning and end of field.
+ ;; We do not look at individual parts of the field
+ ;; as {foo } # bar # { baz} is a fine field.
+ (when (memq 'whitespace format)
+ (goto-char beg-text)
+ (if (looking-at "\\([{\"]\\)[ \t\n]+")
+ (replace-match "\\1"))
+ (goto-char end-text)
+ (if (looking-back "[ \t\n]+\\([}\"]\\)" beg-text t)
+ (replace-match "\\1")))
+
;; remove delimiters from purely numerical fields
(when (and (memq 'numerical-fields format)
(progn (goto-char beg-text)
;; update delimiters
(when (memq 'delimiters format)
(goto-char beg-text)
- (when (looking-at "[{\"]")
- (delete-char 1)
- (insert (bibtex-field-left-delimiter)))
- (goto-char (1- (marker-position end-text)))
- (when (looking-at "[}\"]")
- (delete-char 1)
- (insert (bibtex-field-right-delimiter))))
+ ;; simplified from `bibtex-parse-field-text', as we
+ ;; already checked that the field format is correct
+ (while (< (point) end-text)
+ (if (looking-at bibtex-field-const)
+ (goto-char (match-end 0))
+ (let ((boundaries (bibtex-parse-field-string)))
+ (if (looking-at left-delim-re)
+ (goto-char (cdr boundaries))
+ (delete-char 1)
+ (insert (bibtex-field-left-delimiter))
+ (goto-char (1- (cdr boundaries)))
+ (delete-char 1)
+ (insert (bibtex-field-right-delimiter)))))
+ (if (looking-at "[ \t\n]*#[ \t\n]*")
+ (goto-char (match-end 0)))))
;; update page dashes
(if (and (memq 'page-dashes format)
"\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)")))
(replace-match "\\1-\\2"))
- ;; remove whitespace at beginning and end of field
- (when (memq 'whitespace format)
- (goto-char beg-text)
- (if (looking-at "\\([{\"]\\)[ \t\n]+")
- (replace-match "\\1"))
- (goto-char end-text)
- (if (looking-back "[ \t\n]+\\([}\"]\\)" beg-text t)
- (replace-match "\\1")))
-
;; enclose field text by braces according to
;; `bibtex-field-braces-alist'.
(let (case-fold-search temp) ; Case-sensitive search
;; if match not at left subfield boundary...
(if (< (1+ (nth 1 bounds)) (match-beginning 0))
(insert (bibtex-field-right-delimiter) " # ")
- (delete-backward-char 1))))))))
+ (delete-char -1))))))))
;; use book title of crossref'd entry
(if (and (memq 'inherit-booktitle format)
(if (memq 'realign format)
(bibtex-fill-entry)))))
- ;; Unwindform: move point to location where error occured if possible
+ ;; Unwindform: move point to location where error occurred if possible
(if error-field-name
(let (bounds)
(when (save-excursion
(setq regexp-alist
(mapcar (lambda (e)
(list (car e)
- (replace-regexp-in-string "[ \t\n]+" "[ \t\n]+" (nth 1 e))
+ (replace-regexp-in-string " +" "[ \t\n]+" (nth 1 e))
(nth 2 e))) ; nil for 'braces'.
regexp-alist))
(let (opt-list)
;; gather words from titlestring into a list. Ignore
;; specific words and use only a specific amount of words.
(let ((counter 0)
+ (ignore-re (concat "\\`\\(?:"
+ (mapconcat 'identity
+ bibtex-autokey-titleword-ignore "\\|")
+ "\\)\\'"))
titlewords titlewords-extra word)
(while (and (or (not (numberp bibtex-autokey-titlewords))
(< counter (+ bibtex-autokey-titlewords
(setq word (match-string 0 titlestring)
titlestring (substring titlestring (match-end 0)))
;; Ignore words matched by one of the elements of
- ;; `bibtex-autokey-titleword-ignore'
- (unless (let ((lst bibtex-autokey-titleword-ignore))
- (while (and lst
- (not (string-match (concat "\\`\\(?:" (car lst)
- "\\)\\'") word)))
- (setq lst (cdr lst)))
- lst)
+ ;; `bibtex-autokey-titleword-ignore'. Case is significant.
+ (unless (let (case-fold-search)
+ (string-match ignore-re word))
(setq counter (1+ counter))
(if (or (not (numberp bibtex-autokey-titlewords))
(<= counter bibtex-autokey-titlewords))
(apply 'append
(mapcar (lambda (buf)
(with-current-buffer buf bibtex-reference-keys))
- (bibtex-initialize t)))
- bibtex-reference-keys))
+ ;; include current buffer only if it uses `bibtex-mode'
+ (bibtex-initialize (eq major-mode 'bibtex-mode))))
+ (if (eq major-mode 'bibtex-mode)
+ bibtex-reference-keys)))
(defun bibtex-read-key (prompt &optional key global)
"Read BibTeX key from minibuffer using PROMPT and default KEY.
(save-excursion
(save-match-data
(goto-char (point-min))
- (let ((strings (if (and add
- (listp bibtex-strings))
+ (let ((strings (if (and add (not (functionp bibtex-strings)))
bibtex-strings))
bounds key)
(if (listp add)
(defun bibtex-strings ()
"Return `bibtex-strings'. Initialize this variable if necessary."
- (if (listp bibtex-strings) bibtex-strings
- (bibtex-parse-strings (bibtex-string-files-init))))
+ (if (functionp bibtex-strings)
+ (bibtex-parse-strings (bibtex-string-files-init))
+ bibtex-strings))
(defun bibtex-string-files-init ()
"Return initialization for `bibtex-strings'.
(dolist (file file-list)
(if (file-readable-p file)
(push (find-file-noselect file) buffer-list)))
- ;; include current buffer iff we want it
+ ;; 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))
(cond ((and current (not (memq (current-buffer) buffer-list)))
(push (current-buffer) buffer-list))
((and (not current) (memq (current-buffer) buffer-list))
;; parse keys
(dolist (buffer buffer-list)
(with-current-buffer buffer
- (if (or force (nlistp bibtex-reference-keys))
- (bibtex-parse-keys))))
+ (if (or force (functionp bibtex-reference-keys))
+ (bibtex-parse-keys))
+ (unless (functionp bibtex-strings)
+ (bibtex-parse-strings (bibtex-string-files-init)))))
;; select BibTeX buffer
(if select
(if buffer-list
of a word, all strings are listed. Return completion."
;; Return value is used by cleanup functions.
;; Code inspired by `lisp-complete-symbol'.
- (let* ((case-fold-search t)
- (beg (save-excursion
+ (let ((beg (save-excursion
(re-search-backward "[ \t{\"]")
(forward-char)
(point)))
- (end (point))
- (pattern (buffer-substring-no-properties beg end))
- (completion (try-completion pattern completions)))
- (cond ((not completion)
- (error "Can't find completion for `%s'" pattern))
- ((eq completion t)
- pattern)
- ((not (string= pattern completion))
- (delete-region beg end)
- (insert completion)
- ;; Don't leave around a completions buffer that's out of date.
- (let ((win (get-buffer-window "*Completions*" 0)))
- (if win (with-selected-window win (bury-buffer))))
- completion)
- (t
- (let ((minibuf-is-in-use
- (eq (minibuffer-window) (selected-window))))
- (unless minibuf-is-in-use (message "Making completion list..."))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (sort (all-completions pattern completions) 'string<) pattern))
- (unless minibuf-is-in-use
- (message "Making completion list...done")))
- nil))))
+ (end (point)))
+ (when (completion-in-region beg end completions)
+ (buffer-substring beg (point)))))
(defun bibtex-complete-string-cleanup (str compl)
"Cleanup after inserting string STR.
General information on working with BibTeX mode:
-Use commands such as \\[bibtex-Book] to get a template for a specific entry.
+Use commands such as \\<bibtex-mode-map>\\[bibtex-Book] to get a template for a specific entry.
Then fill in all desired fields using \\[bibtex-next-field] to jump from field
to field. After having filled in all desired fields in the entry, clean the
new entry with the command \\[bibtex-clean-entry].
;; brace-delimited ones
)
nil
- (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
(font-lock-extra-managed-props . (category))
(font-lock-mark-block-function
. (lambda ()
(set-mark (bibtex-end-of-entry))
(bibtex-beginning-of-entry)))))
+ (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)
((looking-at bibtex-any-valid-entry-type)
;; Parsing of entry failed
(error "Syntactically incorrect BibTeX entry starts here"))
- (t (if (interactive-p) (message "Not on a known BibTeX entry."))
+ (t (if (called-interactively-p 'interactive)
+ (message "Not on a known BibTeX entry."))
(goto-char pnt)))
(point)))
(bibtex-beginning-of-first-entry) ; Needed by `sort-subr'
(bibtex-init-sort-entry-class-alist) ; Needed by `bibtex-lessp'.
(if (and (eq bibtex-maintain-sorted-entries 'crossref)
- (nlistp bibtex-reference-keys))
+ (functionp bibtex-reference-keys))
(bibtex-parse-keys)) ; Needed by `bibtex-lessp'.
(sort-subr nil
'bibtex-skip-to-valid-entry ; NEXTREC function
(end (cdr (bibtex-valid-entry t)))
(_ (unless end (error "Not inside valid entry")))
(beg (match-end 0)) ; set by `bibtex-valid-entry'
- (bounds (bibtex-search-forward-field "crossref" end))
+ (bounds (bibtex-search-forward-field "\\(OPT\\)?crossref" end))
case-fold-search best temp crossref-key)
(if bounds
(setq crossref-key (bibtex-text-in-field-bounds bounds t)
(while (and (not found)
(setq buffer (pop buffer-list)))
(with-current-buffer buffer
- (if (and (listp bibtex-reference-keys)
- (cdr (assoc-string key bibtex-reference-keys)))
+ (if (cdr (assoc-string key bibtex-reference-keys))
;; `bibtex-search-entry' moves point if key found
(setq found (bibtex-search-entry key)))))
(cond ((and found display)
Return t if preparation was successful or nil if entry KEY already exists."
(bibtex-init-sort-entry-class-alist) ; Needed by `bibtex-lessp'.
(if (and (eq bibtex-maintain-sorted-entries 'crossref)
- (nlistp bibtex-reference-keys))
+ (functionp bibtex-reference-keys))
(bibtex-parse-keys)) ; Needed by `bibtex-lessp'.
(let ((key (nth 0 index))
key-exist)
(with-current-buffer (get-buffer-create err-buf)
(setq default-directory dir)
(unless (eq major-mode 'compilation-mode) (compilation-mode))
- (toggle-read-only -1)
- (delete-region (point-min) (point-max))
- (insert "BibTeX mode command `bibtex-validate'\n"
- (if syntax-error
- "Maybe undetected errors due to syntax errors. Correct and validate again.\n"
- "\n"))
- (dolist (err error-list)
- (insert (format "%s:%d: %s\n" file (car err) (cdr err))))
- (set-buffer-modified-p nil)
- (toggle-read-only 1)
- (goto-line 3)) ; first error message
+ (let ((inhibit-read-only t))
+ (delete-region (point-min) (point-max))
+ (insert "BibTeX mode command `bibtex-validate'\n"
+ (if syntax-error
+ "Maybe undetected errors due to syntax errors. \
+Correct and validate again.\n"
+ "\n"))
+ (dolist (err error-list)
+ (insert (format "%s:%d: %s\n" file (car err) (cdr err))))
+ (set-buffer-modified-p nil))
+ (goto-char (point-min))
+ (forward-line 2)) ; first error message
(display-buffer err-buf)
nil) ; return `nil' (i.e., buffer is invalid)
(message "%s is syntactically correct"
buffer-key-list current-buf current-keys error-list)
;; Check for duplicate keys within BibTeX buffer
(dolist (buffer buffer-list)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(let (entry-type key key-list)
(goto-char (point-min))
(while (re-search-forward bibtex-entry-head nil t)
(let ((err-buf "*BibTeX validation errors*"))
(with-current-buffer (get-buffer-create err-buf)
(unless (eq major-mode 'compilation-mode) (compilation-mode))
- (toggle-read-only -1)
- (delete-region (point-min) (point-max))
- (insert "BibTeX mode command `bibtex-validate-globally'\n\n")
- (dolist (err (sort error-list 'string-lessp)) (insert err))
- (set-buffer-modified-p nil)
- (toggle-read-only 1)
- (goto-line 3)) ; first error message
+ (let ((inhibit-read-only t))
+ (delete-region (point-min) (point-max))
+ (insert "BibTeX mode command `bibtex-validate-globally'\n\n")
+ (dolist (err (sort error-list 'string-lessp)) (insert err))
+ (set-buffer-modified-p nil))
+ (goto-char (point-min))
+ (forward-line 2)) ; first error message
(display-buffer err-buf)
nil) ; return `nil' (i.e., buffer is invalid)
(message "No duplicate keys.")
(end (bibtex-end-of-field bounds))
(beg (bibtex-start-of-field bounds)))
(goto-char end)
- (skip-chars-forward ",")
+ ;; Preserve white space at end of BibTeX entry
+ (if (looking-at "[ \t\n]*[)}]")
+ (progn (skip-chars-backward " \t\n")
+ (setq end (point)))
+ (skip-chars-forward ","))
(push (list (bibtex-name-in-field bounds) nil
(bibtex-text-in-field-bounds bounds))
bibtex-field-kill-ring)
(setq bibtex-last-kill-command 'field))
(defun bibtex-copy-field-as-kill (&optional comma)
- "Copy the BibTeX field at point to the kill ring.
+ "Copy the BibTeX field at point to `bibtex-field-kill-ring'.
Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for
interactive calls."
(interactive (list t))
(save-excursion
(let* ((case-fold-search t)
(beg (bibtex-beginning-of-entry))
+ (key (progn (looking-at bibtex-any-entry-maybe-empty-head)
+ (bibtex-key-in-head)))
(end (progn (bibtex-end-of-entry)
(if (re-search-forward
bibtex-any-entry-maybe-empty-head nil 'move)
nil))
(setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring)
(unless copy-only
- (delete-region beg end))))
+ (delete-region beg end)
+ ;; remove key from `bibtex-reference-keys'.
+ (unless (functionp bibtex-reference-keys)
+ (setq bibtex-reference-keys
+ (delete (cons key t) bibtex-reference-keys))))))
(setq bibtex-last-kill-command 'entry))
(defun bibtex-copy-entry-as-kill ()
(unless (eq last-command 'bibtex-yank)
(error "Previous command was not a BibTeX yank"))
(setq this-command 'bibtex-yank)
- (let ((inhibit-read-only t))
+ (let ((inhibit-read-only t) key)
+ ;; point is at end of yanked entry
+ (unless (functionp bibtex-reference-keys)
+ ;; remove key of yanked entry from `bibtex-reference-keys'
+ (save-excursion
+ (goto-char (mark t))
+ (if (and (looking-at bibtex-any-entry-maybe-empty-head)
+ (setq key (bibtex-key-in-head)))
+ (setq bibtex-reference-keys
+ (delete (cons key t) bibtex-reference-keys)))))
(delete-region (point) (mark t))
(bibtex-insert-kill n t)))
(defun bibtex-clean-entry (&optional new-key called-by-reformat)
"Finish editing the current BibTeX entry and clean it up.
-Check that no required fields are empty and formats entry dependent
+Check that no required fields are empty and format entry dependent
on the value of `bibtex-entry-format'.
If the reference key of the entry is empty or a prefix argument is given,
calculate a new reference key. (Note: this works only if fields in entry
(if (cdr (assoc-string key bibtex-reference-keys))
(error "Duplicate key in %s" (buffer-file-name)))))
- ;; Only update the list of keys if it has been built already.
+ ;; Only update `bibtex-strings' and `bibtex-reference-keys'
+ ;; if they have been built already.
(cond ((eq entry-type 'string)
- (if (and (listp bibtex-strings)
- (not (assoc key bibtex-strings)))
- (push (cons key (bibtex-text-in-string
- (bibtex-parse-string) t))
- bibtex-strings)))
+ ;; We have a @String entry.
+ (unless (or (functionp bibtex-strings)
+ (assoc key bibtex-strings))
+ (push (cons key (bibtex-text-in-string
+ (bibtex-parse-string) t))
+ bibtex-strings)))
;; We have a normal entry.
- ((listp bibtex-reference-keys)
- (cond ((not (assoc key bibtex-reference-keys))
- (push (cons key t) bibtex-reference-keys))
- ((not (cdr (assoc key bibtex-reference-keys)))
- ;; Turn a crossref key into a header key
- (setq bibtex-reference-keys
- (cons (cons key t)
- (delete (list key) bibtex-reference-keys)))))
- ;; Handle crossref key.
+ ((not (functionp bibtex-reference-keys))
+ (let ((found (assoc key bibtex-reference-keys)))
+ (cond ((not found)
+ (push (cons key t) bibtex-reference-keys))
+ ((not (cdr found))
+ ;; Turn a crossref key into a header key
+ (setq bibtex-reference-keys
+ (cons (cons key t)
+ (delete (list key) bibtex-reference-keys))))))
+ ;; If entry has a crossref key, it goes into the list
+ ;; `bibtex-reference-keys', too.
(if (and (nth 1 index)
(not (assoc (nth 1 index) bibtex-reference-keys)))
(push (list (nth 1 index)) bibtex-reference-keys)))))
last-comma page-dashes unify-case inherit-booktitle
whitespace braces strings))
(t
- (remove 'required-fields (push 'realign bibtex-entry-format)))))
+ (cons 'realign (remove 'required-fields bibtex-entry-format)))))
(reformat-reference-keys
(if read-options
(if use-previous-options
;; is requested.
(let (completion-ignore-case)
(setq choose-completion-string-functions
- (lambda (choice buffer mini-p base-size)
+ (lambda (choice buffer base-position &rest ignored)
(setq choose-completion-string-functions nil)
- (choose-completion-string choice buffer base-size)
+ (choose-completion-string choice buffer base-position)
(bibtex-complete-crossref-cleanup choice)
t)) ; needed by choose-completion-string-functions
(bibtex-complete-crossref-cleanup
;; string completion
(let ((completion-ignore-case t))
(setq choose-completion-string-functions
- `(lambda (choice buffer mini-p base-size)
+ `(lambda (choice buffer base-position &rest ignored)
(setq choose-completion-string-functions nil)
- (choose-completion-string choice buffer base-size)
+ (choose-completion-string choice buffer base-position)
(bibtex-complete-string-cleanup choice ',compl)
t)) ; needed by `choose-completion-string-functions'
(bibtex-complete-string-cleanup (bibtex-complete-internal compl)
(error "Match failed: %s" text)))
(if fmt (apply 'format fmt (nreverse obj))
(apply 'concat (nreverse obj)))))
- (if (interactive-p) (message "%s" url))
+ (if (called-interactively-p 'interactive) (message "%s" url))
(unless no-browse (browse-url url)))
- (if (and (not url) (interactive-p)) (message "No URL known."))
+ (if (and (not url) (called-interactively-p 'interactive))
+ (message "No URL known."))
url)))
\f
(provide 'bibtex)
-;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04
;;; bibtex.el ends here