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