X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/ae940284fa77a6928f5162b7de859e67bdc7506c..e6aff855cef0ef5e20336bd4c08085ba8308fdbc:/lisp/textmodes/reftex-cite.el diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el index 8f45551c3a..079101b56e 100644 --- a/lisp/textmodes/reftex-cite.el +++ b/lisp/textmodes/reftex-cite.el @@ -1,11 +1,9 @@ ;;; reftex-cite.el --- creating citations with RefTeX -;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -;; 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +;; Copyright (C) 1997-2013 Free Software Foundation, Inc. ;; Author: Carsten Dominik ;; Maintainer: auctex-devel@gnu.org -;; Version: 4.31 ;; This file is part of GNU Emacs. @@ -69,14 +67,14 @@ (unless (eq (get 'reftex-default-bibliography :reftex-raw) reftex-default-bibliography) (put 'reftex-default-bibliography :reftex-expanded - (reftex-locate-bibliography-files + (reftex-locate-bibliography-files default-directory reftex-default-bibliography)) (put 'reftex-default-bibliography :reftex-raw 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 + ;; Tests if BibTeX or \begin{thebibliography} should be used for the ;; citation ;; Find the bof of the current file (let* ((docstruct (symbol-value reftex-docstruct-symbol)) @@ -128,10 +126,11 @@ ;; If RETURN is non-nil, just return the entry and restore point. (let* ((re - (if item - (concat "\\\\bibitem\\(\\[[^]]*\\]\\)?{" (regexp-quote key) "}") - (concat "@[a-zA-Z]+[ \t\n\r]*[{(][ \t\n\r]*" (regexp-quote key) - "[, \t\r\n}]"))) + (if item + (concat "\\\\bibitem[ \t]*\\(\\[[^]]*\\]\\)?[ \t]*{" + (regexp-quote key) "}") + (concat "@\\(?:\\w\\|\\s_\\)+[ \t\n\r]*[{(][ \t\n\r]*" + (regexp-quote key) "[, \t\r\n}]"))) (buffer-conf (current-buffer)) file buf pos oldpos) @@ -152,7 +151,7 @@ (when return ;; Just return the relevant entry (if item (goto-char (match-end 0))) - (setq return (buffer-substring + (setq return (buffer-substring (point) (reftex-end-of-bib-entry item))) (goto-char oldpos) ;; restore point. (set-buffer buffer-conf) @@ -169,9 +168,9 @@ (error "No BibTeX entry with citation key %s" key))))) (defun reftex-end-of-bib-entry (item) - (save-excursion + (save-excursion (condition-case nil - (if item + (if item (progn (end-of-line) (re-search-forward "\\\\bibitem\\|\\end{thebibliography}") @@ -192,16 +191,16 @@ ;; Read a regexp, completing on known citation keys. (setq default (regexp-quote (reftex-get-bibkey-default))) - (setq re-list - (split-string - (completing-read + (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 + (cdr (assoc 'bibview-cache (symbol-value reftex-docstruct-symbol)))) nil) nil nil nil 'reftex-cite-regexp-hist) @@ -229,7 +228,13 @@ buffer (not reftex-keep-temporary-buffers)))) (if (not buffer1) (message "No such BibTeX file %s (ignored)" buffer) - (message "Scanning bibliography database %s" buffer1)) + (message "Scanning bibliography database %s" buffer1) + (unless (verify-visited-file-modtime buffer1) + (when (y-or-n-p + (format "File %s changed on disk. Reread from disk? " + (file-name-nondirectory + (buffer-file-name buffer1)))) + (with-current-buffer buffer1 (revert-buffer t t))))) (set-buffer buffer1) (reftex-with-special-syntax-for-bib @@ -238,8 +243,8 @@ (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) + (unless (re-search-backward "\\(\\`\\|[\n\r]\\)[ \t]*\ +@\\(\\(?:\\w\\|\\s_\\)+\\)[ \t\n\r]*[{(]" nil t) (throw 'search-again nil)) (setq start-point (point)) (goto-char (match-end 0)) @@ -248,7 +253,7 @@ (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") @@ -257,12 +262,12 @@ (< (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")) (setq entry (buffer-substring start-point (point))) - + ;; Check if other regexp match as well (setq re-list rest-re) (while re-list @@ -270,24 +275,24 @@ ;; 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)))) @@ -350,50 +355,52 @@ (unless files (error "Need file name to find thebibliography environment")) (while (setq file (pop files)) - (setq buf (reftex-get-file-buffer-force + (setq buf (reftex-get-file-buffer-force file (not reftex-keep-temporary-buffers))) (unless buf (error "No such file %s" file)) (message "Scanning thebibliography environment in %s" file) - (save-excursion - (set-buffer buf) - (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward - "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t) - (beginning-of-line 2) - (setq start (point)) - (if (re-search-forward - "\\(\\`\\|[\n\r]\\)[ \t]*\\\\end{thebibliography}" nil t) - (progn - (beginning-of-line 1) - (setq end (point)))) - (when (and start end) - (setq entries - (append entries - (mapcar 'reftex-parse-bibitem - (delete "" - (split-string - (buffer-substring-no-properties start end) - "[ \t\n\r]*\\\\bibitem\\(\\[[^]]*]\\)*")))))) - (goto-char end))))) + (with-current-buffer buf + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (re-search-forward + "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t) + (beginning-of-line 2) + (setq start (point)) + (if (re-search-forward + "\\(\\`\\|[\n\r]\\)[ \t]*\\\\end{thebibliography}" nil t) + (progn + (beginning-of-line 1) + (setq end (point)))) + (when (and start end) + (setq entries + (append entries + (mapcar 'reftex-parse-bibitem + (delete "" + (split-string + (buffer-substring-no-properties + start end) + "[ \t\n\r]*\\\\bibitem[ \t]*\ +\\(\\[[^]]*]\\)*\[ \t]*")))))) + (goto-char end)))))) (unless entries (error "No bibitems found")) ;; Read a regexp, completing on known citation keys. (setq default (regexp-quote (reftex-get-bibkey-default))) - (setq re-list - (split-string - (completing-read + (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 + (cdr (assoc 'bibview-cache (symbol-value reftex-docstruct-symbol)))) nil) nil nil nil 'reftex-cite-regexp-hist) @@ -406,14 +413,14 @@ (error "Empty regular expression")) (while (and (setq re (pop re-list)) entries) - (setq entries + (setq entries (delq nil (mapcar (lambda (x) (if (string-match re (cdr (assoc "&entry" x))) x nil)) entries)))) - (setq entries - (mapcar + (setq entries + (mapcar (lambda (x) (push (cons "&formatted" (reftex-format-bibitem x)) x) (push (reftex-get-bib-field "&key" x) x) @@ -449,7 +456,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 @@ -461,41 +469,56 @@ (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+\\)[ \t\n\r]*[{(][ \t\n\r]*\\([^ \t\n\r,]+\\)" nil t) + (if (re-search-forward "@\\(\\(?:\\w\\|\\s_\\)+\\)[ \t\n\r]*\ +\[{(][ \t\n\r]*\\([^ \t\n\r,]+\\)" nil t) (setq alist (list (cons "&type" (downcase (reftex-match-string 1))) (cons "&key" (reftex-match-string 2))))) - (while (re-search-forward "\\(\\w+\\)[ \t\n\r]*=[ \t\n\r]*" nil t) + (while (re-search-forward "\\(\\(?:\\w\\|-\\)+\\)[ \t\n\r]*=[ \t\n\r]*" + nil t) (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)) @@ -540,10 +563,7 @@ (t "")))) (setq authors (reftex-truncate authors 30 t t)) (when (reftex-use-fonts) - (put-text-property 0 (length key) 'face - (reftex-verified-face reftex-label-face - 'font-lock-constant-face - 'font-lock-reference-face) + (put-text-property 0 (length key) 'face reftex-label-face key) (put-text-property 0 (length authors) 'face reftex-bib-author-face authors) @@ -639,26 +659,25 @@ While entering the regexp, completion on knows citation keys is possible. (insert-entries selected-entries) entry string cite-view) - (when (stringp selected-entries) - (error selected-entries)) (unless selected-entries (error "Quit")) (if (stringp selected-entries) ;; Nonexistent entry - (setq selected-entries nil - insert-entries (list (list selected-entries - (cons "&key" selected-entries)))) + (setq insert-entries (list (list selected-entries + (cons "&key" selected-entries))) + selected-entries nil) ;; It makes sense to compute the cite-view strings. (setq cite-view t)) (when (eq (car selected-entries) 'concat) ;; All keys go into a single command - we need to trick a little - ;; FIXME: Unfortunately, this meens that commenting does not work right. + ;; FIXME: Unfortunately, this means that commenting does not work right. (pop selected-entries) - (let ((concat-keys (mapconcat 'car selected-entries ","))) - (setq insert-entries + (let ((concat-keys (mapconcat 'car selected-entries + reftex-cite-key-separator))) + (setq insert-entries (list (list concat-keys (cons "&key" concat-keys)))))) - + (unless no-insert ;; We shall insert this into the buffer... @@ -676,8 +695,9 @@ While entering the regexp, completion on knows citation keys is possible. (equal arg '(4)))) (let ((start 0) (nth 0) value) (while (setq start (string-match "\\[\\]" string start)) - (setq value (read-string (format "Optional argument %d: " - (setq nth (1+ nth))))) + (setq value (save-match-data + (read-string (format "Optional argument %d: " + (setq nth (1+ nth)))))) (setq string (replace-match (concat "[" value "]") t t string)) (setq start (1+ start))))) ;; Should we cleanup empty optional arguments? @@ -685,7 +705,7 @@ While entering the regexp, completion on knows citation keys is possible. ;; it has to go. If there is only a single arg and empty, it can go ;; as well. (when reftex-cite-cleanup-optional-args - (cond + (cond ((string-match "\\([a-zA-Z0-9]\\)\\[\\]{" string) (setq string (replace-match "\\1{" nil nil string))) ((string-match "\\[\\]\\(\\[[a-zA-Z0-9., ]+\\]\\)" string) @@ -724,9 +744,9 @@ While entering the regexp, completion on knows citation keys is possible. (decf arg) (reftex-do-citation arg)) (forward-char 1))) - + ;; Return the citation key - (car (car selected-entries)))) + (mapcar 'car selected-entries))) (defun reftex-figure-out-cite-format (arg &optional no-insert format-key) ;; Check if there is already a cite command at point and change cite format @@ -738,16 +758,20 @@ While entering the regexp, completion on knows citation keys is possible. (no-insert ;; Format does not really matter because nothing will be inserted. (setq format "%l")) - + ((and (stringp macro) (string-match "\\`\\\\cite\\|cite\\'" macro)) ;; We are already inside a cite macro (if (or (not arg) (not (listp arg))) (setq format (concat - (if (member (preceding-char) '(?\{ ?,)) "" ",") + (if (member (preceding-char) '(?\{ ?,)) + "" + reftex-cite-key-separator) "%l" - (if (member (following-char) '(?\} ?,)) "" ","))) + (if (member (following-char) '(?\} ?,)) + "" + reftex-cite-key-separator))) (setq format "%l"))) (t ;; Figure out the correct format @@ -759,7 +783,7 @@ While entering the regexp, completion on knows citation keys is possible. (when (listp format) (setq key (or format-key - (reftex-select-with-char + (reftex-select-with-char "" (concat "SELECT A CITATION FORMAT\n\n" (mapconcat (lambda (x) @@ -788,8 +812,8 @@ While entering the regexp, completion on knows citation keys is possible. (let ((bibtype (reftex-bib-or-thebib)) found-list rtn key data selected-entries) - (while - (not + (while + (not (catch 'done ;; Scan bibtex files (setq found-list @@ -804,31 +828,30 @@ While entering the regexp, completion on knows citation keys is possible. (reftex-extract-bib-entries-from-thebibliography (reftex-uniquify (mapcar 'cdr - (reftex-all-assq + (reftex-all-assq 'thebib (symbol-value reftex-docstruct-symbol)))))) (reftex-default-bibliography (message "Using default bibliography") (reftex-extract-bib-entries (reftex-default-bibliography))) (t (error "No valid bibliography in this document, and no default available")))) - + (unless found-list (error "Sorry, no matches found")) - + ;; Remember where we came from (setq reftex-call-back-to-this-buffer (current-buffer)) (set-marker reftex-select-return-marker (point)) - + ;; Offer selection (save-window-excursion (delete-other-windows) - (let ((default-major-mode 'reftex-select-bib-mode)) - (reftex-kill-buffer "*RefTeX Select*") - (switch-to-buffer-other-window "*RefTeX Select*") - (unless (eq major-mode 'reftex-select-bib-mode) - (reftex-select-bib-mode)) - (let ((buffer-read-only nil)) - (erase-buffer) - (reftex-insert-bib-matches found-list))) + (reftex-kill-buffer "*RefTeX Select*") + (switch-to-buffer-other-window "*RefTeX Select*") + (unless (eq major-mode 'reftex-select-bib-mode) + (reftex-select-bib-mode)) + (let ((buffer-read-only nil)) + (erase-buffer) + (reftex-insert-bib-matches found-list)) (setq buffer-read-only t) (if (= 0 (buffer-size)) (error "No matches found")) @@ -858,15 +881,15 @@ While entering the regexp, completion on knows citation keys is possible. (goto-char 1)) ((eq key ?A) ;; Take all (marked) - (setq selected-entries + (setq selected-entries (if reftex-select-marked (mapcar 'car (nreverse reftex-select-marked)) found-list)) (throw 'done t)) ((eq key ?a) ;; Take all (marked), and push the symbol 'concat - (setq selected-entries - (cons 'concat + (setq selected-entries + (cons 'concat (if reftex-select-marked (mapcar 'car (nreverse reftex-select-marked)) found-list))) @@ -885,9 +908,9 @@ While entering the regexp, completion on knows citation keys is possible. ((or (eq key ?\C-m) (eq key 'return)) ;; Take selected - (setq selected-entries + (setq selected-entries (if reftex-select-marked - (cons 'concat + (cons 'concat (mapcar 'car (nreverse reftex-select-marked))) (if data (list data) nil))) (throw 'done t)) @@ -927,7 +950,7 @@ While entering the regexp, completion on knows citation keys is possible. (let ((file (read-file-name "File to create: "))) (find-file-other-window file) (if (> (buffer-size) 0) - (unless (yes-or-no-p + (unless (yes-or-no-p (format "Overwrite non-empty file %s? " file)) (error "Abort"))) (erase-buffer) @@ -1020,6 +1043,7 @@ While entering the regexp, completion on knows citation keys is possible. ((= l ?k) (reftex-get-bib-field "key" entry)) ((= l ?m) (reftex-get-bib-field "month" entry)) ((= l ?n) (reftex-get-bib-field "number" entry)) + ((= l ?N) (reftex-get-bib-field "note" entry)) ((= l ?o) (reftex-get-bib-field "organization" entry)) ((= l ?p) (reftex-get-bib-field "pages" entry)) ((= l ?P) (car (split-string @@ -1027,6 +1051,7 @@ While entering the regexp, completion on knows citation keys is possible. "[- .]+"))) ((= l ?s) (reftex-get-bib-field "school" entry)) ((= l ?u) (reftex-get-bib-field "publisher" entry)) + ((= l ?U) (reftex-get-bib-field "url" entry)) ((= l ?r) (reftex-get-bib-field "address" entry)) ((= l ?t) (reftex-get-bib-field "title" entry)) ((= l ?T) (reftex-abbreviate-title @@ -1047,7 +1072,7 @@ While entering the regexp, completion on knows citation keys is possible. (defun reftex-make-cite-echo-string (entry docstruct-symbol) ;; Format a bibtex entry for the echo area and cache the result. (let* ((key (reftex-get-bib-field "&key" entry)) - (string + (string (let* ((reftex-cite-punctuation '(" " " & " " etal."))) (reftex-format-citation entry reftex-cite-view-format))) (cache (assq 'bibview-cache (symbol-value docstruct-symbol))) @@ -1077,8 +1102,7 @@ While entering the regexp, completion on knows citation keys is possible. bibfile-list item bibtype) (catch 'exit - (save-excursion - (set-buffer reftex-call-back-to-this-buffer) + (with-current-buffer reftex-call-back-to-this-buffer (setq bibtype (reftex-bib-or-thebib)) (cond ((eq bibtype 'bib) @@ -1089,7 +1113,7 @@ While entering the regexp, completion on knows citation keys is possible. (setq bibfile-list (reftex-uniquify (mapcar 'cdr - (reftex-all-assq + (reftex-all-assq 'thebib (symbol-value reftex-docstruct-symbol)))) item t)) (reftex-default-bibliography @@ -1100,24 +1124,24 @@ While entering the regexp, completion on knows citation keys is possible. (setq bibfile-list (reftex-visited-files bibfile-list))) (condition-case nil - (reftex-pop-to-bibtex-entry + (reftex-pop-to-bibtex-entry key bibfile-list (not reftex-keep-temporary-buffers) t item) (error (ding)))) - + (select-window win))) ;;; Global BibTeX file (defun reftex-all-used-citation-keys () (reftex-access-scan-info) (let ((files (reftex-all-document-files)) file keys kk k) - (save-excursion + (save-current-buffer (while (setq file (pop files)) (set-buffer (reftex-get-file-buffer-force file 'mark)) (save-excursion (save-restriction (widen) (goto-char (point-min)) - (while (re-search-forward "^[^%\n\r]*\\\\\\(bibentry\\|[a-zA-Z]*cite[a-zA-Z]*\\)\\(\\[[^\\]]*\\]\\)?{\\([^}]+\\)}" nil t) + (while (re-search-forward "\\(?:^\\|\\=\\)[^%\n\r]*?\\\\\\(bibentry\\|[a-zA-Z]*cite[a-zA-Z]*\\)\\(\\[[^\\]]*\\]\\)?{\\([^}]+\\)}" nil t) (setq kk (match-string-no-properties 3)) (while (string-match "%.*\n?" kk) (setq kk (replace-match "" t t kk))) @@ -1128,27 +1152,43 @@ While entering the regexp, completion on knows citation keys is possible. (reftex-kill-temporary-buffers) keys)) +(defun reftex-get-string-refs (alist) + "Return a list of BibTeX @string references that appear as values in ALIST." + (reftex-remove-if (lambda (x) (string-match "^\\([\"{]\\|[0-9]+$\\)" x)) + ;; get list of values, discard keys + (mapcar 'cdr + ;; remove &key and &type entries + (reftex-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 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. + +Entries referenced from other entries must appear after all +referencing entries. + +You can define strings to be used as header or footer for the +created files in the variables `reftex-create-bibtex-header' or +`reftex-create-bibtex-footer' respectively." (interactive "FNew BibTeX file: ") (let ((keys (reftex-all-used-citation-keys)) (files (reftex-get-bibfile-list)) - file key entries beg end entry) - (save-excursion - (while (setq file (pop files)) + file key entries beg end entry string-keys string-entries) + (save-current-buffer + (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 - "^[ \t]*@[a-zA-Z]+[ \t]*{\\([^ \t\r\n]+\\)," - nil t) + (while (re-search-forward "^[ \t]*@\\(?:\\w\\|\\s_\\)+[ \t\n\r]*\ +\[{(][ \t\n\r]*\\([^ \t\n\r,]+\\)" nil t) (setq key (match-string 1) beg (match-beginning 0) end (progn @@ -1160,19 +1200,58 @@ The sequence in the new file is the same as it was in the old database." (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-current-buffer + (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 + "^[ \t]*@[Ss][Tt][Rr][Ii][Nn][Gg][ \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 + (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" (length entries)))) -;; arch-tag: d53d0a5a-ab32-4b52-a846-2a7c3527cd89 ;;; reftex-cite.el ends here