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