]> code.delx.au - gnu-emacs/blobdiff - lisp/textmodes/reftex-cite.el
Add new maintainer (deego).
[gnu-emacs] / lisp / textmodes / reftex-cite.el
index 0eb70a5005287388e65f001448faeb29aa671719..d4d5b508eefbd421b2f6a863ee1d9727837e6759 100644 (file)
@@ -1,9 +1,8 @@
-;;; 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.
@@ -690,17 +756,20 @@ While entering the regexp, completion on knows citation keys is possible.
 (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
@@ -831,6 +900,7 @@ While entering the regexp, completion on knows citation keys is possible.
 
 (defun reftex-format-names (namelist n)
   (let (last (len (length namelist)))
+    (if (= n 0) (setq n len))
     (cond
      ((< len 1) "")
      ((= 1 len) (car namelist))
@@ -940,15 +1010,18 @@ While entering the regexp, completion on knows citation keys is possible.
   ;; 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