comparison lisp/textmodes/reftex-cite.el @ 25280:9b601931b795

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