auctex-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[AUCTeX-devel] RefTeX: "Create BibTeX file" with cross references


From: Wolfgang Mayer
Subject: [AUCTeX-devel] RefTeX: "Create BibTeX file" with cross references
Date: Fri, 02 May 2008 14:19:14 +0930
User-agent: Thunderbird 2.0.0.12 (X11/20080213)

The attached patch makes reftex-create-bibtex-file include entries that are
cross-referenced from cited entries. Also, the required @String definitions are
now included in the resulting bib-file.

Custom variables reftex-create-bibtex-header and reftex-create-bibtex-footer allow to include custom material at the top/bottom of the generated file (useful to set file-local variables, etc.)


Regards,

- Wolfgang

diff -up reftex-4.33/lisp/reftex-cite.el.orig reftex-4.33/lisp/reftex-cite.el
--- reftex-4.33/lisp/reftex-cite.el.orig        2007-08-24 07:06:03.000000000 
+0930
+++ reftex-4.33/lisp/reftex-cite.el     2008-05-02 09:25:40.000000000 +0930
@@ -450,7 +450,8 @@
       (setq names (replace-match " " nil t names)))
     (split-string names "\n")))
 
-(defun reftex-parse-bibtex-entry (entry &optional from to)
+(defun reftex-parse-bibtex-entry (entry &optional from to raw)
+  ; if RAW is non-nil, keep double quotes/curly braces delimiting fields
   (let (alist key start field)
     (save-excursion
       (save-restriction
@@ -462,7 +463,7 @@
               (erase-buffer)
               (insert entry))
           (widen)
-          (narrow-to-region from to))
+          (if (and from to) (narrow-to-region from to)))
         (goto-char (point-min))
 
         (if (re-search-forward "@\\(\\(?:\\w\\|\\s_\\)+\\)[ \t\n\r]*\
@@ -476,28 +477,42 @@
           (setq key (downcase (reftex-match-string 1)))
           (cond
            ((= (following-char) ?{)
-            (forward-char 1)
-            (setq start (point))
-            (condition-case nil
-                (up-list 1)
-              (error nil)))
+            (cond 
+             (raw 
+              (setq start (point)) 
+              (forward-char 1))
+             (t 
+              (forward-char 1)
+              (setq start (point))
+              (condition-case nil
+                  (up-list 1)
+                (error nil)))))
            ((= (following-char) ?\")
-            (forward-char 1)
-            (setq start (point))
+            (cond
+             (raw
+              (setq start (point))
+              (forward-char 1))
+             (t
+              (forward-char 1)
+              (setq start (point))))
             (while (and (search-forward "\"" nil t)
                         (= ?\\ (char-after (- (point) 2))))))
            (t
             (setq start (point))
             (re-search-forward "[ \t]*[\n\r,}]" nil 1)))
-          (setq field (buffer-substring-no-properties start (1- (point))))
+          ;; extract field value, ignore trailing comma if in RAW mode
+          (let ((stop (if (and raw (not (= (char-after (1- (point))) ?,)))
+                        (point)
+                        (1- (point))) ))
+            (setq field (buffer-substring-no-properties start stop)))
           ;; remove extra whitespace
           (while (string-match "[\n\t\r]\\|[ \t][ \t]+" field)
             (setq field (replace-match " " nil t field)))
           ;; remove leading garbage
-          (if (string-match "^[ \t{]+" field)
+          (if (string-match (if raw "^[ \t]+" "^[ \t{]+") field)
               (setq field (replace-match "" nil t field)))
           ;; remove trailing garbage
-          (if (string-match "[ \t}]+$" field)
+          (if (string-match (if raw "[ \t]+$" "[ \t}]+$") field)
               (setq field (replace-match "" nil t field)))
           (push (cons key field) alist))))
     alist))
@@ -1135,18 +1150,36 @@ While entering the regexp, completion on
     (reftex-kill-temporary-buffers)
     keys))
 
+(defun reftex-stringrefp (string)
+  "Return non-nil if STRING is not enclosed in double quotes 
+   or curly braces and is not a number."
+  (not 
+   (or
+    (string-match "^[\"{]" string)
+    (string-match "^[0-9]+$" string))))
+
+(defun reftex-get-string-refs (alist) 
+  "Return a list of BibTeX @string references that appear as values in alist."
+  (remove-if-not 'reftex-stringrefp 
+                 ; get list of values, discard keys
+                 (mapcar 'cdr 
+                         ; remove &key and &type entries
+                         (remove-if (lambda (pair) (string-match "^&" (car 
pair)))
+                                    alist))))
+
 (defun reftex-create-bibtex-file (bibfile)
   "Create a new BibTeX database file with all entries referenced in document.
 The command prompts for a filename and writes the collected entries to
 that file.  Only entries referenced in the current document with
 any \\cite-like macros are used.
-The sequence in the new file is the same as it was in the old database."
+The sequence in the new file is the same as it was in the old database.
+Entries referenced from other entries must appear after all referencing 
entries."
   (interactive "FNew BibTeX file: ")
   (let ((keys (reftex-all-used-citation-keys))
         (files (reftex-get-bibfile-list))
-        file key entries beg end entry)
+        file key entries beg end entry string-keys string-entries)
     (save-excursion
-      (while (setq file (pop files))
+      (dolist (file files)
         (set-buffer (reftex-get-file-buffer-force file 'mark))
         (reftex-with-special-syntax-for-bib
          (save-excursion
@@ -1167,14 +1200,55 @@ The sequence in the new file is the same
                (when (member key keys)
                  (setq entry (buffer-substring beg end)
                        entries (cons entry entries)
-                       keys (delete key keys)))))))))
+                       keys (delete key keys))
+
+                 ;; check for crossref entries
+                 (let* ((attr-list (reftex-parse-bibtex-entry nil beg end))
+                        (xref-key (cdr (assoc "crossref" attr-list))))
+                   (if xref-key (pushnew xref-key keys)))
+                 ;; check for string references
+                 (let* ((raw-fields (reftex-parse-bibtex-entry nil beg end t))
+                        (string-fields (reftex-get-string-refs raw-fields)))
+                   (dolist (skey string-fields)
+                     (unless (member skey string-keys)
+                       (push skey string-keys))))
+                 )))))))
+    ;;; second pass: grab @string references
+    (if string-keys
+        (save-excursion
+          (dolist (file files)
+            (set-buffer (reftex-get-file-buffer-force file 'mark))
+            (reftex-with-special-syntax-for-bib
+             (save-excursion
+               (save-restriction
+                 (widen)
+                 (goto-char (point-min))
+                 (while (re-search-forward
+                         "^[ address@hidden \t]*{[ \t]*\\([^ \t\r\n]+\\)"
+                         nil t)
+                   (setq key (match-string 1)
+                         beg (match-beginning 0)
+                         end (progn
+                               (goto-char (match-beginning 1))
+                               (condition-case nil
+                                   (up-list 1)
+                                 (error (goto-char (match-end 0))))
+                               (point)))
+                   (when (member key string-keys)
+                     (setq entry (buffer-substring beg end)
+                           string-entries (cons entry string-entries)
+                           string-keys (delete key string-keys))))))))))
     (find-file-other-window bibfile)
     (if (> (buffer-size) 0)
         (unless (yes-or-no-p
                  (format "Overwrite non-empty file %s? " bibfile))
           (error "Abort")))
     (erase-buffer)
+    (if reftex-create-bibtex-header (insert reftex-create-bibtex-header 
"\n\n"))
+    (insert (mapconcat 'identity (reverse string-entries) "\n\n"))
+    (if string-entries (insert "\n\n\n"))
     (insert (mapconcat 'identity (reverse entries) "\n\n"))
+    (if reftex-create-bibtex-footer (insert "\n\n" 
reftex-create-bibtex-footer))
     (goto-char (point-min))
     (save-buffer)
     (message "%d entries extracted and copied to new database"
diff -up reftex-4.33/lisp/reftex-vars.el.orig reftex-4.33/lisp/reftex-vars.el
--- reftex-4.33/lisp/reftex-vars.el.orig        2007-08-24 07:06:02.000000000 
+0930
+++ reftex-4.33/lisp/reftex-vars.el     2008-05-02 09:19:45.000000000 +0930
@@ -1194,6 +1194,16 @@ should return the string to insert into 
   :group 'reftex-citation-support
   :type 'string)
 
+(defcustom reftex-create-bibtex-header nil
+  "Header to insert in BibTeX files generated by RefTeX."
+  :group 'reftex-citation-support
+  :type 'string)
+
+(defcustom reftex-create-bibtex-footer nil
+  "Footer to insert in BibTeX files generated by RefTeX."
+  :group 'reftex-citation-support
+  :type 'string)
+
 ;; Index Support Configuration
 
 (defgroup reftex-index-support nil

reply via email to

[Prev in Thread] Current Thread [Next in Thread]