Fix up comment convention on the arch-tag lines.
[bpt/emacs.git] / lisp / textmodes / reftex-cite.el
CommitLineData
3afbc435 1;;; reftex-cite.el --- creating citations with RefTeX
f2e3589a
GM
2
3;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
12dc447f 4;; 2006, 2007, 2008 Free Software Foundation, Inc.
3ba2590f 5
6fbeb429 6;; Author: Carsten Dominik <dominik@science.uva.nl>
ce545621 7;; Maintainer: auctex-devel@gnu.org
5d2a58e0 8;; Version: 4.31
3ba2590f
RS
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
5a9dffec 14;; the Free Software Foundation; either version 3, or (at your option)
3ba2590f
RS
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
27e81652
TTN
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
1a9461d0 26
3afbc435
PJ
27;;; Commentary:
28
29;;; Code:
30
7c4d13cc 31(eval-when-compile (require 'cl))
1a9461d0
CD
32(provide 'reftex-cite)
33(require 'reftex)
34;;;
35
36;; Variables and constants
37
38;; The history list of regular expressions used for citations
39(defvar reftex-cite-regexp-hist nil)
40
41;; Prompt and help string for citation selection
42(defconst reftex-citation-prompt
43 "Select: [n]ext [p]revious [r]estrict [ ]full_entry [q]uit RET [?]Help+more")
44
45(defconst reftex-citation-help
46 " n / p Go to next/previous entry (Cursor motion works as well).
47 g / r Start over with new regexp / Refine with additional regexp.
48 SPC Show full database entry in other window.
49 f Toggle follow mode: Other window will follow with full db entry.
50 . Show insertion point.
51 q Quit without inserting \\cite macro into buffer.
52 TAB Enter citation key with completion.
53 RET Accept current entry (also on mouse-2) and create \\cite macro.
54 m / u Mark/Unmark the entry.
f3c18bd0 55 e / E Create BibTeX file with all (marked/unmarked) entries
1a9461d0
CD
56 a / A Put all (marked) entries into one/many \\cite commands.")
57
58;; Find bibtex files
59
6fbeb429
CD
60(defmacro reftex-with-special-syntax-for-bib (&rest body)
61 `(let ((saved-syntax (syntax-table)))
62 (unwind-protect
3666daf6
CD
63 (progn
64 (set-syntax-table reftex-syntax-table-for-bib)
65 ,@body)
6fbeb429
CD
66 (set-syntax-table saved-syntax))))
67
1a9461d0
CD
68(defun reftex-default-bibliography ()
69 ;; Return the expanded value of `reftex-default-bibliography'.
70 ;; The expanded value is cached.
71 (unless (eq (get 'reftex-default-bibliography :reftex-raw)
3666daf6 72 reftex-default-bibliography)
1a9461d0 73 (put 'reftex-default-bibliography :reftex-expanded
7b07114a 74 (reftex-locate-bibliography-files
3666daf6 75 default-directory reftex-default-bibliography))
1a9461d0 76 (put 'reftex-default-bibliography :reftex-raw
3666daf6 77 reftex-default-bibliography))
1a9461d0
CD
78 (get 'reftex-default-bibliography :reftex-expanded))
79
20cd3579
CD
80(defun reftex-bib-or-thebib ()
81 ;; Tests if BibTeX or \begin{tehbibliography} should be used for the
82 ;; citation
83 ;; Find the bof of the current file
84 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
3666daf6
CD
85 (rest (or (member (list 'bof (buffer-file-name)) docstruct)
86 docstruct))
87 (bib (assq 'bib rest))
88 (thebib (assq 'thebib rest))
89 (bibmem (memq bib rest))
90 (thebibmem (memq thebib rest)))
20cd3579
CD
91 (when (not (or thebib bib))
92 (setq bib (assq 'bib docstruct)
3666daf6
CD
93 thebib (assq 'thebib docstruct)
94 bibmem (memq bib docstruct)
95 thebibmem (memq thebib docstruct)))
20cd3579 96 (if (> (length bibmem) (length thebibmem))
3666daf6 97 (if bib 'bib nil)
20cd3579
CD
98 (if thebib 'thebib nil))))
99
1a9461d0
CD
100(defun reftex-get-bibfile-list ()
101 ;; Return list of bibfiles for current document.
102 ;; When using the chapterbib or bibunits package you should either
103 ;; use the same database files everywhere, or separate parts using
104 ;; different databases into different files (included into the mater file).
105 ;; Then this function will return the applicable database files.
106
107 ;; Ensure access to scanning info
108 (reftex-access-scan-info)
109 (or
110 ;; Try inside this file (and its includes)
111 (cdr (reftex-last-assoc-before-elt
112 'bib (list 'eof (buffer-file-name))
113 (member (list 'bof (buffer-file-name))
114 (symbol-value reftex-docstruct-symbol))))
115 ;; Try after the beginning of this file
116 (cdr (assq 'bib (member (list 'bof (buffer-file-name))
117 (symbol-value reftex-docstruct-symbol))))
118 ;; Anywhere in the entire document
119 (cdr (assq 'bib (symbol-value reftex-docstruct-symbol)))
120 (error "\\bibliography statement missing or .bib files not found")))
121
122;; Find a certain reference in any of the BibTeX files.
123
124(defun reftex-pop-to-bibtex-entry (key file-list &optional mark-to-kill
3666daf6 125 highlight item return)
1a9461d0
CD
126 ;; Find BibTeX KEY in any file in FILE-LIST in another window.
127 ;; If MARK-TO-KILL is non-nil, mark new buffer to kill.
128 ;; If HIGHLIGHT is non-nil, highlight the match.
129 ;; If ITEM in non-nil, search for bibitem instead of database entry.
759f7eed 130 ;; If RETURN is non-nil, just return the entry and restore point.
1a9461d0
CD
131
132 (let* ((re
7b07114a 133 (if item
3666daf6
CD
134 (concat "\\\\bibitem\\(\\[[^]]*\\]\\)?{" (regexp-quote key) "}")
135 (concat "@[a-zA-Z]+[ \t\n\r]*[{(][ \t\n\r]*" (regexp-quote key)
136 "[, \t\r\n}]")))
137 (buffer-conf (current-buffer))
759f7eed 138 file buf pos oldpos)
1a9461d0
CD
139
140 (catch 'exit
141 (while file-list
142 (setq file (car file-list)
143 file-list (cdr file-list))
144 (unless (setq buf (reftex-get-file-buffer-force file mark-to-kill))
145 (error "No such file %s" file))
146 (set-buffer buf)
759f7eed 147 (setq oldpos (point))
1a9461d0
CD
148 (widen)
149 (goto-char (point-min))
759f7eed
CD
150 (if (not (re-search-forward re nil t))
151 (goto-char oldpos) ;; restore previous position of point
1a9461d0 152 (goto-char (match-beginning 0))
3666daf6
CD
153 (setq pos (point))
154 (when return
155 ;; Just return the relevant entry
156 (if item (goto-char (match-end 0)))
7b07114a 157 (setq return (buffer-substring
3666daf6 158 (point) (reftex-end-of-bib-entry item)))
759f7eed 159 (goto-char oldpos) ;; restore point.
3666daf6
CD
160 (set-buffer buffer-conf)
161 (throw 'exit return))
162 (switch-to-buffer-other-window buf)
163 (goto-char pos)
1a9461d0
CD
164 (recenter 0)
165 (if highlight
166 (reftex-highlight 0 (match-beginning 0) (match-end 0)))
167 (throw 'exit (selected-window))))
168 (set-buffer buffer-conf)
169 (if item
3666daf6
CD
170 (error "No \\bibitem with citation key %s" key)
171 (error "No BibTeX entry with citation key %s" key)))))
1a9461d0
CD
172
173(defun reftex-end-of-bib-entry (item)
7b07114a 174 (save-excursion
1a9461d0 175 (condition-case nil
7b07114a 176 (if item
3666daf6
CD
177 (progn (end-of-line)
178 (re-search-forward
179 "\\\\bibitem\\|\\end{thebibliography}")
180 (1- (match-beginning 0)))
181 (progn (forward-list 1) (point)))
1a9461d0
CD
182 (error (min (point-max) (+ 300 (point)))))))
183
184;; Parse bibtex buffers
185
3666daf6 186(defun reftex-extract-bib-entries (buffers)
1a9461d0
CD
187 ;; Extract bib entries which match regexps from BUFFERS.
188 ;; BUFFERS is a list of buffers or file names.
189 ;; Return list with entries."
3666daf6
CD
190 (let* (re-list first-re rest-re
191 (buffer-list (if (listp buffers) buffers (list buffers)))
192 found-list entry buffer1 buffer alist
193 key-point start-point end-point default)
194
195 ;; Read a regexp, completing on known citation keys.
196 (setq default (regexp-quote (reftex-get-bibkey-default)))
7b07114a
CD
197 (setq re-list
198 (split-string
199 (completing-read
3666daf6
CD
200 (concat
201 "Regex { && Regex...}: "
202 "[" default "]: ")
203 (if reftex-mode
204 (if (fboundp 'LaTeX-bibitem-list)
205 (LaTeX-bibitem-list)
7b07114a 206 (cdr (assoc 'bibview-cache
3666daf6
CD
207 (symbol-value reftex-docstruct-symbol))))
208 nil)
209 nil nil nil 'reftex-cite-regexp-hist)
210 "[ \t]*&&[ \t]*"))
211
212 (if (or (null re-list ) (equal re-list '("")))
213 (setq re-list (list default)))
214
215 (setq first-re (car re-list) ; We'll use the first re to find things,
216 rest-re (cdr re-list)) ; the others to narrow down.
217 (if (string-match "\\`[ \t]*\\'" (or first-re ""))
218 (error "Empty regular expression"))
1a9461d0
CD
219
220 (save-excursion
221 (save-window-excursion
222
223 ;; Walk through all bibtex files
224 (while buffer-list
225 (setq buffer (car buffer-list)
226 buffer-list (cdr buffer-list))
227 (if (and (bufferp buffer)
228 (buffer-live-p buffer))
229 (setq buffer1 buffer)
230 (setq buffer1 (reftex-get-file-buffer-force
231 buffer (not reftex-keep-temporary-buffers))))
232 (if (not buffer1)
233 (message "No such BibTeX file %s (ignored)" buffer)
234 (message "Scanning bibliography database %s" buffer1))
235
236 (set-buffer buffer1)
3666daf6
CD
237 (reftex-with-special-syntax-for-bib
238 (save-excursion
239 (goto-char (point-min))
240 (while (re-search-forward first-re nil t)
241 (catch 'search-again
242 (setq key-point (point))
243 (unless (re-search-backward
244 "\\(\\`\\|[\n\r]\\)[ \t]*@\\([a-zA-Z]+\\)[ \t\n\r]*[{(]" nil t)
245 (throw 'search-again nil))
246 (setq start-point (point))
247 (goto-char (match-end 0))
248 (condition-case nil
249 (up-list 1)
250 (error (goto-char key-point)
1a9461d0 251 (throw 'search-again nil)))
3666daf6 252 (setq end-point (point))
7b07114a 253
3666daf6
CD
254 ;; Ignore @string, @comment and @c entries or things
255 ;; outside entries
256 (when (or (string= (downcase (match-string 2)) "string")
257 (string= (downcase (match-string 2)) "comment")
258 (string= (downcase (match-string 2)) "c")
259 (< (point) key-point)) ; this means match not in {}
260 (goto-char key-point)
261 (throw 'search-again nil))
7b07114a 262
3666daf6
CD
263 ;; Well, we have got a match
264 ;;(setq entry (concat
265 ;; (buffer-substring start-point (point)) "\n"))
266 (setq entry (buffer-substring start-point (point)))
7b07114a 267
3666daf6
CD
268 ;; Check if other regexp match as well
269 (setq re-list rest-re)
270 (while re-list
271 (unless (string-match (car re-list) entry)
272 ;; nope - move on
273 (throw 'search-again nil))
274 (pop re-list))
7b07114a 275
3666daf6
CD
276 (setq alist (reftex-parse-bibtex-entry
277 nil start-point end-point))
278 (push (cons "&entry" entry) alist)
7b07114a 279
3666daf6
CD
280 ;; check for crossref entries
281 (if (assoc "crossref" alist)
282 (setq alist
283 (append
284 alist (reftex-get-crossref-alist alist))))
7b07114a 285
3666daf6
CD
286 ;; format the entry
287 (push (cons "&formatted" (reftex-format-bib-entry alist))
288 alist)
7b07114a 289
3666daf6
CD
290 ;; make key the first element
291 (push (reftex-get-bib-field "&key" alist) alist)
7b07114a 292
3666daf6
CD
293 ;; add it to the list
294 (push alist found-list)))))
295 (reftex-kill-temporary-buffers))))
1a9461d0
CD
296 (setq found-list (nreverse found-list))
297
298 ;; Sorting
299 (cond
300 ((eq 'author reftex-sort-bibtex-matches)
301 (sort found-list 'reftex-bib-sort-author))
302 ((eq 'year reftex-sort-bibtex-matches)
303 (sort found-list 'reftex-bib-sort-year))
304 ((eq 'reverse-year reftex-sort-bibtex-matches)
305 (sort found-list 'reftex-bib-sort-year-reverse))
306 (t found-list))))
307
308(defun reftex-bib-sort-author (e1 e2)
309 (let ((al1 (reftex-get-bib-names "author" e1))
310 (al2 (reftex-get-bib-names "author" e2)))
311 (while (and al1 al2 (string= (car al1) (car al2)))
312 (pop al1)
313 (pop al2))
314 (if (and (stringp (car al1))
315 (stringp (car al2)))
316 (string< (car al1) (car al2))
317 (not (stringp (car al1))))))
318
319(defun reftex-bib-sort-year (e1 e2)
027a4b6b
JB
320 (< (string-to-number (or (cdr (assoc "year" e1)) "0"))
321 (string-to-number (or (cdr (assoc "year" e2)) "0"))))
1a9461d0
CD
322
323(defun reftex-bib-sort-year-reverse (e1 e2)
027a4b6b
JB
324 (> (string-to-number (or (cdr (assoc "year" e1)) "0"))
325 (string-to-number (or (cdr (assoc "year" e2)) "0"))))
1a9461d0
CD
326
327(defun reftex-get-crossref-alist (entry)
328 ;; return the alist from a crossref entry
329 (let ((crkey (cdr (assoc "crossref" entry)))
330 start)
331 (save-excursion
332 (save-restriction
333 (widen)
334 (if (re-search-forward
335 (concat "@\\w+[{(][ \t\n\r]*" (regexp-quote crkey)
336 "[ \t\n\r]*,") nil t)
337 (progn
338 (setq start (match-beginning 0))
339 (condition-case nil
340 (up-list 1)
341 (error nil))
342 (reftex-parse-bibtex-entry nil start (point)))
343 nil)))))
344
aa87aafc 345;; Parse the bibliography environment
3666daf6 346(defun reftex-extract-bib-entries-from-thebibliography (files)
1a9461d0
CD
347 ;; Extract bib-entries from the \begin{thebibliography} environment.
348 ;; Parsing is not as good as for the BibTeX database stuff.
349 ;; The environment should be located in file FILE.
350
3666daf6 351 (let* (start end buf entries re re-list file default)
09308e63 352 (unless files
1a9461d0 353 (error "Need file name to find thebibliography environment"))
09308e63 354 (while (setq file (pop files))
7b07114a 355 (setq buf (reftex-get-file-buffer-force
3666daf6 356 file (not reftex-keep-temporary-buffers)))
09308e63 357 (unless buf
3666daf6 358 (error "No such file %s" file))
09308e63 359 (message "Scanning thebibliography environment in %s" file)
1a9461d0 360
09308e63 361 (save-excursion
3666daf6
CD
362 (set-buffer buf)
363 (save-restriction
364 (widen)
365 (goto-char (point-min))
7b07114a 366 (while (re-search-forward
3666daf6
CD
367 "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t)
368 (beginning-of-line 2)
369 (setq start (point))
7b07114a 370 (if (re-search-forward
3666daf6
CD
371 "\\(\\`\\|[\n\r]\\)[ \t]*\\\\end{thebibliography}" nil t)
372 (progn
373 (beginning-of-line 1)
374 (setq end (point))))
375 (when (and start end)
7b07114a 376 (setq entries
3666daf6 377 (append entries
09308e63 378 (mapcar 'reftex-parse-bibitem
3666daf6 379 (delete ""
7b07114a 380 (split-string
3666daf6
CD
381 (buffer-substring-no-properties start end)
382 "[ \t\n\r]*\\\\bibitem\\(\\[[^]]*]\\)*"))))))
383 (goto-char end)))))
1a9461d0
CD
384 (unless entries
385 (error "No bibitems found"))
386
3666daf6
CD
387 ;; Read a regexp, completing on known citation keys.
388 (setq default (regexp-quote (reftex-get-bibkey-default)))
7b07114a
CD
389 (setq re-list
390 (split-string
391 (completing-read
3666daf6
CD
392 (concat
393 "Regex { && Regex...}: "
394 "[" default "]: ")
395 (if reftex-mode
396 (if (fboundp 'LaTeX-bibitem-list)
397 (LaTeX-bibitem-list)
7b07114a 398 (cdr (assoc 'bibview-cache
3666daf6
CD
399 (symbol-value reftex-docstruct-symbol))))
400 nil)
401 nil nil nil 'reftex-cite-regexp-hist)
402 "[ \t]*&&[ \t]*"))
403
404 (if (or (null re-list ) (equal re-list '("")))
405 (setq re-list (list default)))
406
407 (if (string-match "\\`[ \t]*\\'" (car re-list))
408 (error "Empty regular expression"))
409
1a9461d0 410 (while (and (setq re (pop re-list)) entries)
7b07114a 411 (setq entries
3666daf6
CD
412 (delq nil (mapcar
413 (lambda (x)
414 (if (string-match re (cdr (assoc "&entry" x)))
415 x nil))
416 entries))))
7b07114a
CD
417 (setq entries
418 (mapcar
3666daf6
CD
419 (lambda (x)
420 (push (cons "&formatted" (reftex-format-bibitem x)) x)
421 (push (reftex-get-bib-field "&key" x) x)
422 x)
423 entries))
1a9461d0
CD
424
425 entries))
426
7ac7387b
CD
427(defun reftex-get-bibkey-default ()
428 ;; Return the word before the cursor. If the cursor is in a
429 ;; citation macro, return the word before the macro.
430 (let* ((macro (reftex-what-macro 1)))
431 (save-excursion
432 (if (and macro (string-match "cite" (car macro)))
3666daf6 433 (goto-char (cdr macro)))
7ac7387b
CD
434 (skip-chars-backward "^a-zA-Z0-9")
435 (reftex-this-word))))
436
1a9461d0
CD
437;; Parse and format individual entries
438
439(defun reftex-get-bib-names (field entry)
440 ;; Return a list with the author or editor names in ENTRY
441 (let ((names (reftex-get-bib-field field entry)))
442 (if (equal "" names)
443 (setq names (reftex-get-bib-field "editor" entry)))
444 (while (string-match "\\band\\b[ \t]*" names)
445 (setq names (replace-match "\n" nil t names)))
446 (while (string-match "[\\.a-zA-Z\\-]+\\.[ \t]*\\|,.*\\|[{}]+" names)
447 (setq names (replace-match "" nil t names)))
448 (while (string-match "^[ \t]+\\|[ \t]+$" names)
449 (setq names (replace-match "" nil t names)))
450 (while (string-match "[ \t][ \t]+" names)
451 (setq names (replace-match " " nil t names)))
452 (split-string names "\n")))
453
454(defun reftex-parse-bibtex-entry (entry &optional from to)
455 (let (alist key start field)
456 (save-excursion
457 (save-restriction
458 (if entry
459 (progn
460 (set-buffer (get-buffer-create " *RefTeX-scratch*"))
461 (fundamental-mode)
3666daf6 462 (set-syntax-table reftex-syntax-table-for-bib)
1a9461d0
CD
463 (erase-buffer)
464 (insert entry))
465 (widen)
466 (narrow-to-region from to))
467 (goto-char (point-min))
468
469 (if (re-search-forward
470 "@\\(\\w+\\)[ \t\n\r]*[{(][ \t\n\r]*\\([^ \t\n\r,]+\\)" nil t)
471 (setq alist
472 (list
473 (cons "&type" (downcase (reftex-match-string 1)))
474 (cons "&key" (reftex-match-string 2)))))
475 (while (re-search-forward "\\(\\w+\\)[ \t\n\r]*=[ \t\n\r]*" nil t)
476 (setq key (downcase (reftex-match-string 1)))
477 (cond
478 ((= (following-char) ?{)
479 (forward-char 1)
480 (setq start (point))
481 (condition-case nil
482 (up-list 1)
483 (error nil)))
484 ((= (following-char) ?\")
485 (forward-char 1)
486 (setq start (point))
487 (while (and (search-forward "\"" nil t)
488 (= ?\\ (char-after (- (point) 2))))))
489 (t
490 (setq start (point))
491 (re-search-forward "[ \t]*[\n\r,}]" nil 1)))
492 (setq field (buffer-substring-no-properties start (1- (point))))
493 ;; remove extra whitespace
494 (while (string-match "[\n\t\r]\\|[ \t][ \t]+" field)
495 (setq field (replace-match " " nil t field)))
496 ;; remove leading garbage
497 (if (string-match "^[ \t{]+" field)
498 (setq field (replace-match "" nil t field)))
499 ;; remove trailing garbage
500 (if (string-match "[ \t}]+$" field)
501 (setq field (replace-match "" nil t field)))
502 (push (cons key field) alist))))
503 alist))
504
505(defun reftex-get-bib-field (fieldname entry &optional format)
506 ;; Extract the field FIELDNAME from an ENTRY
507 (let ((cell (assoc fieldname entry)))
508 (if cell
3666daf6
CD
509 (if format
510 (format format (cdr cell))
511 (cdr cell))
1a9461d0
CD
512 "")))
513
514(defun reftex-format-bib-entry (entry)
515 ;; Format a BibTeX ENTRY so that it is nice to look at
516 (let*
517 ((auth-list (reftex-get-bib-names "author" entry))
518 (authors (mapconcat 'identity auth-list ", "))
519 (year (reftex-get-bib-field "year" entry))
520 (title (reftex-get-bib-field "title" entry))
521 (type (reftex-get-bib-field "&type" entry))
522 (key (reftex-get-bib-field "&key" entry))
523 (extra
524 (cond
525 ((equal type "article")
526 (concat (reftex-get-bib-field "journal" entry) " "
527 (reftex-get-bib-field "volume" entry) ", "
528 (reftex-get-bib-field "pages" entry)))
529 ((equal type "book")
530 (concat "book (" (reftex-get-bib-field "publisher" entry) ")"))
531 ((equal type "phdthesis")
532 (concat "PhD: " (reftex-get-bib-field "school" entry)))
533 ((equal type "mastersthesis")
534 (concat "Master: " (reftex-get-bib-field "school" entry)))
535 ((equal type "inbook")
536 (concat "Chap: " (reftex-get-bib-field "chapter" entry)
537 ", pp. " (reftex-get-bib-field "pages" entry)))
538 ((or (equal type "conference")
539 (equal type "incollection")
540 (equal type "inproceedings"))
541 (reftex-get-bib-field "booktitle" entry "in: %s"))
542 (t ""))))
543 (setq authors (reftex-truncate authors 30 t t))
544 (when (reftex-use-fonts)
545 (put-text-property 0 (length key) 'face
3666daf6
CD
546 (reftex-verified-face reftex-label-face
547 'font-lock-constant-face
548 'font-lock-reference-face)
1a9461d0
CD
549 key)
550 (put-text-property 0 (length authors) 'face reftex-bib-author-face
551 authors)
552 (put-text-property 0 (length year) 'face reftex-bib-year-face
553 year)
554 (put-text-property 0 (length title) 'face reftex-bib-title-face
555 title)
556 (put-text-property 0 (length extra) 'face reftex-bib-extra-face
557 extra))
558 (concat key "\n " authors " " year " " extra "\n " title "\n\n")))
559
560(defun reftex-parse-bibitem (item)
561 ;; Parse a \bibitem entry
562 (let ((key "") (text ""))
70d797cd 563 (when (string-match "\\`{\\([^}]+\\)}\\([^\000]*\\)" item)
1a9461d0 564 (setq key (match-string 1 item)
3666daf6 565 text (match-string 2 item)))
1a9461d0
CD
566 ;; Clean up the text a little bit
567 (while (string-match "[\n\r\t]\\|[ \t][ \t]+" text)
568 (setq text (replace-match " " nil t text)))
569 (if (string-match "\\`[ \t]+" text)
3666daf6 570 (setq text (replace-match "" nil t text)))
1a9461d0
CD
571 (list
572 (cons "&key" key)
573 (cons "&text" text)
574 (cons "&entry" (concat key " " text)))))
575
576(defun reftex-format-bibitem (item)
577 ;; Format a \bibitem entry so that it is (relatively) nice to look at.
578 (let ((text (reftex-get-bib-field "&text" item))
3666daf6
CD
579 (key (reftex-get-bib-field "&key" item))
580 (lines nil))
1a9461d0
CD
581
582 ;; Wrap the text into several lines.
583 (while (and (> (length text) 70)
3666daf6
CD
584 (string-match " " (substring text 60)))
585 (push (substring text 0 (+ 60 (match-beginning 0))) lines)
586 (setq text (substring text (+ 61 (match-beginning 0)))))
1a9461d0
CD
587 (push text lines)
588 (setq text (mapconcat 'identity (nreverse lines) "\n "))
589
590 (when (reftex-use-fonts)
591 (put-text-property 0 (length text) 'face reftex-bib-author-face text))
592 (concat key "\n " text "\n\n")))
593
594;; Make a citation
595
596;;;###autoload
7c4d13cc 597(defun reftex-citation (&optional no-insert format-key)
1a9461d0
CD
598 "Make a citation using BibTeX database files.
599After prompting for a regular expression, scans the buffers with
600bibtex entries (taken from the \\bibliography command) and offers the
9e3e72cb 601matching entries for selection. The selected entry is formatted according
1a9461d0
CD
602to `reftex-cite-format' and inserted into the buffer.
603
604If NO-INSERT is non-nil, nothing is inserted, only the selected key returned.
605
42187e99 606FORMAT-KEY can be used to pre-select a citation format.
7c4d13cc 607
f3c18bd0
CD
608When called with a `C-u' prefix, prompt for optional arguments in
609cite macros. When called with a numeric prefix, make that many
610citations. When called with point inside the braces of a `\\cite'
611command, it will add another key, ignoring the value of
612`reftex-cite-format'.
1a9461d0
CD
613
614The regular expression uses an expanded syntax: && is interpreted as `and'.
615Thus, `aaaa&&bbb' matches entries which contain both `aaaa' and `bbb'.
616While entering the regexp, completion on knows citation keys is possible.
617`=' is a good regular expression to match all entries in all files."
618
619 (interactive)
620
621 ;; check for recursive edit
622 (reftex-check-recursive-edit)
623
624 ;; This function may also be called outside reftex-mode.
625 ;; Thus look for the scanning info only if in reftex-mode.
626
627 (when reftex-mode
f3c18bd0 628 (reftex-access-scan-info nil))
1a9461d0
CD
629
630 ;; Call reftex-do-citation, but protected
631 (unwind-protect
7c4d13cc 632 (reftex-do-citation current-prefix-arg no-insert format-key)
1a9461d0
CD
633 (reftex-kill-temporary-buffers)))
634
7c4d13cc 635(defun reftex-do-citation (&optional arg no-insert format-key)
1a9461d0
CD
636 ;; This really does the work of reftex-citation.
637
7c4d13cc 638 (let* ((format (reftex-figure-out-cite-format arg no-insert format-key))
3666daf6
CD
639 (docstruct-symbol reftex-docstruct-symbol)
640 (selected-entries (reftex-offer-bib-menu))
641 (insert-entries selected-entries)
642 entry string cite-view)
1a9461d0 643
f3c18bd0
CD
644 (when (stringp selected-entries)
645 (error selected-entries))
1a9461d0
CD
646 (unless selected-entries (error "Quit"))
647
648 (if (stringp selected-entries)
3666daf6
CD
649 ;; Nonexistent entry
650 (setq selected-entries nil
651 insert-entries (list (list selected-entries
652 (cons "&key" selected-entries))))
1a9461d0
CD
653 ;; It makes sense to compute the cite-view strings.
654 (setq cite-view t))
655
656 (when (eq (car selected-entries) 'concat)
657 ;; All keys go into a single command - we need to trick a little
f3c18bd0 658 ;; FIXME: Unfortunately, this meens that commenting does not work right.
1a9461d0
CD
659 (pop selected-entries)
660 (let ((concat-keys (mapconcat 'car selected-entries ",")))
7b07114a 661 (setq insert-entries
3666daf6 662 (list (list concat-keys (cons "&key" concat-keys))))))
7b07114a 663
1a9461d0
CD
664 (unless no-insert
665
666 ;; We shall insert this into the buffer...
667 (message "Formatting...")
42187e99 668
1a9461d0 669 (while (setq entry (pop insert-entries))
3666daf6
CD
670 ;; Format the citation and insert it
671 (setq string (if reftex-format-cite-function
672 (funcall reftex-format-cite-function
673 (reftex-get-bib-field "&key" entry)
674 format)
675 (reftex-format-citation entry format)))
f3c18bd0
CD
676 (when (or (eq reftex-cite-prompt-optional-args t)
677 (and reftex-cite-prompt-optional-args
678 (equal arg '(4))))
679 (let ((start 0) (nth 0) value)
680 (while (setq start (string-match "\\[\\]" string start))
681 (setq value (read-string (format "Optional argument %d: "
682 (setq nth (1+ nth)))))
683 (setq string (replace-match (concat "[" value "]") t t string))
684 (setq start (1+ start)))))
685 ;; Should we cleanup empty optional arguments?
686 ;; if the first is empty, it can be removed. If the second is empty,
3ee26b0c 687 ;; it has to go. If there is only a single arg and empty, it can go
3a1e8128 688 ;; as well.
f3c18bd0 689 (when reftex-cite-cleanup-optional-args
7b07114a 690 (cond
3ee26b0c
CD
691 ((string-match "\\([a-zA-Z0-9]\\)\\[\\]{" string)
692 (setq string (replace-match "\\1{" nil nil string)))
f3c18bd0
CD
693 ((string-match "\\[\\]\\(\\[[a-zA-Z0-9., ]+\\]\\)" string)
694 (setq string (replace-match "\\1" nil nil string)))
695 ((string-match "\\[\\]\\[\\]" string)
696 (setq string (replace-match "" t t string)))))
3666daf6 697 (insert string))
1a9461d0
CD
698
699 ;; Reposition cursor?
700 (when (string-match "\\?" string)
3666daf6
CD
701 (search-backward "?")
702 (delete-char 1))
1a9461d0
CD
703
704 ;; Tell AUCTeX
551e625f 705 (when (and reftex-mode
3666daf6
CD
706 (fboundp 'LaTeX-add-bibitems)
707 reftex-plug-into-AUCTeX)
708 (apply 'LaTeX-add-bibitems (mapcar 'car selected-entries)))
551e625f 709
1a9461d0
CD
710 ;; Produce the cite-view strings
711 (when (and reftex-mode reftex-cache-cite-echo cite-view)
551e625f
GM
712 (mapc (lambda (entry)
713 (reftex-make-cite-echo-string entry docstruct-symbol))
714 selected-entries))
1a9461d0
CD
715
716 (message ""))
717
718 (set-marker reftex-select-return-marker nil)
719 (reftex-kill-buffer "*RefTeX Select*")
551e625f 720
1a9461d0
CD
721 ;; Check if the prefix arg was numeric, and call recursively
722 (when (integerp arg)
723 (if (> arg 1)
551e625f 724 (progn
3666daf6
CD
725 (skip-chars-backward "}")
726 (decf arg)
727 (reftex-do-citation arg))
728 (forward-char 1)))
7b07114a 729
1a9461d0
CD
730 ;; Return the citation key
731 (car (car selected-entries))))
732
7c4d13cc 733(defun reftex-figure-out-cite-format (arg &optional no-insert format-key)
1a9461d0
CD
734 ;; Check if there is already a cite command at point and change cite format
735 ;; in order to only add another reference in the same cite command.
736 (let ((macro (car (reftex-what-macro 1)))
3666daf6
CD
737 (cite-format-value (reftex-get-cite-format))
738 key format)
1a9461d0
CD
739 (cond
740 (no-insert
741 ;; Format does not really matter because nothing will be inserted.
742 (setq format "%l"))
7b07114a 743
1a9461d0 744 ((and (stringp macro)
3666daf6 745 (string-match "\\`\\\\cite\\|cite\\'" macro))
1a9461d0
CD
746 ;; We are already inside a cite macro
747 (if (or (not arg) (not (listp arg)))
3666daf6
CD
748 (setq format
749 (concat
750 (if (member (preceding-char) '(?\{ ?,)) "" ",")
751 "%l"
752 (if (member (following-char) '(?\} ?,)) "" ",")))
753 (setq format "%l")))
1a9461d0
CD
754 (t
755 ;; Figure out the correct format
756 (setq format
757 (if (and (symbolp cite-format-value)
3666daf6
CD
758 (assq cite-format-value reftex-cite-format-builtin))
759 (nth 2 (assq cite-format-value reftex-cite-format-builtin))
760 cite-format-value))
1a9461d0 761 (when (listp format)
3666daf6
CD
762 (setq key
763 (or format-key
7b07114a 764 (reftex-select-with-char
3666daf6
CD
765 "" (concat "SELECT A CITATION FORMAT\n\n"
766 (mapconcat
767 (lambda (x)
768 (format "[%c] %s %s" (car x)
769 (if (> (car x) 31) " " "")
770 (cdr x)))
771 format "\n")))))
772 (if (assq key format)
773 (setq format (cdr (assq key format)))
774 (error "No citation format associated with key `%c'" key)))))
1a9461d0
CD
775 format))
776
7c4d13cc
CD
777(defun reftex-citep ()
778 "Call `reftex-citation' with a format selector `?p'."
779 (interactive)
780 (reftex-citation nil ?p))
781
782(defun reftex-citet ()
783 "Call `reftex-citation' with a format selector `?t'."
784 (interactive)
785 (reftex-citation nil ?t))
786
1a9461d0
CD
787(defvar reftex-select-bib-map)
788(defun reftex-offer-bib-menu ()
789 ;; Offer bib menu and return list of selected items
790
20cd3579 791 (let ((bibtype (reftex-bib-or-thebib))
3666daf6 792 found-list rtn key data selected-entries)
7b07114a
CD
793 (while
794 (not
3666daf6
CD
795 (catch 'done
796 ;; Scan bibtex files
797 (setq found-list
798 (cond
799 ((eq bibtype 'bib)
800; ((assq 'bib (symbol-value reftex-docstruct-symbol))
801 ;; using BibTeX database files.
802 (reftex-extract-bib-entries (reftex-get-bibfile-list)))
803 ((eq bibtype 'thebib)
804; ((assq 'thebib (symbol-value reftex-docstruct-symbol))
805 ;; using thebibliography environment.
806 (reftex-extract-bib-entries-from-thebibliography
807 (reftex-uniquify
808 (mapcar 'cdr
7b07114a 809 (reftex-all-assq
3666daf6
CD
810 'thebib (symbol-value reftex-docstruct-symbol))))))
811 (reftex-default-bibliography
812 (message "Using default bibliography")
813 (reftex-extract-bib-entries (reftex-default-bibliography)))
814 (t (error "No valid bibliography in this document, and no default available"))))
7b07114a 815
3666daf6
CD
816 (unless found-list
817 (error "Sorry, no matches found"))
7b07114a 818
3666daf6
CD
819 ;; Remember where we came from
820 (setq reftex-call-back-to-this-buffer (current-buffer))
821 (set-marker reftex-select-return-marker (point))
7b07114a 822
3666daf6
CD
823 ;; Offer selection
824 (save-window-excursion
825 (delete-other-windows)
826 (let ((default-major-mode 'reftex-select-bib-mode))
827 (reftex-kill-buffer "*RefTeX Select*")
828 (switch-to-buffer-other-window "*RefTeX Select*")
829 (unless (eq major-mode 'reftex-select-bib-mode)
830 (reftex-select-bib-mode))
831 (let ((buffer-read-only nil))
832 (erase-buffer)
833 (reftex-insert-bib-matches found-list)))
834 (setq buffer-read-only t)
835 (if (= 0 (buffer-size))
836 (error "No matches found"))
837 (setq truncate-lines t)
838 (goto-char 1)
839 (while t
840 (setq rtn
841 (reftex-select-item
842 reftex-citation-prompt
843 reftex-citation-help
844 reftex-select-bib-map
845 nil
846 'reftex-bibtex-selection-callback nil))
847 (setq key (car rtn)
848 data (nth 1 rtn))
849 (unless key (throw 'done t))
850 (cond
851 ((eq key ?g)
852 ;; Start over
853 (throw 'done nil))
854 ((eq key ?r)
855 ;; Restrict with new regular expression
856 (setq found-list (reftex-restrict-bib-matches found-list))
857 (let ((buffer-read-only nil))
858 (erase-buffer)
859 (reftex-insert-bib-matches found-list))
860 (goto-char 1))
861 ((eq key ?A)
862 ;; Take all (marked)
7b07114a 863 (setq selected-entries
3666daf6
CD
864 (if reftex-select-marked
865 (mapcar 'car (nreverse reftex-select-marked))
866 found-list))
867 (throw 'done t))
868 ((eq key ?a)
869 ;; Take all (marked), and push the symbol 'concat
7b07114a
CD
870 (setq selected-entries
871 (cons 'concat
3666daf6
CD
872 (if reftex-select-marked
873 (mapcar 'car (nreverse reftex-select-marked))
874 found-list)))
875 (throw 'done t))
f3c18bd0
CD
876 ((eq key ?e)
877 ;; Take all (marked), and push the symbol 'concat
878 (reftex-extract-bib-file found-list reftex-select-marked)
879 (setq selected-entries "BibTeX database file created")
880 (throw 'done t))
881 ((eq key ?E)
882 ;; Take all (marked), and push the symbol 'concat
883 (reftex-extract-bib-file found-list reftex-select-marked
884 'complement)
885 (setq selected-entries "BibTeX database file created")
886 (throw 'done t))
3666daf6
CD
887 ((or (eq key ?\C-m)
888 (eq key 'return))
889 ;; Take selected
7b07114a 890 (setq selected-entries
3666daf6 891 (if reftex-select-marked
7b07114a 892 (cons 'concat
3666daf6
CD
893 (mapcar 'car (nreverse reftex-select-marked)))
894 (if data (list data) nil)))
895 (throw 'done t))
896 ((stringp key)
897 ;; Got this one with completion
898 (setq selected-entries key)
899 (throw 'done t))
900 (t
901 (ding))))))))
1a9461d0
CD
902 selected-entries))
903
904(defun reftex-restrict-bib-matches (found-list)
905 ;; Limit FOUND-LIST with more regular expressions
906 (let ((re-list (split-string (read-string
3666daf6
CD
907 "RegExp [ && RegExp...]: "
908 nil 'reftex-cite-regexp-hist)
909 "[ \t]*&&[ \t]*"))
910 (found-list-r found-list)
911 re)
1a9461d0
CD
912 (while (setq re (pop re-list))
913 (setq found-list-r
3666daf6
CD
914 (delq nil
915 (mapcar
916 (lambda (x)
917 (if (string-match
918 re (cdr (assoc "&entry" x)))
919 x
920 nil))
921 found-list-r))))
1a9461d0 922 (if found-list-r
3666daf6 923 found-list-r
1a9461d0
CD
924 (ding)
925 found-list)))
926
f3c18bd0
CD
927(defun reftex-extract-bib-file (all &optional marked complement)
928 ;; Limit FOUND-LIST with more regular expressions
929 (let ((file (read-file-name "File to create: ")))
930 (find-file-other-window file)
931 (if (> (buffer-size) 0)
7b07114a 932 (unless (yes-or-no-p
f3c18bd0
CD
933 (format "Overwrite non-empty file %s? " file))
934 (error "Abort")))
935 (erase-buffer)
936 (setq all (delq nil
937 (mapcar
938 (lambda (x)
939 (if marked
940 (if (or (and (assoc x marked) (not complement))
941 (and (not (assoc x marked)) complement))
942 (cdr (assoc "&entry" x))
943 nil)
944 (cdr (assoc "&entry" x))))
945 all)))
946 (insert (mapconcat 'identity all "\n\n"))
947 (save-buffer)
948 (goto-char (point-min))))
949
1a9461d0
CD
950(defun reftex-insert-bib-matches (list)
951 ;; Insert the bib matches and number them correctly
952 (let ((mouse-face
3666daf6
CD
953 (if (memq reftex-highlight-selection '(mouse both))
954 reftex-mouse-selected-face
955 nil))
956 tmp len)
551e625f 957 (mapc
1a9461d0
CD
958 (lambda (x)
959 (setq tmp (cdr (assoc "&formatted" x))
3666daf6 960 len (length tmp))
1a9461d0
CD
961 (put-text-property 0 len :data x tmp)
962 (put-text-property 0 (1- len) 'mouse-face mouse-face tmp)
963 (insert tmp))
964 list))
965 (run-hooks 'reftex-display-copied-context-hook))
966
967(defun reftex-format-names (namelist n)
968 (let (last (len (length namelist)))
6fbeb429 969 (if (= n 0) (setq n len))
1a9461d0
CD
970 (cond
971 ((< len 1) "")
972 ((= 1 len) (car namelist))
973 ((> len n) (concat (car namelist) (nth 2 reftex-cite-punctuation)))
974 (t
975 (setq n (min len n)
976 last (nth (1- n) namelist))
977 (setcdr (nthcdr (- n 2) namelist) nil)
978 (concat
979 (mapconcat 'identity namelist (nth 0 reftex-cite-punctuation))
980 (nth 1 reftex-cite-punctuation)
981 last)))))
982
983(defun reftex-format-citation (entry format)
984 ;; Format a citation from the info in the BibTeX ENTRY
985
986 (unless (stringp format) (setq format "\\cite{%l}"))
987
988 (if (and reftex-comment-citations
989 (string-match "%l" reftex-cite-comment-format))
5181ff9f 990 (error "reftex-cite-comment-format contains invalid %%l"))
1a9461d0
CD
991
992 (while (string-match
993 "\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
994 format)
027a4b6b 995 (let ((n (string-to-number (match-string 4 format)))
1a9461d0
CD
996 (l (string-to-char (match-string 5 format)))
997 rpl b e)
998 (save-match-data
999 (setq rpl
1000 (cond
1001 ((= l ?l) (concat
1002 (reftex-get-bib-field "&key" entry)
1003 (if reftex-comment-citations
1004 reftex-cite-comment-format
1005 "")))
1006 ((= l ?a) (reftex-format-names
1007 (reftex-get-bib-names "author" entry)
1008 (or n 2)))
1009 ((= l ?A) (car (reftex-get-bib-names "author" entry)))
1010 ((= l ?b) (reftex-get-bib-field "booktitle" entry "in: %s"))
1011 ((= l ?B) (reftex-abbreviate-title
3666daf6 1012 (reftex-get-bib-field "booktitle" entry "in: %s")))
1a9461d0
CD
1013 ((= l ?c) (reftex-get-bib-field "chapter" entry))
1014 ((= l ?d) (reftex-get-bib-field "edition" entry))
1015 ((= l ?e) (reftex-format-names
1016 (reftex-get-bib-names "editor" entry)
1017 (or n 2)))
1018 ((= l ?E) (car (reftex-get-bib-names "editor" entry)))
1019 ((= l ?h) (reftex-get-bib-field "howpublished" entry))
1020 ((= l ?i) (reftex-get-bib-field "institution" entry))
1021 ((= l ?j) (reftex-get-bib-field "journal" entry))
1022 ((= l ?k) (reftex-get-bib-field "key" entry))
1023 ((= l ?m) (reftex-get-bib-field "month" entry))
1024 ((= l ?n) (reftex-get-bib-field "number" entry))
1025 ((= l ?o) (reftex-get-bib-field "organization" entry))
1026 ((= l ?p) (reftex-get-bib-field "pages" entry))
1027 ((= l ?P) (car (split-string
1028 (reftex-get-bib-field "pages" entry)
1029 "[- .]+")))
1030 ((= l ?s) (reftex-get-bib-field "school" entry))
1031 ((= l ?u) (reftex-get-bib-field "publisher" entry))
1032 ((= l ?r) (reftex-get-bib-field "address" entry))
1033 ((= l ?t) (reftex-get-bib-field "title" entry))
1034 ((= l ?T) (reftex-abbreviate-title
3666daf6 1035 (reftex-get-bib-field "title" entry)))
1a9461d0
CD
1036 ((= l ?v) (reftex-get-bib-field "volume" entry))
1037 ((= l ?y) (reftex-get-bib-field "year" entry)))))
1038
1039 (if (string= rpl "")
1040 (setq b (match-beginning 2) e (match-end 2))
1041 (setq b (match-beginning 3) e (match-end 3)))
1042 (setq format (concat (substring format 0 b) rpl (substring format e)))))
1043 (while (string-match "%%" format)
1044 (setq format (replace-match "%" t t format)))
1045 (while (string-match "[ ,.;:]*%<" format)
1046 (setq format (replace-match "" t t format)))
1047 format)
1048
1049(defun reftex-make-cite-echo-string (entry docstruct-symbol)
1050 ;; Format a bibtex entry for the echo area and cache the result.
1051 (let* ((key (reftex-get-bib-field "&key" entry))
7b07114a 1052 (string
3666daf6
CD
1053 (let* ((reftex-cite-punctuation '(" " " & " " etal.")))
1054 (reftex-format-citation entry reftex-cite-view-format)))
1055 (cache (assq 'bibview-cache (symbol-value docstruct-symbol)))
1056 (cache-entry (assoc key (cdr cache))))
1a9461d0
CD
1057 (unless cache
1058 ;; This docstruct has no cache - make one.
1059 (set docstruct-symbol (cons (cons 'bibview-cache nil)
3666daf6 1060 (symbol-value docstruct-symbol))))
1a9461d0
CD
1061 (when reftex-cache-cite-echo
1062 (setq key (copy-sequence key))
1063 (set-text-properties 0 (length key) nil key)
1064 (set-text-properties 0 (length string) nil string)
1065 (if cache-entry
3666daf6
CD
1066 (unless (string= (cdr cache-entry) string)
1067 (setcdr cache-entry string)
1068 (put reftex-docstruct-symbol 'modified t))
1069 (push (cons key string) (cdr cache))
1070 (put reftex-docstruct-symbol 'modified t)))
1a9461d0
CD
1071 string))
1072
1073(defun reftex-bibtex-selection-callback (data ignore no-revisit)
1074 ;; Callback function to be called from the BibTeX selection, in
1075 ;; order to display context. This function is relatively slow and not
1076 ;; recommended for follow mode. It works OK for individual lookups.
1077 (let ((win (selected-window))
1078 (key (reftex-get-bib-field "&key" data))
20cd3579 1079 bibfile-list item bibtype)
1a9461d0
CD
1080
1081 (catch 'exit
1082 (save-excursion
3666daf6
CD
1083 (set-buffer reftex-call-back-to-this-buffer)
1084 (setq bibtype (reftex-bib-or-thebib))
1085 (cond
1086 ((eq bibtype 'bib)
1087; ((assq 'bib (symbol-value reftex-docstruct-symbol))
1088 (setq bibfile-list (reftex-get-bibfile-list)))
1089 ((eq bibtype 'thebib)
1090; ((assq 'thebib (symbol-value reftex-docstruct-symbol))
1091 (setq bibfile-list
1092 (reftex-uniquify
1093 (mapcar 'cdr
7b07114a 1094 (reftex-all-assq
3666daf6
CD
1095 'thebib (symbol-value reftex-docstruct-symbol))))
1096 item t))
1097 (reftex-default-bibliography
1098 (setq bibfile-list (reftex-default-bibliography)))
1099 (t (ding) (throw 'exit nil))))
1a9461d0
CD
1100
1101 (when no-revisit
3666daf6 1102 (setq bibfile-list (reftex-visited-files bibfile-list)))
1a9461d0
CD
1103
1104 (condition-case nil
7b07114a 1105 (reftex-pop-to-bibtex-entry
3666daf6
CD
1106 key bibfile-list (not reftex-keep-temporary-buffers) t item)
1107 (error (ding))))
7b07114a 1108
1a9461d0
CD
1109 (select-window win)))
1110
f3c18bd0
CD
1111;;; Global BibTeX file
1112(defun reftex-all-used-citation-keys ()
1113 (reftex-access-scan-info)
7b07114a 1114 (let ((files (reftex-all-document-files)) file keys kk k)
f3c18bd0
CD
1115 (save-excursion
1116 (while (setq file (pop files))
1117 (set-buffer (reftex-get-file-buffer-force file 'mark))
1118 (save-excursion
1119 (save-restriction
1120 (widen)
1121 (goto-char (point-min))
1122 (while (re-search-forward "^[^%\n\r]*\\\\\\(bibentry\\|[a-zA-Z]*cite[a-zA-Z]*\\)\\(\\[[^\\]]*\\]\\)?{\\([^}]+\\)}" nil t)
1123 (setq kk (match-string-no-properties 3))
1124 (while (string-match "%.*\n?" kk)
1125 (setq kk (replace-match "" t t kk)))
1126 (setq kk (split-string kk "[, \t\r\n]+"))
1127 (while (setq k (pop kk))
1128 (or (member k keys)
1129 (setq keys (cons k keys)))))))))
1130 (reftex-kill-temporary-buffers)
1131 keys))
1132
1133(defun reftex-create-bibtex-file (bibfile)
1134 "Create a new BibTeX database file with all entries referenced in document.
1135The command prompts for a filename and writes the collected entries to
1136that file. Only entries referenced in the current document with
7b07114a 1137any \\cite-like macros are used.
f3c18bd0
CD
1138The sequence in the new file is the same as it was in the old database."
1139 (interactive "FNew BibTeX file: ")
1140 (let ((keys (reftex-all-used-citation-keys))
1141 (files (reftex-get-bibfile-list))
1142 file key entries beg end entry)
1143 (save-excursion
1144 (while (setq file (pop files))
1145 (set-buffer (reftex-get-file-buffer-force file 'mark))
1146 (reftex-with-special-syntax-for-bib
1147 (save-excursion
1148 (save-restriction
1149 (widen)
1150 (goto-char (point-min))
7b07114a 1151 (while (re-search-forward
f3c18bd0
CD
1152 "^[ \t]*@[a-zA-Z]+[ \t]*{\\([^ \t\r\n]+\\),"
1153 nil t)
1154 (setq key (match-string 1)
1155 beg (match-beginning 0)
1156 end (progn
1157 (goto-char (match-beginning 1))
1158 (condition-case nil
1159 (up-list 1)
1160 (error (goto-char (match-end 0))))
1161 (point)))
1162 (when (member key keys)
1163 (setq entry (buffer-substring beg end)
1164 entries (cons entry entries)
1165 keys (delete key keys)))))))))
1166 (find-file-other-window bibfile)
1167 (if (> (buffer-size) 0)
7b07114a 1168 (unless (yes-or-no-p
f3c18bd0
CD
1169 (format "Overwrite non-empty file %s? " bibfile))
1170 (error "Abort")))
1171 (erase-buffer)
1172 (insert (mapconcat 'identity (reverse entries) "\n\n"))
1173 (goto-char (point-min))
1174 (save-buffer)
1175 (message "%d entries extracted and copied to new database"
1176 (length entries))))
1177
1178
cbee283d 1179;; arch-tag: d53d0a5a-ab32-4b52-a846-2a7c3527cd89
1a9461d0 1180;;; reftex-cite.el ends here