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