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