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