scheme interaction mode
[bpt/emacs.git] / lisp / textmodes / reftex-ref.el
CommitLineData
3afbc435 1;;; reftex-ref.el --- code to create labels and references with RefTeX
f2e3589a 2
ba318903 3;; Copyright (C) 1997-2014 Free Software Foundation, Inc.
3ba2590f 4
6fbeb429 5;; Author: Carsten Dominik <dominik@science.uva.nl>
ce545621 6;; Maintainer: auctex-devel@gnu.org
3ba2590f
RS
7
8;; This file is part of GNU Emacs.
9
1fecc8fe 10;; GNU Emacs is free software: you can redistribute it and/or modify
3ba2590f 11;; it under the terms of the GNU General Public License as published by
1fecc8fe
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
3ba2590f
RS
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
1fecc8fe 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
1a9461d0 22
3afbc435
PJ
23;;; Commentary:
24
25;;; Code:
26
7c4d13cc 27(eval-when-compile (require 'cl))
4f595e15 28
1a9461d0 29(require 'reftex)
3a1e8128 30(require 'reftex-parse)
1a9461d0 31
41116c5a 32;;;###autoload
1a9461d0
CD
33(defun reftex-label-location (&optional bound)
34 "Return the environment or macro which determines the label type at point.
35If optional BOUND is an integer, limit backward searches to that point."
36
37 (let* ((loc1 (reftex-what-macro reftex-label-mac-list bound))
38 (loc2 (reftex-what-environment reftex-label-env-list bound))
3666daf6 39 (loc3 (reftex-what-special-env 1 bound))
1a9461d0
CD
40 (p1 (or (cdr loc1) 0))
41 (p2 (or (cdr loc2) 0))
3666daf6
CD
42 (p3 (or (cdr loc3) 0))
43 (pmax (max p1 p2 p3)))
1a9461d0
CD
44
45 (setq reftex-location-start pmax)
46 (cond
47 ((= p1 pmax)
48 ;; A macro. Default context after macro name.
49 (setq reftex-default-context-position (+ p1 (length (car loc1))))
50 (or (car loc1) "section"))
51 ((= p2 pmax)
52 ;; An environment. Default context after \begin{name}.
53 (setq reftex-default-context-position (+ p2 8 (length (car loc2))))
54 (or (car loc2) "section"))
55 ((= p3 pmax)
56 ;; A special. Default context right there.
57 (setq reftex-default-context-position p3)
58 (setq loc3 (car loc3))
59 (cond ((null loc3) "section")
3666daf6
CD
60 ((symbolp loc3) (symbol-name loc3))
61 ((stringp loc3) loc3)
62 (t "section")))
1a9461d0
CD
63 (t ;; This should not happen, I think?
64 "section"))))
65
41116c5a 66;;;###autoload
1a9461d0
CD
67(defun reftex-label-info-update (cell)
68 ;; Update information about just one label in a different file.
69 ;; CELL contains the old info list
70 (let* ((label (nth 0 cell))
71 (typekey (nth 1 cell))
72 ;; (text (nth 2 cell))
73 (file (nth 3 cell))
74 (comment (nth 4 cell))
75 (note (nth 5 cell))
76 (buf (reftex-get-file-buffer-force
77 file (not (eq t reftex-keep-temporary-buffers)))))
78 (if (not buf)
79 (list label typekey "" file comment "LOST LABEL. RESCAN TO FIX.")
9a529312 80 (with-current-buffer buf
1a9461d0
CD
81 (save-restriction
82 (widen)
83 (goto-char 1)
84
85 (if (or (re-search-forward
3666daf6
CD
86 (format reftex-find-label-regexp-format
87 (regexp-quote label)) nil t)
88 (re-search-forward
89 (format reftex-find-label-regexp-format2
90 (regexp-quote label)) nil t))
1a9461d0
CD
91
92 (progn
93 (backward-char 1)
94 (append (reftex-label-info label file) (list note)))
95 (list label typekey "" file "LOST LABEL. RESCAN TO FIX.")))))))
96
41116c5a 97;;;###autoload
1a9461d0
CD
98(defun reftex-label-info (label &optional file bound derive env-or-mac)
99 ;; Return info list on LABEL at point.
f3c18bd0
CD
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)))
1a9461d0 103 (file (or file (buffer-file-name)))
f3c18bd0 104 (trust reftex-trust-label-prefix)
3666daf6 105 (in-comment (reftex-in-comment)))
f3c18bd0
CD
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)))))
1a9461d0
CD
121
122;;; Creating labels ---------------------------------------------------------
123
41116c5a 124;;;###autoload
1a9461d0
CD
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
c7015153 210 ;; Let's 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")
d2c32364 317 (file-name-base))
f3c18bd0
CD
318 ((equal letter "F")
319 (let ((masterdir (file-name-directory (reftex-TeX-master-file)))
320 (file (file-name-sans-extension (buffer-file-name))))
321 (if (string-match (concat "\\`" (regexp-quote masterdir))
322 file)
323 (substring file (length masterdir))
324 file)))
325 ((equal letter "m")
d2c32364 326 (file-name-base (reftex-TeX-master-file)))
f3c18bd0
CD
327 ((equal letter "M")
328 (file-name-nondirectory
329 (substring (file-name-directory (reftex-TeX-master-file))
330 0 -1)))
331 ((equal letter "u")
332 (or (user-login-name) ""))
333 ((equal letter "S")
334 (let* (macro level-exp level)
335 (save-excursion
336 (save-match-data
337 (when (re-search-backward reftex-section-regexp nil t)
338 (setq macro (reftex-match-string 2)
339 level-exp (cdr (assoc macro reftex-section-levels-all))
340 level (if (symbolp level-exp)
341 (abs (save-match-data
342 (funcall level-exp)))
343 (abs level-exp))))
344 (cdr (or (assoc macro reftex-section-prefixes)
345 (assoc level reftex-section-prefixes)
346 (assq t reftex-section-prefixes)
347 (list t "sec:")))))))
348 (t ""))))
1a9461d0
CD
349 (setq num (1- (+ (match-beginning 1) (length replace)))
350 prefix (replace-match replace nil nil prefix)))
351 prefix)))
352
353(defun reftex-uniquify-label (label &optional force separator)
354 ;; Make label unique by appending a number.
355 ;; Optional FORCE means, force appending a number, even if label is unique.
356 ;; Optional SEPARATOR is a string to stick between label and number.
357
358 ;; Ensure access to scanning info
359 (reftex-access-scan-info)
360
361 (cond
362 ((and (not force)
363 (not (assoc label (symbol-value reftex-docstruct-symbol))))
364 label)
365 (t
366 (let* ((label-numbers (assq 'label-numbers
367 (symbol-value reftex-docstruct-symbol)))
368 (label-numbers-alist (cdr label-numbers))
369 (cell (or (assoc label label-numbers-alist)
370 (car (setcdr label-numbers
371 (cons (cons label 0)
372 label-numbers-alist)))))
373 (num (1+ (cdr cell)))
374 (sep (or separator "")))
375 (while (assoc (concat label sep (int-to-string num))
376 (symbol-value reftex-docstruct-symbol))
377 (incf num))
378 (setcdr cell num)
379 (concat label sep (int-to-string num))))))
380
381;;; Referencing labels ------------------------------------------------------
382
383;; Help string for the reference label menu
384(defconst reftex-select-label-prompt
385 "Select: [n]ext [p]revious [r]escan [ ]context e[x]tern [q]uit RET [?]HELP+more")
386
387(defconst reftex-select-label-help
388 " n / p Go to next/previous label (Cursor motion works as well)
389 C-c C-n/p Go to next/previous section heading.
390 b / l Jump back to previous selection / Reuse last referenced label.
70d797cd 391 z Jump to a specific section, e.g. '3 z' jumps to section 3.
1a9461d0
CD
392 g / s Update menu / Switch label type.
393 r / C-u r Reparse document / Reparse entire document.
394 x Switch to label menu of external document (with LaTeX package `xr').
395 F t c Toggle: [F]ile borders, [t]able of contents, [c]ontext
396 # % Toggle: [#] label counters, [%] labels in comments
397 SPC / f Show full context in other window / Toggle follow mode.
398 . Show insertion point in other window.
399 v / V Toggle \\ref <-> \\vref / Rotate \\ref <=> \\fref <=> \\Fref
400 TAB Enter a label with completion.
401 m , - + Mark entry. `,-+' also assign a separator.
402 a / A Put all marked entries into one/many \\ref commands.
403 q / RET Quit without referencing / Accept current label (also on mouse-2).")
404
41116c5a 405;;;###autoload
1a9461d0
CD
406(defun reftex-reference (&optional type no-insert cut)
407 "Make a LaTeX reference. Look only for labels of a certain TYPE.
408With prefix arg, force to rescan buffer for labels. This should only be
409necessary if you have recently entered labels yourself without using
410reftex-label. Rescanning of the buffer can also be requested from the
411label selection menu.
412The function returns the selected label or nil.
413If NO-INSERT is non-nil, do not insert \\ref command, just return label.
414When called with 2 C-u prefix args, disable magic word recognition."
415
416 (interactive)
417
4f595e15 418 ;; Check for active recursive edits
1a9461d0
CD
419 (reftex-check-recursive-edit)
420
4f595e15 421 ;; Ensure access to scanning info and rescan buffer if prefix is '(4)
1a9461d0
CD
422 (reftex-access-scan-info current-prefix-arg)
423
4f595e15
RA
424 (let ((reftex-refstyle (when (and (boundp 'reftex-refstyle) reftex-refstyle)
425 reftex-refstyle))
426 (reftex-format-ref-function reftex-format-ref-function)
427 (form "\\ref{%s}")
428 label labels sep sep1 style-alist)
429
430 (unless reftex-refstyle
431 (if reftex-ref-macro-prompt
432 (progn
433 ;; Build a temporary list which handles more easily.
434 (dolist (elt reftex-ref-style-alist)
435 (when (member (car elt) (reftex-ref-style-list))
436 (mapc (lambda (x)
437 (add-to-list 'style-alist (cons (cadr x) (car x)) t))
438 (nth 2 elt))))
439 ;; Prompt the user for the macro.
440 (let ((key (reftex-select-with-char
441 "" (concat "SELECT A REFERENCE FORMAT\n\n"
442 (mapconcat
443 (lambda (x)
444 (format "[%c] %s %s" (car x)
445 (if (> (car x) 31) " " "")
446 (cdr x)))
447 style-alist "\n")))))
448 (setq reftex-refstyle (cdr (assoc key style-alist)))
449 (unless reftex-refstyle
450 (error "No reference macro associated with key `%c'" key))))
451 ;; Get the first macro from `reftex-ref-style-alist' which
452 ;; matches the first entry in the list of active styles.
453 (setq reftex-refstyle
454 (or (caar (nth 2 (assoc (car (reftex-ref-style-list))
455 reftex-ref-style-alist)))
456 ;; Use the first entry in r-r-s-a as a last resort.
457 (caar (nth 2 (car reftex-ref-style-alist)))))))
458
459 (unless type
460 ;; Guess type from context
461 (if (and reftex-guess-label-type
462 (setq type (reftex-guess-label-type)))
463 (setq cut (cdr type)
464 type (car type))
465 (setq type (reftex-query-label-type))))
1a9461d0
CD
466
467 ;; Have the user select a label
468 (set-marker reftex-select-return-marker (point))
469 (setq labels (save-excursion
3666daf6 470 (reftex-offer-label-menu type)))
1a9461d0
CD
471 (reftex-ensure-compiled-variables)
472 (set-marker reftex-select-return-marker nil)
3b919c9f 473 ;; If the first entry is the symbol 'concat, concat all labels.
1a9461d0
CD
474 ;; We keep the cdr of the first label for typekey etc information.
475 (if (eq (car labels) 'concat)
3666daf6
CD
476 (setq labels (list (list (mapconcat 'car (cdr labels) ",")
477 (cdr (nth 1 labels))))))
1a9461d0 478 (setq type (nth 1 (car labels))
3666daf6
CD
479 form (or (cdr (assoc type reftex-typekey-to-format-alist))
480 form))
c8f3bf36 481
1a9461d0
CD
482 (cond
483 (no-insert
484 ;; Just return the first label
485 (car (car labels)))
486 ((null labels)
487 (message "Quit")
488 nil)
489 (t
490 (while labels
3666daf6
CD
491 (setq label (car (car labels))
492 sep (nth 2 (car labels))
493 sep1 (cdr (assoc sep reftex-multiref-punctuation))
494 labels (cdr labels))
c8f3bf36 495 (when cut
3666daf6
CD
496 (backward-delete-char cut)
497 (setq cut nil))
498
499 ;; remove ~ if we do already have a space
500 (when (and (= ?~ (string-to-char form))
f3c18bd0 501 (member (preceding-char) '(?\ ?\t ?\n ?~)))
3666daf6
CD
502 (setq form (substring form 1)))
503 ;; do we have a special format?
4f595e15
RA
504 (unless (string= reftex-refstyle "\\ref")
505 (setq reftex-format-ref-function 'reftex-format-special))
3666daf6
CD
506 ;; ok, insert the reference
507 (if sep1 (insert sep1))
508 (insert
509 (if reftex-format-ref-function
4f595e15 510 (funcall reftex-format-ref-function label form reftex-refstyle)
3666daf6
CD
511 (format form label label)))
512 ;; take out the initial ~ for good
513 (and (= ?~ (string-to-char form))
514 (setq form (substring form 1))))
1a9461d0
CD
515 (message "")
516 label))))
517
518(defun reftex-guess-label-type ()
519 ;; Examine context to guess what a \ref might want to reference.
520 (let ((words reftex-words-to-typekey-alist)
3666daf6
CD
521 (case-fold-search t)
522 (bound (max (point-min) (- (point) 35)))
523 matched cell)
1a9461d0
CD
524 (save-excursion
525 (while (and (setq cell (pop words))
c8f3bf36 526 (not (setq matched
3666daf6 527 (re-search-backward (car cell) bound t))))))
1a9461d0 528 (if matched
3666daf6 529 (cons (cdr cell) (- (match-end 0) (match-end 1)))
1a9461d0
CD
530 nil)))
531
532(defvar reftex-select-label-map)
533(defun reftex-offer-label-menu (typekey)
534 ;; Offer a menu with the appropriate labels.
535 (let* ((buf (current-buffer))
3666daf6
CD
536 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol)))
537 (xr-alist (cons (cons "" (buffer-file-name)) (nth 1 xr-data)))
538 (xr-index 0)
1a9461d0 539 (here-I-am (car (reftex-where-am-I)))
3666daf6 540 (here-I-am1 here-I-am)
1a9461d0
CD
541 (toc (reftex-typekey-check typekey reftex-label-menu-flags 0))
542 (files (reftex-typekey-check typekey reftex-label-menu-flags 7))
543 (context (not (reftex-typekey-check
544 typekey reftex-label-menu-flags 3)))
545 (counter (reftex-typekey-check
546 typekey reftex-label-menu-flags 2))
547 (follow (reftex-typekey-check
548 typekey reftex-label-menu-flags 4))
549 (commented (nth 5 reftex-label-menu-flags))
3666daf6
CD
550 (prefix "")
551 selection-buffers
1a9461d0
CD
552 offset rtn key data last-data entries)
553
554 (unwind-protect
555 (catch 'exit
556 (while t
557 (save-window-excursion
3666daf6
CD
558 (delete-other-windows)
559 (setq reftex-call-back-to-this-buffer buf
560 reftex-latex-syntax-table (syntax-table))
d63eb0e7
GM
561 (if reftex-use-multiple-selection-buffers
562 (switch-to-buffer-other-window
9a529312 563 (with-current-buffer buf
d63eb0e7
GM
564 (reftex-make-selection-buffer-name typekey)))
565 (switch-to-buffer-other-window "*RefTeX Select*")
566 (reftex-erase-buffer))
3666daf6
CD
567 (unless (eq major-mode 'reftex-select-label-mode)
568 (reftex-select-label-mode))
569 (add-to-list 'selection-buffers (current-buffer))
1a9461d0 570 (setq truncate-lines t)
3666daf6
CD
571 (setq mode-line-format
572 (list "---- " 'mode-line-buffer-identification
573 " " 'global-mode-string " (" mode-name ")"
c8f3bf36 574 " S<" 'reftex-refstyle ">"
3666daf6
CD
575 " -%-"))
576 (cond
577 ((= 0 (buffer-size))
578 (let ((buffer-read-only nil))
579 (message "Creating Selection Buffer...")
580 (setq offset (reftex-insert-docstruct
581 buf
582 toc
583 typekey
584 nil ; index
585 files
586 context
587 counter
588 commented
c8f3bf36 589 (or here-I-am offset)
3666daf6 590 prefix
c8f3bf36 591 nil ; no a toc buffer
3666daf6
CD
592 ))))
593 (here-I-am
594 (setq offset (reftex-get-offset buf here-I-am typekey)))
595 (t (setq offset t)))
596 (setq buffer-read-only t)
597 (setq offset (or offset t))
1a9461d0
CD
598
599 (setq here-I-am nil) ; turn off determination of offset
600 (setq rtn
601 (reftex-select-item
602 reftex-select-label-prompt
603 reftex-select-label-help
3666daf6 604 reftex-select-label-map
1a9461d0
CD
605 offset
606 'reftex-show-label-location follow))
607 (setq key (car rtn)
608 data (nth 1 rtn)
609 last-data (nth 2 rtn)
3666daf6 610 offset t)
1a9461d0
CD
611 (unless key (throw 'exit nil))
612 (cond
3666daf6
CD
613 ((eq key ?g)
614 ;; update buffer
615 (reftex-erase-buffer))
1a9461d0
CD
616 ((or (eq key ?r)
617 (eq key ?R))
618 ;; rescan buffer
3666daf6
CD
619 (and current-prefix-arg (setq key ?R))
620 (reftex-erase-buffer)
1a9461d0
CD
621 (reftex-reparse-document buf last-data key))
622 ((eq key ?c)
623 ;; toggle context mode
3666daf6 624 (reftex-erase-buffer)
1a9461d0
CD
625 (setq context (not context)))
626 ((eq key ?s)
627 ;; switch type
3666daf6 628 (setq here-I-am here-I-am1)
1a9461d0
CD
629 (setq typekey (reftex-query-label-type)))
630 ((eq key ?t)
7c4d13cc 631 ;; toggle table of contents display, or change depth
3666daf6
CD
632 (reftex-erase-buffer)
633 (if current-prefix-arg
634 (setq reftex-toc-max-level (prefix-numeric-value
635 current-prefix-arg))
636 (setq toc (not toc))))
1a9461d0
CD
637 ((eq key ?F)
638 ;; toggle display of included file borders
3666daf6 639 (reftex-erase-buffer)
1a9461d0
CD
640 (setq files (not files)))
641 ((eq key ?#)
642 ;; toggle counter display
3666daf6 643 (reftex-erase-buffer)
1a9461d0
CD
644 (setq counter (not counter)))
645 ((eq key ?%)
646 ;; toggle display of commented labels
3666daf6 647 (reftex-erase-buffer)
1a9461d0
CD
648 (setq commented (not commented)))
649 ((eq key ?l)
650 ;; reuse the last referenced label again
651 (setq entries reftex-last-used-reference)
652 (throw 'exit t))
3666daf6
CD
653 ((eq key ?x)
654 ;; select an external document
655 (setq xr-index (reftex-select-external-document
656 xr-alist xr-index))
657 (setq buf (or (reftex-get-file-buffer-force
658 (cdr (nth xr-index xr-alist)))
659 (error "Cannot switch document"))
660 prefix (or (car (nth xr-index xr-alist)) ""))
1a9461d0 661 (set-buffer buf)
3666daf6
CD
662 (reftex-access-scan-info))
663 ((stringp key)
664 (setq entries
665 (list
666 (list
667 (or (assoc key (symbol-value reftex-docstruct-symbol))
668 (list key typekey)))))
1a9461d0 669 (throw 'exit t))
3666daf6
CD
670 ((memq key '(?a ?A return))
671 (cond
672 (reftex-select-marked
673 (setq entries (nreverse reftex-select-marked)))
674 (data
675 (setq entries (list (list data))))
676 (t (setq entries nil)))
677 (when entries
678 (if (equal key ?a) (push 'concat entries))
679 (setq reftex-last-used-reference entries))
680 (set-buffer buf)
681 (throw 'exit t))
682 (t (error "This should not happen (reftex-offer-label-menu)"))))))
1a9461d0 683 (save-excursion
3666daf6
CD
684 (while reftex-buffers-with-changed-invisibility
685 (set-buffer (car (car reftex-buffers-with-changed-invisibility)))
fe2ca5ec 686 (setq buffer-invisibility-spec
3666daf6 687 (cdr (pop reftex-buffers-with-changed-invisibility)))))
fe2ca5ec
GM
688 (mapc (lambda (buf) (and (buffer-live-p buf) (bury-buffer buf)))
689 selection-buffers)
1a9461d0
CD
690 (reftex-kill-temporary-buffers))
691 ;; Add the prefixes, put together the relevant information in the form
7ac7387b 692 ;; (LABEL TYPEKEY SEPARATOR) and return a list of those.
1a9461d0 693 (mapcar (lambda (x)
3666daf6
CD
694 (if (listp x)
695 (list (concat prefix (car (car x)))
696 (nth 1 (car x))
697 (nth 2 x))
698 x))
699 entries)))
1a9461d0
CD
700
701(defun reftex-reparse-document (&optional buffer data key)
702 ;; Rescan the document.
703 (save-window-excursion
704 (save-excursion
705 (if buffer
706 (if (not (bufferp buffer))
707 (error "No such buffer %s" (buffer-name buffer))
708 (set-buffer buffer)))
709 (let ((arg (if (eq key ?R) '(16) '(4)))
710 (file (nth 3 data)))
711 (reftex-access-scan-info arg file)))))
712
41116c5a 713;;;###autoload
1a9461d0
CD
714(defun reftex-query-label-type ()
715 ;; Ask for label type
c8f3bf36 716 (let ((key (reftex-select-with-char
3666daf6 717 reftex-type-query-prompt reftex-type-query-help 3)))
1a9461d0
CD
718 (unless (member (char-to-string key) reftex-typekey-list)
719 (error "No such label type: %s" (char-to-string key)))
720 (char-to-string key)))
721
41116c5a 722;;;###autoload
c8f3bf36 723(defun reftex-show-label-location (data forward no-revisit
3666daf6 724 &optional stay error)
1a9461d0
CD
725 ;; View the definition site of a label in another window.
726 ;; DATA is an entry from the docstruct list.
727 ;; FORWARD indicates if the label is likely forward from current point.
728 ;; NO-REVISIT means do not load a file to show this label.
729 ;; STAY means leave the new window selected.
730 ;; ERROR means throw an error exception when the label cannot be found.
731 ;; If ERROR is nil, the return value of this function indicates success.
732 (let* ((this-window (selected-window))
3666daf6 733 (errorf (if error 'error 'message))
1a9461d0
CD
734 label file buffer re found)
735
736 (catch 'exit
737 (setq label (nth 0 data)
3666daf6 738 file (nth 3 data))
1a9461d0
CD
739
740 (unless file
3666daf6
CD
741 (funcall errorf "Unknown label - reparse might help")
742 (throw 'exit nil))
1a9461d0
CD
743
744 ;; Goto the file in another window
c8f3bf36 745 (setq buffer
3666daf6
CD
746 (if no-revisit
747 (reftex-get-buffer-visiting file)
748 (reftex-get-file-buffer-force
749 file (not reftex-keep-temporary-buffers))))
1a9461d0
CD
750 (if buffer
751 ;; good - the file is available
752 (switch-to-buffer-other-window buffer)
753 ;; we have got a problem here. The file does not exist.
754 ;; Let' get out of here..
3666daf6
CD
755 (funcall errorf "Label %s not found" label)
756 (throw 'exit nil))
1a9461d0
CD
757
758 ;; search for that label
759 (setq re (format reftex-find-label-regexp-format (regexp-quote label)))
760 (setq found
3666daf6
CD
761 (if forward
762 (re-search-forward re nil t)
763 (re-search-backward re nil t)))
1a9461d0
CD
764 (unless found
765 (goto-char (point-min))
3666daf6
CD
766 (unless (setq found (re-search-forward re nil t))
767 ;; Ooops. Must be in a macro with distributed args.
768 (setq found
769 (re-search-forward
770 (format reftex-find-label-regexp-format2
771 (regexp-quote label)) nil t))))
1a9461d0 772 (if (match-end 3)
3666daf6
CD
773 (progn
774 (reftex-highlight 0 (match-beginning 3) (match-end 3))
775 (reftex-show-entry (match-beginning 3) (match-end 3))
776 (recenter '(4))
777 (unless stay (select-window this-window)))
778 (select-window this-window)
779 (funcall errorf "Label %s not found" label))
1a9461d0
CD
780 found)))
781
782(defvar font-lock-mode)
783(defun reftex-show-entry (beg-hlt end-hlt)
784 ;; Show entry if point is hidden
785 (let* ((n (/ (reftex-window-height) 2))
786 (beg (save-excursion
787 (re-search-backward "[\n\r]" nil 1 n) (point)))
788 (end (save-excursion
789 (re-search-forward "[\n\r]" nil 1 n) (point))))
790 (cond
791 ((and (boundp 'buffer-invisibility-spec) buffer-invisibility-spec
3666daf6 792 (get-char-property (1+ beg-hlt) 'invisible))
1a9461d0
CD
793 ;; Invisible with text properties. That is easy to change.
794 (push (cons (current-buffer) buffer-invisibility-spec)
3666daf6 795 reftex-buffers-with-changed-invisibility)
1a9461d0
CD
796 (setq buffer-invisibility-spec nil))
797 ((string-match "\r" (buffer-substring beg end))
798 ;; Invisible with selective display. We need to copy it.
799 (let ((string (buffer-substring-no-properties beg end)))
3666daf6
CD
800 (switch-to-buffer "*RefTeX Context Copy*")
801 (setq buffer-read-only nil)
802 (erase-buffer)
803 (insert string)
804 (subst-char-in-region (point-min) (point-max) ?\r ?\n t)
805 (goto-char (- beg-hlt beg))
806 (reftex-highlight 0 (1+ (- beg-hlt beg)) (1+ (- end-hlt beg)))
807 (if (reftex-refontify)
808 (when (or (not (eq major-mode 'latex-mode))
809 (not font-lock-mode))
810 (latex-mode)
c8f3bf36 811 (run-hook-with-args
3666daf6
CD
812 'reftex-pre-refontification-functions
813 reftex-call-back-to-this-buffer 'reftex-hidden)
814 (turn-on-font-lock))
815 (when (or (not (eq major-mode 'fundamental-mode))
816 font-lock-mode)
817 (fundamental-mode)))
818 (run-hooks 'reftex-display-copied-context-hook)
819 (setq buffer-read-only t))))))
1a9461d0 820
4f595e15
RA
821;; Generate functions for direct insertion of specific referencing
822;; macros. The functions are named `reftex-<package>-<macro>',
823;; e.g. `reftex-varioref-vref'.
824(dolist (elt reftex-ref-style-alist)
825 (when (stringp (nth 1 elt))
826 (dolist (item (nth 2 elt))
827 (let ((macro (car item))
828 (package (nth 1 elt)))
829 (eval `(defun ,(intern (format "reftex-%s-%s" package
830 (substring macro 1 (length macro)))) ()
831 ,(format "Insert a reference using the `%s' macro from the %s \
832package.\n\nThis is a generated function."
833 macro package)
834 (interactive)
835 (let ((reftex-refstyle ,macro))
836 (reftex-reference))))))))
837
838(defun reftex-format-special (label fmt refstyle)
839 "Apply selected reference style to format FMT and add LABEL.
840Replace any occurrences of \"\\ref\" with REFSTYLE."
841 ;; Replace instances of \ref in `fmt' with the special reference
842 ;; style selected by the user.
5e26d984
TH
843 (cond
844 ((while (string-match "\\(\\\\ref\\)[ \t]*{" fmt)
845 (setq fmt (replace-match refstyle t t fmt 1))))
846 ((string-match "\\(\\\\[[:alpha:]]+\\)[ \t]*{" fmt)
847 (setq fmt (replace-match refstyle t t fmt 1))))
4f595e15 848 (format fmt label))
1a9461d0 849
41116c5a 850;;;###autoload
3b919c9f
CD
851(defun reftex-goto-label (&optional other-window)
852 "Prompt for a label (with completion) and jump to the location of this label.
853Optional prefix argument OTHER-WINDOW goes to the label in another window."
854 (interactive "P")
855 (reftex-access-scan-info)
856 (let* ((wcfg (current-window-configuration))
3666daf6 857 (docstruct (symbol-value reftex-docstruct-symbol))
c799747b
TH
858 ;; If point is inside a \ref{} or \pageref{}, use that as
859 ;; default value.
860 (default (when (looking-back "\\\\\\(?:page\\)?ref{[-a-zA-Z0-9_*.:]*")
861 (reftex-this-word "-a-zA-Z0-9_*.:")))
862 (label (completing-read (if default
863 (format "Label (default %s): " default)
864 "Label: ")
865 docstruct
866 (lambda (x) (stringp (car x))) t nil nil
867 default))
3666daf6
CD
868 (selection (assoc label docstruct))
869 (where (progn
870 (reftex-show-label-location selection t nil 'stay)
871 (point-marker))))
3b919c9f
CD
872 (unless other-window
873 (set-window-configuration wcfg)
874 (switch-to-buffer (marker-buffer where))
c8f3bf36 875 (goto-char where))
3b919c9f
CD
876 (reftex-unhighlight 0)))
877
4f595e15 878(provide 'reftex-ref)
3b919c9f 879
1a9461d0 880;;; reftex-ref.el ends here
41116c5a
GM
881
882;; Local Variables:
883;; generated-autoload-file: "reftex.el"
884;; End: