-;;; reftex-cite.el - Creating citations with RefTeX
+;;; reftex-cite.el --- creating citations with RefTeX
;; Copyright (c) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
-;; Author: Carsten Dominik <dominik@strw.LeidenUniv.nl>
-;; Version: 4.16
-;;
+;; Author: Carsten Dominik <dominik@science.uva.nl>
+;; Version: 4.18
;; This file is part of GNU Emacs.
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
+;;; Commentary:
+
+;;; Code:
+
(eval-when-compile (require 'cl))
(provide 'reftex-cite)
(require 'reftex)
;; Find bibtex files
+
+(defmacro reftex-with-special-syntax-for-bib (&rest body)
+ `(let ((saved-syntax (syntax-table)))
+ (unwind-protect
+ (progn
+ (set-syntax-table reftex-syntax-table-for-bib)
+ ,@body)
+ (set-syntax-table saved-syntax))))
+
(defun reftex-default-bibliography ()
;; Return the expanded value of `reftex-default-bibliography'.
;; The expanded value is cached.
reftex-default-bibliography))
(get 'reftex-default-bibliography :reftex-expanded))
+(defun reftex-bib-or-thebib ()
+ ;; Tests if BibTeX or \begin{tehbibliography} should be used for the
+ ;; citation
+ ;; Find the bof of the current file
+ (let* ((docstruct (symbol-value reftex-docstruct-symbol))
+ (rest (or (member (list 'bof (buffer-file-name)) docstruct)
+ docstruct))
+ (bib (assq 'bib rest))
+ (thebib (assq 'thebib rest))
+ (bibmem (memq bib rest))
+ (thebibmem (memq thebib rest)))
+ (when (not (or thebib bib))
+ (setq bib (assq 'bib docstruct)
+ thebib (assq 'thebib docstruct)
+ bibmem (memq bib docstruct)
+ thebibmem (memq thebib docstruct)))
+ (if (> (length bibmem) (length thebibmem))
+ (if bib 'bib nil)
+ (if thebib 'thebib nil))))
+
(defun reftex-get-bibfile-list ()
;; Return list of bibfiles for current document.
;; When using the chapterbib or bibunits package you should either
(let* (re-list first-re rest-re
(buffer-list (if (listp buffers) buffers (list buffers)))
found-list entry buffer1 buffer alist
- key-point start-point end-point)
+ key-point start-point end-point default)
;; Read a regexp, completing on known citation keys.
+ (setq default (regexp-quote (reftex-get-bibkey-default)))
(setq re-list
(split-string
(completing-read
- "RegExp [ && RegExp...]: "
+ (concat
+ "Regex { && Regex...}: "
+ "[" default "]: ")
(if reftex-mode
(if (fboundp 'LaTeX-bibitem-list)
(LaTeX-bibitem-list)
nil nil nil 'reftex-cite-regexp-hist)
"[ \t]*&&[ \t]*"))
+ (if (or (null re-list ) (equal re-list '("")))
+ (setq re-list (list default)))
+
(setq first-re (car re-list) ; We'll use the first re to find things,
rest-re (cdr re-list)) ; the others to narrow down.
(if (string-match "\\`[ \t]*\\'" (or first-re ""))
(message "Scanning bibliography database %s" buffer1))
(set-buffer buffer1)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward first-re nil t)
- (catch 'search-again
- (setq key-point (point))
- (unless (re-search-backward
- "\\(\\`\\|[\n\r]\\)[ \t]*@\\([a-zA-Z]+\\)[ \t\n\r]*[{(]" nil t)
- (throw 'search-again nil))
- (setq start-point (point))
- (goto-char (match-end 0))
- (condition-case nil
- (up-list 1)
- (error (goto-char key-point)
+ (reftex-with-special-syntax-for-bib
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward first-re nil t)
+ (catch 'search-again
+ (setq key-point (point))
+ (unless (re-search-backward
+ "\\(\\`\\|[\n\r]\\)[ \t]*@\\([a-zA-Z]+\\)[ \t\n\r]*[{(]" nil t)
+ (throw 'search-again nil))
+ (setq start-point (point))
+ (goto-char (match-end 0))
+ (condition-case nil
+ (up-list 1)
+ (error (goto-char key-point)
(throw 'search-again nil)))
- (setq end-point (point))
-
- ;; Ignore @string, @comment and @c entries or things
- ;; outside entries
- (when (or (string= (downcase (match-string 2)) "string")
- (string= (downcase (match-string 2)) "comment")
- (string= (downcase (match-string 2)) "c")
- (< (point) key-point)) ; this means match not in {}
- (goto-char key-point)
- (throw 'search-again nil))
-
- ;; Well, we have got a match
- (setq entry (concat
- (buffer-substring start-point (point)) "\n"))
-
- ;; Check if other regexp match as well
- (setq re-list rest-re)
- (while re-list
- (unless (string-match (car re-list) entry)
- ;; nope - move on
- (throw 'search-again nil))
- (pop re-list))
-
- (setq alist (reftex-parse-bibtex-entry
- nil start-point end-point))
- (push (cons "&entry" entry) alist)
-
- ;; check for crossref entries
- (if (assoc "crossref" alist)
- (setq alist
- (append
- alist (reftex-get-crossref-alist alist))))
-
- ;; format the entry
- (push (cons "&formatted" (reftex-format-bib-entry alist))
- alist)
-
- ;; make key the first element
- (push (reftex-get-bib-field "&key" alist) alist)
-
- ;; add it to the list
- (push alist found-list))))
- (reftex-kill-temporary-buffers))))
+ (setq end-point (point))
+
+ ;; Ignore @string, @comment and @c entries or things
+ ;; outside entries
+ (when (or (string= (downcase (match-string 2)) "string")
+ (string= (downcase (match-string 2)) "comment")
+ (string= (downcase (match-string 2)) "c")
+ (< (point) key-point)) ; this means match not in {}
+ (goto-char key-point)
+ (throw 'search-again nil))
+
+ ;; Well, we have got a match
+ (setq entry (concat
+ (buffer-substring start-point (point)) "\n"))
+
+ ;; Check if other regexp match as well
+ (setq re-list rest-re)
+ (while re-list
+ (unless (string-match (car re-list) entry)
+ ;; nope - move on
+ (throw 'search-again nil))
+ (pop re-list))
+
+ (setq alist (reftex-parse-bibtex-entry
+ nil start-point end-point))
+ (push (cons "&entry" entry) alist)
+
+ ;; check for crossref entries
+ (if (assoc "crossref" alist)
+ (setq alist
+ (append
+ alist (reftex-get-crossref-alist alist))))
+
+ ;; format the entry
+ (push (cons "&formatted" (reftex-format-bib-entry alist))
+ alist)
+
+ ;; make key the first element
+ (push (reftex-get-bib-field "&key" alist) alist)
+
+ ;; add it to the list
+ (push alist found-list)))))
+ (reftex-kill-temporary-buffers))))
(setq found-list (nreverse found-list))
;; Sorting
(reftex-parse-bibtex-entry nil start (point)))
nil)))))
-;; Parse the thebibliography environment
+;; Parse the bibliography environment
(defun reftex-extract-bib-entries-from-thebibliography (files)
;; Extract bib-entries from the \begin{thebibliography} environment.
;; Parsing is not as good as for the BibTeX database stuff.
;; The environment should be located in file FILE.
- (let* (start end buf entries re re-list file)
+ (let* (start end buf entries re re-list file default)
(unless files
(error "Need file name to find thebibliography environment"))
(while (setq file (pop files))
(unless entries
(error "No bibitems found"))
- (setq re-list (split-string
- (read-string "RegExp [ && RegExp...]: "
- nil 'reftex-cite-regexp-hist)
- "[ \t]*&&[ \t]*"))
+ ;; Read a regexp, completing on known citation keys.
+ (setq default (regexp-quote (reftex-get-bibkey-default)))
+ (setq re-list
+ (split-string
+ (completing-read
+ (concat
+ "Regex { && Regex...}: "
+ "[" default "]: ")
+ (if reftex-mode
+ (if (fboundp 'LaTeX-bibitem-list)
+ (LaTeX-bibitem-list)
+ (cdr (assoc 'bibview-cache
+ (symbol-value reftex-docstruct-symbol))))
+ nil)
+ nil nil nil 'reftex-cite-regexp-hist)
+ "[ \t]*&&[ \t]*"))
+
+ (if (or (null re-list ) (equal re-list '("")))
+ (setq re-list (list default)))
+
(if (string-match "\\`[ \t]*\\'" (car re-list))
(error "Empty regular expression"))
entries))
+(defun reftex-get-bibkey-default ()
+ ;; Return the word before the cursor. If the cursor is in a
+ ;; citation macro, return the word before the macro.
+ (let* ((macro (reftex-what-macro 1)))
+ (save-excursion
+ (if (and macro (string-match "cite" (car macro)))
+ (goto-char (cdr macro)))
+ (skip-chars-backward "^a-zA-Z0-9")
+ (reftex-this-word))))
+
;; Parse and format individual entries
(defun reftex-get-bib-names (field entry)
(progn
(set-buffer (get-buffer-create " *RefTeX-scratch*"))
(fundamental-mode)
+ (set-syntax-table reftex-syntax-table-for-bib)
(erase-buffer)
(insert entry))
(widen)
"Make a citation using BibTeX database files.
After prompting for a regular expression, scans the buffers with
bibtex entries (taken from the \\bibliography command) and offers the
-matching entries for selection. The selected entry is formated according
+matching entries for selection. The selected entry is formatted according
to `reftex-cite-format' and inserted into the buffer.
If NO-INSERT is non-nil, nothing is inserted, only the selected key returned.
(defun reftex-offer-bib-menu ()
;; Offer bib menu and return list of selected items
- (let (found-list rtn key data selected-entries)
+ (let ((bibtype (reftex-bib-or-thebib))
+ found-list rtn key data selected-entries)
(while
(not
(catch 'done
;; Scan bibtex files
(setq found-list
(cond
- ((assq 'bib (symbol-value reftex-docstruct-symbol))
+ ((eq bibtype 'bib)
+; ((assq 'bib (symbol-value reftex-docstruct-symbol))
;; using BibTeX database files.
(reftex-extract-bib-entries (reftex-get-bibfile-list)))
- ((assq 'thebib (symbol-value reftex-docstruct-symbol))
+ ((eq bibtype 'thebib)
+; ((assq 'thebib (symbol-value reftex-docstruct-symbol))
;; using thebibliography environment.
(reftex-extract-bib-entries-from-thebibliography
(reftex-uniquify
(defun reftex-format-names (namelist n)
(let (last (len (length namelist)))
+ (if (= n 0) (setq n len))
(cond
((< len 1) "")
((= 1 len) (car namelist))
;; recommended for follow mode. It works OK for individual lookups.
(let ((win (selected-window))
(key (reftex-get-bib-field "&key" data))
- bibfile-list item)
+ bibfile-list item bibtype)
(catch 'exit
(save-excursion
(set-buffer reftex-call-back-to-this-buffer)
+ (setq bibtype (reftex-bib-or-thebib))
(cond
- ((assq 'bib (symbol-value reftex-docstruct-symbol))
+ ((eq bibtype 'bib)
+; ((assq 'bib (symbol-value reftex-docstruct-symbol))
(setq bibfile-list (reftex-get-bibfile-list)))
- ((assq 'thebib (symbol-value reftex-docstruct-symbol))
+ ((eq bibtype 'thebib)
+; ((assq 'thebib (symbol-value reftex-docstruct-symbol))
(setq bibfile-list
(reftex-uniquify
(mapcar 'cdr