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