]> code.delx.au - gnu-emacs/blob - lisp/textmodes/reftex-ref.el
Merge from emacs-24
[gnu-emacs] / lisp / textmodes / reftex-ref.el
1 ;;; reftex-ref.el --- code to create labels and references with RefTeX
2
3 ;; Copyright (C) 1997-2012 Free Software Foundation, Inc.
4
5 ;; Author: Carsten Dominik <dominik@science.uva.nl>
6 ;; Maintainer: auctex-devel@gnu.org
7 ;; Version: 4.31
8 ;; Package: reftex
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 3 of the License, or
15 ;; (at your option) 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. If not, see <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26
27 ;;; Code:
28
29 (eval-when-compile (require 'cl))
30 (provide 'reftex-ref)
31 (require 'reftex)
32 (require 'reftex-parse)
33 ;;;
34
35 (defun reftex-label-location (&optional bound)
36 "Return the environment or macro which determines the label type at point.
37 If optional BOUND is an integer, limit backward searches to that point."
38
39 (let* ((loc1 (reftex-what-macro reftex-label-mac-list bound))
40 (loc2 (reftex-what-environment reftex-label-env-list bound))
41 (loc3 (reftex-what-special-env 1 bound))
42 (p1 (or (cdr loc1) 0))
43 (p2 (or (cdr loc2) 0))
44 (p3 (or (cdr loc3) 0))
45 (pmax (max p1 p2 p3)))
46
47 (setq reftex-location-start pmax)
48 (cond
49 ((= p1 pmax)
50 ;; A macro. Default context after macro name.
51 (setq reftex-default-context-position (+ p1 (length (car loc1))))
52 (or (car loc1) "section"))
53 ((= p2 pmax)
54 ;; An environment. Default context after \begin{name}.
55 (setq reftex-default-context-position (+ p2 8 (length (car loc2))))
56 (or (car loc2) "section"))
57 ((= p3 pmax)
58 ;; A special. Default context right there.
59 (setq reftex-default-context-position p3)
60 (setq loc3 (car loc3))
61 (cond ((null loc3) "section")
62 ((symbolp loc3) (symbol-name loc3))
63 ((stringp loc3) loc3)
64 (t "section")))
65 (t ;; This should not happen, I think?
66 "section"))))
67
68 (defun reftex-label-info-update (cell)
69 ;; Update information about just one label in a different file.
70 ;; CELL contains the old info list
71 (let* ((label (nth 0 cell))
72 (typekey (nth 1 cell))
73 ;; (text (nth 2 cell))
74 (file (nth 3 cell))
75 (comment (nth 4 cell))
76 (note (nth 5 cell))
77 (buf (reftex-get-file-buffer-force
78 file (not (eq t reftex-keep-temporary-buffers)))))
79 (if (not buf)
80 (list label typekey "" file comment "LOST LABEL. RESCAN TO FIX.")
81 (with-current-buffer buf
82 (save-restriction
83 (widen)
84 (goto-char 1)
85
86 (if (or (re-search-forward
87 (format reftex-find-label-regexp-format
88 (regexp-quote label)) nil t)
89 (re-search-forward
90 (format reftex-find-label-regexp-format2
91 (regexp-quote label)) nil t))
92
93 (progn
94 (backward-char 1)
95 (append (reftex-label-info label file) (list note)))
96 (list label typekey "" file "LOST LABEL. RESCAN TO FIX.")))))))
97
98 (defun reftex-label-info (label &optional file bound derive env-or-mac)
99 ;; Return info list on LABEL at point.
100 (let* ((prefix (if (string-match "^[a-zA-Z0-9]+:" label)
101 (match-string 0 label)))
102 (typekey (cdr (assoc prefix reftex-prefix-to-typekey-alist)))
103 (file (or file (buffer-file-name)))
104 (trust reftex-trust-label-prefix)
105 (in-comment (reftex-in-comment)))
106 (if (and typekey
107 (cond ((eq trust t) t)
108 ((null trust) nil)
109 ((stringp trust) (string-match trust typekey))
110 ((listp trust) (member typekey trust))
111 (t nil)))
112 (list label typekey
113 (reftex-nicify-text (reftex-context-substring))
114 file in-comment)
115 (let* ((env-or-mac (or env-or-mac (reftex-label-location bound)))
116 (typekey (nth 1 (assoc env-or-mac reftex-env-or-mac-alist)))
117 (parse (nth 2 (assoc env-or-mac reftex-env-or-mac-alist)))
118 (text (reftex-short-context env-or-mac parse reftex-location-start
119 derive)))
120 (list label typekey text file in-comment)))))
121
122 ;;; Creating labels ---------------------------------------------------------
123
124 (defun reftex-label (&optional environment no-insert)
125 "Insert a unique label. Return the label.
126 If ENVIRONMENT is given, don't bother to find out yourself.
127 If NO-INSERT is non-nil, do not insert label into buffer.
128 With prefix arg, force to rescan document first.
129 When you are prompted to enter or confirm a label, and you reply with
130 just the prefix or an empty string, no label at all will be inserted.
131 A new label is also recorded into the label list.
132 This function is controlled by the settings of reftex-insert-label-flags."
133
134 (interactive)
135
136 ;; Ensure access to scanning info and rescan buffer if prefix are is '(4).
137 (reftex-access-scan-info current-prefix-arg)
138
139 ;; Find out what kind of environment this is and abort if necessary.
140 (if (or (not environment)
141 (not (assoc environment reftex-env-or-mac-alist)))
142 (setq environment (reftex-label-location)))
143 (unless environment
144 (error "Can't figure out what kind of label should be inserted"))
145
146 ;; Ok, go ahead.
147 (catch 'exit
148 (let* ((entry (assoc environment reftex-env-or-mac-alist))
149 (typekey (nth 1 entry))
150 (format (nth 3 entry))
151 (macro-cell (reftex-what-macro 1))
152 (entry1 (assoc (car macro-cell) reftex-env-or-mac-alist))
153 label naked prefix valid default force-prompt rescan-is-useful)
154 (when (and (or (nth 5 entry) (nth 5 entry1))
155 (memq (preceding-char) '(?\[ ?\{)))
156 ;; This is an argument of a label macro. Insert naked label.
157 (setq naked t format "%s"))
158
159 (setq prefix (or (cdr (assoc typekey reftex-typekey-to-prefix-alist))
160 (concat typekey "-")))
161 ;; Replace any escapes in the prefix
162 (setq prefix (reftex-replace-prefix-escapes prefix))
163
164 ;; Make a default label.
165 (cond
166
167 ((reftex-typekey-check typekey (nth 0 reftex-insert-label-flags))
168 ;; Derive a label from context.
169 (setq reftex-active-toc (reftex-last-assoc-before-elt
170 'toc (car (reftex-where-am-I))
171 (symbol-value reftex-docstruct-symbol)))
172 (setq default (reftex-no-props
173 (nth 2 (reftex-label-info " " nil nil t))))
174 ;; Catch the cases where the is actually no context available.
175 (if (or (string-match "NO MATCH FOR CONTEXT REGEXP" default)
176 (string-match "INVALID VALUE OF PARSE" default)
177 (string-match "SECTION HEADING NOT FOUND" default)
178 (string-match "HOOK ERROR" default)
179 (string-match "^[ \t]*$" default))
180 (setq default prefix
181 force-prompt t) ; need to prompt
182 (setq default
183 (concat prefix
184 (funcall reftex-string-to-label-function default)))
185
186 ;; Make it unique.
187 (setq default (reftex-uniquify-label default nil "-"))))
188
189 ((reftex-typekey-check typekey (nth 1 reftex-insert-label-flags))
190 ;; Minimal default: the user will be prompted.
191 (setq default prefix))
192
193 (t
194 ;; Make an automatic label.
195 (setq default (reftex-uniquify-label prefix t))))
196
197 ;; Should we ask the user?
198 (if (or (reftex-typekey-check typekey
199 (nth 1 reftex-insert-label-flags)) ; prompt
200 force-prompt)
201
202 (while (not valid)
203 ;; iterate until we get a valid label
204
205 (setq label (read-string
206 (if naked "Naked Label: " "Label: ")
207 default))
208
209 ;; Let's make sure that this is a valid label
210 (cond
211
212 ((string-match (concat "\\`\\(" (regexp-quote prefix)
213 "\\)?[ \t]*\\'")
214 label)
215 ;; No label at all, please
216 (message "No label inserted.")
217 (throw 'exit nil))
218
219 ;; Test if label contains strange characters
220 ((string-match reftex-label-illegal-re label)
221 (message "Label \"%s\" contains invalid characters" label)
222 (ding)
223 (sit-for 2))
224
225 ;; Look it up in the label list
226 ((setq entry (assoc label
227 (symbol-value reftex-docstruct-symbol)))
228 (ding)
229 (if (y-or-n-p
230 (format "Label '%s' exists. Use anyway? " label))
231 (setq valid t)))
232
233 ;; Label is ok
234 (t
235 (setq valid t))))
236 (setq label default))
237
238 ;; Insert the label into the label list
239 (let* ((here-I-am-info
240 (save-excursion
241 (if (and (or naked no-insert)
242 (integerp (cdr macro-cell)))
243 (goto-char (cdr macro-cell)))
244 (reftex-where-am-I)))
245 (here-I-am (car here-I-am-info))
246 (note (if (cdr here-I-am-info)
247 ""
248 "POSITION UNCERTAIN. RESCAN TO FIX."))
249 (file (buffer-file-name))
250 (text nil)
251 (tail (memq here-I-am (symbol-value reftex-docstruct-symbol))))
252
253 (or (cdr here-I-am-info) (setq rescan-is-useful t))
254
255 (when tail
256 (push (list label typekey text file nil note) (cdr tail))
257 (put reftex-docstruct-symbol 'modified t)))
258
259 ;; Insert the label into the buffer
260 (unless no-insert
261 (insert
262 (if reftex-format-label-function
263 (funcall reftex-format-label-function label format)
264 (format format label)))
265 (if (and reftex-plug-into-AUCTeX
266 (fboundp 'LaTeX-add-labels))
267 ;; Tell AUCTeX about this
268 (LaTeX-add-labels label)))
269
270 ;; Delete the corresponding selection buffers to force update on next use.
271 (when reftex-auto-update-selection-buffers
272 (reftex-erase-buffer (reftex-make-selection-buffer-name typekey))
273 (reftex-erase-buffer (reftex-make-selection-buffer-name " ")))
274
275 (when (and rescan-is-useful reftex-allow-automatic-rescan)
276 (reftex-parse-one))
277
278 ;; return value of the function is the label
279 label)))
280
281 (defun reftex-string-to-label (string)
282 "Convert a string (a sentence) to a label.
283 Uses `reftex-derive-label-parameters' and `reftex-label-illegal-re'. It
284 also applies `reftex-translate-to-ascii-function' to the string."
285 (when (and reftex-translate-to-ascii-function
286 (fboundp reftex-translate-to-ascii-function))
287 (setq string (funcall reftex-translate-to-ascii-function string)))
288 (apply 'reftex-convert-string string
289 "[-~ \t\n\r,;]+" reftex-label-illegal-re nil nil
290 reftex-derive-label-parameters))
291
292 (defun reftex-latin1-to-ascii (string)
293 ;; Translate the upper 128 chars in the Latin-1 charset to ASCII equivalents
294 (let ((tab "@@@@@@@@@@@@@@@@@@'@@@@@@@@@@@@@ icLxY|S\"ca<--R-o|23'uq..1o>423?AAAAAAACEEEEIIIIDNOOOOOXOUUUUYP3aaaaaaaceeeeiiiidnooooo:ouuuuypy")
295 (emacsp (not (featurep 'xemacs))))
296 (mapconcat
297 (lambda (c)
298 (cond ((and (> c 127) (< c 256)) ; 8 bit Latin-1
299 (char-to-string (aref tab (- c 128))))
300 ((and emacsp ; Not for XEmacs
301 (> c 2175) (< c 2304)) ; Mule Latin-1
302 (char-to-string (aref tab (- c 2176))))
303 (t (char-to-string c))))
304 string "")))
305
306 (defun reftex-replace-prefix-escapes (prefix)
307 ;; Replace %escapes in a label prefix
308 (save-match-data
309 (let (letter (num 0) replace)
310 (while (string-match "\\%\\([a-zA-Z]\\)" prefix num)
311 (setq letter (match-string 1 prefix))
312 (setq replace
313 (save-match-data
314 (cond
315 ((equal letter "f")
316 (file-name-base))
317 ((equal letter "F")
318 (let ((masterdir (file-name-directory (reftex-TeX-master-file)))
319 (file (file-name-sans-extension (buffer-file-name))))
320 (if (string-match (concat "\\`" (regexp-quote masterdir))
321 file)
322 (substring file (length masterdir))
323 file)))
324 ((equal letter "m")
325 (file-name-base (reftex-TeX-master-file)))
326 ((equal letter "M")
327 (file-name-nondirectory
328 (substring (file-name-directory (reftex-TeX-master-file))
329 0 -1)))
330 ((equal letter "u")
331 (or (user-login-name) ""))
332 ((equal letter "S")
333 (let* (macro level-exp level)
334 (save-excursion
335 (save-match-data
336 (when (re-search-backward reftex-section-regexp nil t)
337 (setq macro (reftex-match-string 2)
338 level-exp (cdr (assoc macro reftex-section-levels-all))
339 level (if (symbolp level-exp)
340 (abs (save-match-data
341 (funcall level-exp)))
342 (abs level-exp))))
343 (cdr (or (assoc macro reftex-section-prefixes)
344 (assoc level reftex-section-prefixes)
345 (assq t reftex-section-prefixes)
346 (list t "sec:")))))))
347 (t ""))))
348 (setq num (1- (+ (match-beginning 1) (length replace)))
349 prefix (replace-match replace nil nil prefix)))
350 prefix)))
351
352 (defun reftex-uniquify-label (label &optional force separator)
353 ;; Make label unique by appending a number.
354 ;; Optional FORCE means, force appending a number, even if label is unique.
355 ;; Optional SEPARATOR is a string to stick between label and number.
356
357 ;; Ensure access to scanning info
358 (reftex-access-scan-info)
359
360 (cond
361 ((and (not force)
362 (not (assoc label (symbol-value reftex-docstruct-symbol))))
363 label)
364 (t
365 (let* ((label-numbers (assq 'label-numbers
366 (symbol-value reftex-docstruct-symbol)))
367 (label-numbers-alist (cdr label-numbers))
368 (cell (or (assoc label label-numbers-alist)
369 (car (setcdr label-numbers
370 (cons (cons label 0)
371 label-numbers-alist)))))
372 (num (1+ (cdr cell)))
373 (sep (or separator "")))
374 (while (assoc (concat label sep (int-to-string num))
375 (symbol-value reftex-docstruct-symbol))
376 (incf num))
377 (setcdr cell num)
378 (concat label sep (int-to-string num))))))
379
380 ;;; Referencing labels ------------------------------------------------------
381
382 ;; Help string for the reference label menu
383 (defconst reftex-select-label-prompt
384 "Select: [n]ext [p]revious [r]escan [ ]context e[x]tern [q]uit RET [?]HELP+more")
385
386 (defconst reftex-select-label-help
387 " n / p Go to next/previous label (Cursor motion works as well)
388 C-c C-n/p Go to next/previous section heading.
389 b / l Jump back to previous selection / Reuse last referenced label.
390 z Jump to a specific section, e.g. '3 z' jumps to section 3.
391 g / s Update menu / Switch label type.
392 r / C-u r Reparse document / Reparse entire document.
393 x Switch to label menu of external document (with LaTeX package `xr').
394 F t c Toggle: [F]ile borders, [t]able of contents, [c]ontext
395 # % Toggle: [#] label counters, [%] labels in comments
396 SPC / f Show full context in other window / Toggle follow mode.
397 . Show insertion point in other window.
398 v / V Toggle \\ref <-> \\vref / Rotate \\ref <=> \\fref <=> \\Fref
399 TAB Enter a label with completion.
400 m , - + Mark entry. `,-+' also assign a separator.
401 a / A Put all marked entries into one/many \\ref commands.
402 q / RET Quit without referencing / Accept current label (also on mouse-2).")
403
404 (defun reftex-reference (&optional type no-insert cut)
405 "Make a LaTeX reference. Look only for labels of a certain TYPE.
406 With prefix arg, force to rescan buffer for labels. This should only be
407 necessary if you have recently entered labels yourself without using
408 reftex-label. Rescanning of the buffer can also be requested from the
409 label selection menu.
410 The function returns the selected label or nil.
411 If NO-INSERT is non-nil, do not insert \\ref command, just return label.
412 When called with 2 C-u prefix args, disable magic word recognition."
413
414 (interactive)
415
416 ;; check for active recursive edits
417 (reftex-check-recursive-edit)
418
419 ;; Ensure access to scanning info and rescan buffer if prefix are is '(4)
420 (reftex-access-scan-info current-prefix-arg)
421
422 (unless type
423 ;; guess type from context
424 (if (and reftex-guess-label-type
425 (setq type (reftex-guess-label-type)))
426 (setq cut (cdr type)
427 type (car type))
428 (setq type (reftex-query-label-type))))
429
430 (let* ((reftex-refstyle
431 (cond ((reftex-typekey-check type reftex-vref-is-default) "\\vref")
432 ((reftex-typekey-check type reftex-fref-is-default) "\\fref")
433 (t "\\ref")))
434 (reftex-format-ref-function reftex-format-ref-function)
435 (form "\\ref{%s}")
436 label labels sep sep1)
437
438 ;; Have the user select a label
439 (set-marker reftex-select-return-marker (point))
440 (setq labels (save-excursion
441 (reftex-offer-label-menu type)))
442 (reftex-ensure-compiled-variables)
443 (set-marker reftex-select-return-marker nil)
444 ;; If the first entry is the symbol 'concat, concat all labels.
445 ;; We keep the cdr of the first label for typekey etc information.
446 (if (eq (car labels) 'concat)
447 (setq labels (list (list (mapconcat 'car (cdr labels) ",")
448 (cdr (nth 1 labels))))))
449 (setq type (nth 1 (car labels))
450 form (or (cdr (assoc type reftex-typekey-to-format-alist))
451 form))
452
453 (cond
454 (no-insert
455 ;; Just return the first label
456 (car (car labels)))
457 ((null labels)
458 (message "Quit")
459 nil)
460 (t
461 (while labels
462 (setq label (car (car labels))
463 sep (nth 2 (car labels))
464 sep1 (cdr (assoc sep reftex-multiref-punctuation))
465 labels (cdr labels))
466 (when cut
467 (backward-delete-char cut)
468 (setq cut nil))
469
470 ;; remove ~ if we do already have a space
471 (when (and (= ?~ (string-to-char form))
472 (member (preceding-char) '(?\ ?\t ?\n ?~)))
473 (setq form (substring form 1)))
474 ;; do we have a special format?
475 (setq reftex-format-ref-function
476 (cond
477 ((string= reftex-refstyle "\\vref") 'reftex-format-vref)
478 ((string= reftex-refstyle "\\fref") 'reftex-format-fref)
479 ((string= reftex-refstyle "\\Fref") 'reftex-format-Fref)
480 (t reftex-format-ref-function)))
481 ;; ok, insert the reference
482 (if sep1 (insert sep1))
483 (insert
484 (if reftex-format-ref-function
485 (funcall reftex-format-ref-function label form)
486 (format form label label)))
487 ;; take out the initial ~ for good
488 (and (= ?~ (string-to-char form))
489 (setq form (substring form 1))))
490 (message "")
491 label))))
492
493 (defun reftex-guess-label-type ()
494 ;; Examine context to guess what a \ref might want to reference.
495 (let ((words reftex-words-to-typekey-alist)
496 (case-fold-search t)
497 (bound (max (point-min) (- (point) 35)))
498 matched cell)
499 (save-excursion
500 (while (and (setq cell (pop words))
501 (not (setq matched
502 (re-search-backward (car cell) bound t))))))
503 (if matched
504 (cons (cdr cell) (- (match-end 0) (match-end 1)))
505 nil)))
506
507 (defvar reftex-select-label-map)
508 (defun reftex-offer-label-menu (typekey)
509 ;; Offer a menu with the appropriate labels.
510 (let* ((buf (current-buffer))
511 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol)))
512 (xr-alist (cons (cons "" (buffer-file-name)) (nth 1 xr-data)))
513 (xr-index 0)
514 (here-I-am (car (reftex-where-am-I)))
515 (here-I-am1 here-I-am)
516 (toc (reftex-typekey-check typekey reftex-label-menu-flags 0))
517 (files (reftex-typekey-check typekey reftex-label-menu-flags 7))
518 (context (not (reftex-typekey-check
519 typekey reftex-label-menu-flags 3)))
520 (counter (reftex-typekey-check
521 typekey reftex-label-menu-flags 2))
522 (follow (reftex-typekey-check
523 typekey reftex-label-menu-flags 4))
524 (commented (nth 5 reftex-label-menu-flags))
525 (prefix "")
526 selection-buffers
527 offset rtn key data last-data entries)
528
529 (unwind-protect
530 (catch 'exit
531 (while t
532 (save-window-excursion
533 (delete-other-windows)
534 (setq reftex-call-back-to-this-buffer buf
535 reftex-latex-syntax-table (syntax-table))
536 (if reftex-use-multiple-selection-buffers
537 (switch-to-buffer-other-window
538 (with-current-buffer buf
539 (reftex-make-selection-buffer-name typekey)))
540 (switch-to-buffer-other-window "*RefTeX Select*")
541 (reftex-erase-buffer))
542 (unless (eq major-mode 'reftex-select-label-mode)
543 (reftex-select-label-mode))
544 (add-to-list 'selection-buffers (current-buffer))
545 (setq truncate-lines t)
546 (setq mode-line-format
547 (list "---- " 'mode-line-buffer-identification
548 " " 'global-mode-string " (" mode-name ")"
549 " S<" 'reftex-refstyle ">"
550 " -%-"))
551 (cond
552 ((= 0 (buffer-size))
553 (let ((buffer-read-only nil))
554 (message "Creating Selection Buffer...")
555 (setq offset (reftex-insert-docstruct
556 buf
557 toc
558 typekey
559 nil ; index
560 files
561 context
562 counter
563 commented
564 (or here-I-am offset)
565 prefix
566 nil ; no a toc buffer
567 ))))
568 (here-I-am
569 (setq offset (reftex-get-offset buf here-I-am typekey)))
570 (t (setq offset t)))
571 (setq buffer-read-only t)
572 (setq offset (or offset t))
573
574 (setq here-I-am nil) ; turn off determination of offset
575 (setq rtn
576 (reftex-select-item
577 reftex-select-label-prompt
578 reftex-select-label-help
579 reftex-select-label-map
580 offset
581 'reftex-show-label-location follow))
582 (setq key (car rtn)
583 data (nth 1 rtn)
584 last-data (nth 2 rtn)
585 offset t)
586 (unless key (throw 'exit nil))
587 (cond
588 ((eq key ?g)
589 ;; update buffer
590 (reftex-erase-buffer))
591 ((or (eq key ?r)
592 (eq key ?R))
593 ;; rescan buffer
594 (and current-prefix-arg (setq key ?R))
595 (reftex-erase-buffer)
596 (reftex-reparse-document buf last-data key))
597 ((eq key ?c)
598 ;; toggle context mode
599 (reftex-erase-buffer)
600 (setq context (not context)))
601 ((eq key ?s)
602 ;; switch type
603 (setq here-I-am here-I-am1)
604 (setq typekey (reftex-query-label-type)))
605 ((eq key ?t)
606 ;; toggle table of contents display, or change depth
607 (reftex-erase-buffer)
608 (if current-prefix-arg
609 (setq reftex-toc-max-level (prefix-numeric-value
610 current-prefix-arg))
611 (setq toc (not toc))))
612 ((eq key ?F)
613 ;; toggle display of included file borders
614 (reftex-erase-buffer)
615 (setq files (not files)))
616 ((eq key ?#)
617 ;; toggle counter display
618 (reftex-erase-buffer)
619 (setq counter (not counter)))
620 ((eq key ?%)
621 ;; toggle display of commented labels
622 (reftex-erase-buffer)
623 (setq commented (not commented)))
624 ((eq key ?l)
625 ;; reuse the last referenced label again
626 (setq entries reftex-last-used-reference)
627 (throw 'exit t))
628 ((eq key ?x)
629 ;; select an external document
630 (setq xr-index (reftex-select-external-document
631 xr-alist xr-index))
632 (setq buf (or (reftex-get-file-buffer-force
633 (cdr (nth xr-index xr-alist)))
634 (error "Cannot switch document"))
635 prefix (or (car (nth xr-index xr-alist)) ""))
636 (set-buffer buf)
637 (reftex-access-scan-info))
638 ((stringp key)
639 (setq entries
640 (list
641 (list
642 (or (assoc key (symbol-value reftex-docstruct-symbol))
643 (list key typekey)))))
644 (throw 'exit t))
645 ((memq key '(?a ?A return))
646 (cond
647 (reftex-select-marked
648 (setq entries (nreverse reftex-select-marked)))
649 (data
650 (setq entries (list (list data))))
651 (t (setq entries nil)))
652 (when entries
653 (if (equal key ?a) (push 'concat entries))
654 (setq reftex-last-used-reference entries))
655 (set-buffer buf)
656 (throw 'exit t))
657 (t (error "This should not happen (reftex-offer-label-menu)"))))))
658 (save-excursion
659 (while reftex-buffers-with-changed-invisibility
660 (set-buffer (car (car reftex-buffers-with-changed-invisibility)))
661 (setq buffer-invisibility-spec
662 (cdr (pop reftex-buffers-with-changed-invisibility)))))
663 (mapc (lambda (buf) (and (buffer-live-p buf) (bury-buffer buf)))
664 selection-buffers)
665 (reftex-kill-temporary-buffers))
666 ;; Add the prefixes, put together the relevant information in the form
667 ;; (LABEL TYPEKEY SEPARATOR) and return a list of those.
668 (mapcar (lambda (x)
669 (if (listp x)
670 (list (concat prefix (car (car x)))
671 (nth 1 (car x))
672 (nth 2 x))
673 x))
674 entries)))
675
676 (defun reftex-reparse-document (&optional buffer data key)
677 ;; Rescan the document.
678 (save-window-excursion
679 (save-excursion
680 (if buffer
681 (if (not (bufferp buffer))
682 (error "No such buffer %s" (buffer-name buffer))
683 (set-buffer buffer)))
684 (let ((arg (if (eq key ?R) '(16) '(4)))
685 (file (nth 3 data)))
686 (reftex-access-scan-info arg file)))))
687
688 (defun reftex-query-label-type ()
689 ;; Ask for label type
690 (let ((key (reftex-select-with-char
691 reftex-type-query-prompt reftex-type-query-help 3)))
692 (unless (member (char-to-string key) reftex-typekey-list)
693 (error "No such label type: %s" (char-to-string key)))
694 (char-to-string key)))
695
696 (defun reftex-show-label-location (data forward no-revisit
697 &optional stay error)
698 ;; View the definition site of a label in another window.
699 ;; DATA is an entry from the docstruct list.
700 ;; FORWARD indicates if the label is likely forward from current point.
701 ;; NO-REVISIT means do not load a file to show this label.
702 ;; STAY means leave the new window selected.
703 ;; ERROR means throw an error exception when the label cannot be found.
704 ;; If ERROR is nil, the return value of this function indicates success.
705 (let* ((this-window (selected-window))
706 (errorf (if error 'error 'message))
707 label file buffer re found)
708
709 (catch 'exit
710 (setq label (nth 0 data)
711 file (nth 3 data))
712
713 (unless file
714 (funcall errorf "Unknown label - reparse might help")
715 (throw 'exit nil))
716
717 ;; Goto the file in another window
718 (setq buffer
719 (if no-revisit
720 (reftex-get-buffer-visiting file)
721 (reftex-get-file-buffer-force
722 file (not reftex-keep-temporary-buffers))))
723 (if buffer
724 ;; good - the file is available
725 (switch-to-buffer-other-window buffer)
726 ;; we have got a problem here. The file does not exist.
727 ;; Let' get out of here..
728 (funcall errorf "Label %s not found" label)
729 (throw 'exit nil))
730
731 ;; search for that label
732 (setq re (format reftex-find-label-regexp-format (regexp-quote label)))
733 (setq found
734 (if forward
735 (re-search-forward re nil t)
736 (re-search-backward re nil t)))
737 (unless found
738 (goto-char (point-min))
739 (unless (setq found (re-search-forward re nil t))
740 ;; Ooops. Must be in a macro with distributed args.
741 (setq found
742 (re-search-forward
743 (format reftex-find-label-regexp-format2
744 (regexp-quote label)) nil t))))
745 (if (match-end 3)
746 (progn
747 (reftex-highlight 0 (match-beginning 3) (match-end 3))
748 (reftex-show-entry (match-beginning 3) (match-end 3))
749 (recenter '(4))
750 (unless stay (select-window this-window)))
751 (select-window this-window)
752 (funcall errorf "Label %s not found" label))
753 found)))
754
755 (defvar font-lock-mode)
756 (defun reftex-show-entry (beg-hlt end-hlt)
757 ;; Show entry if point is hidden
758 (let* ((n (/ (reftex-window-height) 2))
759 (beg (save-excursion
760 (re-search-backward "[\n\r]" nil 1 n) (point)))
761 (end (save-excursion
762 (re-search-forward "[\n\r]" nil 1 n) (point))))
763 (cond
764 ((and (boundp 'buffer-invisibility-spec) buffer-invisibility-spec
765 (get-char-property (1+ beg-hlt) 'invisible))
766 ;; Invisible with text properties. That is easy to change.
767 (push (cons (current-buffer) buffer-invisibility-spec)
768 reftex-buffers-with-changed-invisibility)
769 (setq buffer-invisibility-spec nil))
770 ((string-match "\r" (buffer-substring beg end))
771 ;; Invisible with selective display. We need to copy it.
772 (let ((string (buffer-substring-no-properties beg end)))
773 (switch-to-buffer "*RefTeX Context Copy*")
774 (setq buffer-read-only nil)
775 (erase-buffer)
776 (insert string)
777 (subst-char-in-region (point-min) (point-max) ?\r ?\n t)
778 (goto-char (- beg-hlt beg))
779 (reftex-highlight 0 (1+ (- beg-hlt beg)) (1+ (- end-hlt beg)))
780 (if (reftex-refontify)
781 (when (or (not (eq major-mode 'latex-mode))
782 (not font-lock-mode))
783 (latex-mode)
784 (run-hook-with-args
785 'reftex-pre-refontification-functions
786 reftex-call-back-to-this-buffer 'reftex-hidden)
787 (turn-on-font-lock))
788 (when (or (not (eq major-mode 'fundamental-mode))
789 font-lock-mode)
790 (fundamental-mode)))
791 (run-hooks 'reftex-display-copied-context-hook)
792 (setq buffer-read-only t))))))
793
794 (defun reftex-varioref-vref ()
795 "Insert a reference using the `\\vref' macro from the varioref package."
796 (interactive)
797 (let ((reftex-format-ref-function 'reftex-format-vref))
798 (reftex-reference)))
799 (defun reftex-fancyref-fref ()
800 "Insert a reference using the `\\fref' macro from the fancyref package."
801 (interactive)
802 (let ((reftex-format-ref-function 'reftex-format-fref)
803 ;;(reftex-guess-label-type nil) ;FIXME do we want this????
804 )
805 (reftex-reference)))
806 (defun reftex-fancyref-Fref ()
807 "Insert a reference using the `\\Fref' macro from the fancyref package."
808 (interactive)
809 (let ((reftex-format-ref-function 'reftex-format-Fref)
810 ;;(reftex-guess-label-type nil) ;FIXME do we want this????
811 )
812 (reftex-reference)))
813
814 (defun reftex-format-vref (label fmt)
815 (while (string-match "\\\\ref{" fmt)
816 (setq fmt (replace-match "\\vref{" t t fmt)))
817 (format fmt label label))
818 (defun reftex-format-Fref (label def-fmt)
819 (format "\\Fref{%s}" label))
820 (defun reftex-format-fref (label def-fmt)
821 (format "\\fref{%s}" label))
822
823 (defun reftex-goto-label (&optional other-window)
824 "Prompt for a label (with completion) and jump to the location of this label.
825 Optional prefix argument OTHER-WINDOW goes to the label in another window."
826 (interactive "P")
827 (reftex-access-scan-info)
828 (let* ((wcfg (current-window-configuration))
829 (docstruct (symbol-value reftex-docstruct-symbol))
830 ;; If point is inside a \ref{} or \pageref{}, use that as
831 ;; default value.
832 (default (when (looking-back "\\\\\\(?:page\\)?ref{[-a-zA-Z0-9_*.:]*")
833 (reftex-this-word "-a-zA-Z0-9_*.:")))
834 (label (completing-read (if default
835 (format "Label (default %s): " default)
836 "Label: ")
837 docstruct
838 (lambda (x) (stringp (car x))) t nil nil
839 default))
840 (selection (assoc label docstruct))
841 (where (progn
842 (reftex-show-label-location selection t nil 'stay)
843 (point-marker))))
844 (unless other-window
845 (set-window-configuration wcfg)
846 (switch-to-buffer (marker-buffer where))
847 (goto-char where))
848 (reftex-unhighlight 0)))
849
850
851 ;;; reftex-ref.el ends here