don't use function-equal in nadvice
[bpt/emacs.git] / lisp / textmodes / reftex-parse.el
CommitLineData
3afbc435 1;;; reftex-parse.el --- parser functions for 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
CD
29(require 'reftex)
30
31(defmacro reftex-with-special-syntax (&rest body)
32 `(let ((saved-syntax (syntax-table)))
33 (unwind-protect
3666daf6
CD
34 (progn
35 (set-syntax-table reftex-syntax-table)
36 (let ((case-fold-search nil))
37 ,@body))
1a9461d0
CD
38 (set-syntax-table saved-syntax))))
39
41116c5a 40;;;###autoload
1a9461d0
CD
41(defun reftex-parse-one ()
42 "Re-parse this file."
43 (interactive)
44 (let ((reftex-enable-partial-scans t))
45 (reftex-access-scan-info '(4))))
46
41116c5a 47;;;###autoload
1a9461d0
CD
48(defun reftex-parse-all ()
49 "Re-parse entire document."
50 (interactive)
51 (reftex-access-scan-info '(16)))
52
6b31e6b1
SM
53(defvar reftex--index-tags)
54
41116c5a 55;;;###autoload
1a9461d0 56(defun reftex-do-parse (rescan &optional file)
79d7167f
TH
57 "Do a document rescan.
58When allowed, do only a partial scan from FILE."
1a9461d0
CD
59
60 ;; Normalize the rescan argument
61 (setq rescan (cond ((eq rescan t) t)
62 ((eq rescan 1) 1)
63 ((equal rescan '(4)) t)
64 ((equal rescan '(16)) 1)
65 (t 1)))
66
67 ;; Partial scans only when allowed
68 (unless reftex-enable-partial-scans
69 (setq rescan 1))
70
71 ;; Do the scanning.
72
73 (let* ((old-list (symbol-value reftex-docstruct-symbol))
74 (master (reftex-TeX-master-file))
3666daf6
CD
75 (true-master (file-truename master))
76 (master-dir (file-name-as-directory (file-name-directory master)))
1a9461d0 77 (file (or file (buffer-file-name)))
3666daf6
CD
78 (true-file (file-truename file))
79 (bibview-cache (assq 'bibview-cache old-list))
6b31e6b1 80 (reftex--index-tags (cdr (assq 'index-tags old-list)))
1a9461d0
CD
81 from-file appendix docstruct tmp)
82
83 ;; Make sure replacement is really an option here
84 (when (and (eq rescan t)
85 (not (and (member (list 'bof file) old-list)
86 (member (list 'eof file) old-list))))
87 ;; Scan whole document because no such file section exists
88 (setq rescan 1))
89 (when (string= true-file true-master)
90 ;; Scan whole document because this file is the master
91 (setq rescan 1))
92
93 ;; From which file do we start?
94 (setq from-file
95 (cond ((eq rescan t) (or file master))
96 ((eq rescan 1) master)
97 (t (error "This should not happen (reftex-do-parse)"))))
98
99 ;; Reset index-tags if we scan everything
6b31e6b1 100 (if (equal rescan 1) (setq reftex--index-tags nil))
1a9461d0
CD
101
102 ;; Find active toc entry and initialize section-numbers
103 (setq reftex-active-toc (reftex-last-assoc-before-elt
3666daf6
CD
104 'toc (list 'bof from-file) old-list)
105 appendix (reftex-last-assoc-before-elt
106 'appendix (list 'bof from-file) old-list))
1a9461d0
CD
107
108 (reftex-init-section-numbers reftex-active-toc appendix)
109
110 (if (eq rescan 1)
111 (message "Scanning entire document...")
112 (message "Scanning document from %s..." from-file))
113
114 (reftex-with-special-syntax
115 (save-window-excursion
116 (save-excursion
3666daf6
CD
117 (unwind-protect
118 (setq docstruct
119 (reftex-parse-from-file
120 from-file docstruct master-dir))
121 (reftex-kill-temporary-buffers)))))
1a9461d0
CD
122
123 (message "Scanning document... done")
124
125 ;; Turn the list around.
126 (setq docstruct (nreverse docstruct))
127
128 ;; Set or insert
129 (setq docstruct (reftex-replace-label-list-segment
130 old-list docstruct (eq rescan 1)))
131
132 ;; Add all missing information
133 (unless (assq 'label-numbers docstruct)
134 (push (cons 'label-numbers nil) docstruct))
135 (unless (assq 'master-dir docstruct)
136 (push (cons 'master-dir master-dir) docstruct))
137 (unless (assq 'bibview-cache docstruct)
138 (push (cons 'bibview-cache (cdr bibview-cache)) docstruct))
139 (let* ((bof1 (memq (assq 'bof docstruct) docstruct))
140 (bof2 (assq 'bof (cdr bof1)))
141 (is-multi (not (not (and bof1 bof2))))
142 (entry (or (assq 'is-multi docstruct)
143 (car (push (list 'is-multi is-multi) docstruct)))))
144 (setcdr entry (cons is-multi nil)))
6b31e6b1
SM
145 (and reftex--index-tags
146 (setq reftex--index-tags (sort reftex--index-tags 'string<)))
1a9461d0
CD
147 (let ((index-tag-cell (assq 'index-tags docstruct)))
148 (if index-tag-cell
6b31e6b1
SM
149 (setcdr index-tag-cell reftex--index-tags)
150 (push (cons 'index-tags reftex--index-tags) docstruct)))
1a9461d0
CD
151 (unless (assq 'xr docstruct)
152 (let* ((allxr (reftex-all-assq 'xr-doc docstruct))
3666daf6 153 (alist (mapcar
887a0b34 154 (lambda (x)
3666daf6
CD
155 (if (setq tmp (reftex-locate-file (nth 2 x) "tex"
156 master-dir))
157 (cons (nth 1 x) tmp)
158 (message "Can't find external document %s"
159 (nth 2 x))
160 nil))
161 allxr))
162 (alist (delq nil alist))
163 (allprefix (delq nil (mapcar 'car alist)))
164 (regexp (if allprefix
887a0b34 165 (concat "\\`\\("
3666daf6
CD
166 (mapconcat 'identity allprefix "\\|")
167 "\\)")
168 "\\\\\\\\\\\\"))) ; this will never match
169 (push (list 'xr alist regexp) docstruct)))
1a9461d0
CD
170
171 (set reftex-docstruct-symbol docstruct)
172 (put reftex-docstruct-symbol 'modified t)))
173
41116c5a 174;;;###autoload
1a9461d0
CD
175(defun reftex-everything-regexp ()
176 (if reftex-support-index
177 reftex-everything-regexp
178 reftex-everything-regexp-no-index))
179
41116c5a 180;; NB this is a global autoload - see reftex.el.
03ca24fb 181;;;###autoload
1a9461d0
CD
182(defun reftex-all-document-files (&optional relative)
183 "Return a list of all files belonging to the current document.
184When RELATIVE is non-nil, give file names relative to directory
185of master file."
186 (let* ((all (symbol-value reftex-docstruct-symbol))
187 (master-dir (file-name-directory (reftex-TeX-master-file)))
188 (re (concat "\\`" (regexp-quote master-dir)))
189 file-list tmp file)
190 (while (setq tmp (assoc 'bof all))
191 (setq file (nth 1 tmp)
192 all (cdr (memq tmp all)))
193 (and relative
194 (string-match re file)
195 (setq file (substring file (match-end 0))))
196 (push file file-list))
197 (nreverse file-list)))
198
887a0b34 199;; Bound in the caller, reftex-do-parse.
1a9461d0 200(defun reftex-parse-from-file (file docstruct master-dir)
79d7167f 201 "Scan the buffer for labels and save them in a list."
1a9461d0
CD
202 (let ((regexp (reftex-everything-regexp))
203 (bound 0)
204 file-found tmp include-file
205 (level 1)
206 (highest-level 100)
207 toc-entry index-entry next-buf buf)
208
209 (catch 'exit
210 (setq file-found (reftex-locate-file file "tex" master-dir))
211 (if (and (not file-found)
3666daf6
CD
212 (setq buf (reftex-get-buffer-visiting file)))
213 (setq file-found (buffer-file-name buf)))
1a9461d0
CD
214
215 (unless file-found
216 (push (list 'file-error file) docstruct)
217 (throw 'exit nil))
218
219 (save-excursion
220
221 (message "Scanning file %s" file)
222 (set-buffer
223 (setq next-buf
224 (reftex-get-file-buffer-force
225 file-found
226 (not (eq t reftex-keep-temporary-buffers)))))
227
228 ;; Begin of file mark
229 (setq file (buffer-file-name))
230 (push (list 'bof file) docstruct)
231
3666daf6
CD
232 (reftex-with-special-syntax
233 (save-excursion
234 (save-restriction
235 (widen)
236 (goto-char 1)
237
238 (while (re-search-forward regexp nil t)
239
240 (cond
241
242 ((match-end 1)
243 ;; It is a label
d79d37bd
TH
244 (when (or (null reftex-label-ignored-macros-and-environments)
245 ;; \label{} defs should always be honored,
246 ;; just no keyval style [label=foo] defs.
247 (string-equal "\label{" (substring (reftex-match-string 0) 0 7))
f440830d
GM
248 (if (and (fboundp 'TeX-current-macro)
249 (fboundp 'LaTeX-current-environment))
250 (not (or (member (save-match-data (TeX-current-macro))
251 reftex-label-ignored-macros-and-environments)
252 (member (save-match-data (LaTeX-current-environment))
253 reftex-label-ignored-macros-and-environments)))
254 t))
d79d37bd
TH
255 (push (reftex-label-info (reftex-match-string 1) file bound)
256 docstruct)))
3666daf6
CD
257
258 ((match-end 3)
259 ;; It is a section
3666daf6 260
4f595e15
RA
261 ;; Use the beginning as bound and not the end
262 ;; (i.e. (point)) because the section command might
263 ;; be the start of the current environment to be
264 ;; found by `reftex-label-info'.
265 (setq bound (match-beginning 0))
266 ;; The section regexp matches a character at the end
267 ;; we are not interested in. Especially if it is the
268 ;; backslash of a following macro we want to find in
269 ;; the next parsing iteration.
270 (when (eq (char-before) ?\\) (backward-char))
3666daf6 271 ;; Insert in List
e2cb57f5 272 (setq toc-entry (funcall reftex-section-info-function file))
3666daf6
CD
273 (when toc-entry
274 ;; It can happen that section info returns nil
275 (setq level (nth 5 toc-entry))
276 (setq highest-level (min highest-level level))
277 (if (= level highest-level)
278 (message
279 "Scanning %s %s ..."
280 (car (rassoc level reftex-section-levels-all))
281 (nth 6 toc-entry)))
282
283 (push toc-entry docstruct)
284 (setq reftex-active-toc toc-entry)))
285
286 ((match-end 7)
287 ;; It's an include or input
288 (setq include-file (reftex-match-string 7))
289 ;; Test if this file should be ignored
887a0b34 290 (unless (delq nil (mapcar
3666daf6
CD
291 (lambda (x) (string-match x include-file))
292 reftex-no-include-regexps))
293 ;; Parse it
294 (setq docstruct
295 (reftex-parse-from-file
296 include-file
297 docstruct master-dir))))
298
299 ((match-end 9)
300 ;; Appendix starts here
301 (reftex-init-section-numbers nil t)
302 (push (cons 'appendix t) docstruct))
303
304 ((match-end 10)
305 ;; Index entry
306 (when reftex-support-index
307 (setq index-entry (reftex-index-info file))
308 (when index-entry
6b31e6b1 309 (add-to-list 'reftex--index-tags (nth 1 index-entry))
3666daf6
CD
310 (push index-entry docstruct))))
311
312 ((match-end 11)
313 ;; A macro with label
314 (save-excursion
315 (let* ((mac (reftex-match-string 11))
316 (label (progn (goto-char (match-end 11))
317 (save-match-data
318 (reftex-no-props
319 (reftex-nth-arg-wrapper
320 mac)))))
321 (typekey (nth 1 (assoc mac reftex-env-or-mac-alist)))
322 (entry (progn (if typekey
323 ;; A typing macro
324 (goto-char (match-end 0))
325 ;; A neutral macro
326 (goto-char (match-end 11))
327 (reftex-move-over-touching-args))
328 (reftex-label-info
329 label file bound nil nil))))
330 (push entry docstruct))))
331 (t (error "This should not happen (reftex-parse-from-file)")))
332 )
333
334 ;; Find bibliography statement
335 (when (setq tmp (reftex-locate-bibliography-files master-dir))
336 (push (cons 'bib tmp) docstruct))
337
338 (goto-char 1)
887a0b34 339 (when (re-search-forward
3666daf6
CD
340 "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t)
341 (push (cons 'thebib file) docstruct))
887a0b34 342
3666daf6
CD
343 ;; Find external document specifications
344 (goto-char 1)
345 (while (re-search-forward "[\n\r][ \t]*\\\\externaldocument\\(\\[\\([^]]*\\)\\]\\)?{\\([^}]+\\)}" nil t)
346 (push (list 'xr-doc (reftex-match-string 2)
347 (reftex-match-string 3))
348 docstruct))
349
350 ;; End of file mark
351 (push (list 'eof file) docstruct)))))
1a9461d0
CD
352
353 ;; Kill the scanned buffer
354 (reftex-kill-temporary-buffers next-buf))
355
356 ;; Return the list
357 docstruct))
358
9bc236c8 359(defun reftex-using-biblatex-p ()
d136f184 360 "Return non-nil if we are using biblatex rather than bibtex."
9bc236c8
TH
361 (if (boundp 'TeX-active-styles)
362 ;; the sophisticated AUCTeX way
363 (member "biblatex" TeX-active-styles)
364 ;; poor-man's check...
365 (save-excursion
5132f910 366 (re-search-forward "^[^%\n]*?\\\\usepackage.*{biblatex}" nil t))))
9bc236c8 367
41116c5a 368;;;###autoload
1a9461d0 369(defun reftex-locate-bibliography-files (master-dir &optional files)
9bc236c8 370 "Scan buffer for bibliography macros and return file list."
1a9461d0
CD
371 (unless files
372 (save-excursion
373 (goto-char (point-min))
9bc236c8
TH
374 ;; when biblatex is used, multiple \bibliography or
375 ;; \addbibresource macros are allowed. With plain bibtex, only
376 ;; the first is used.
377 (let ((using-biblatex (reftex-using-biblatex-p))
378 (again t))
379 (while (and again
380 (re-search-forward
381 (concat
382 ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
383 "\\(^\\)[^%\n\r]*\\\\\\("
384 (mapconcat 'identity reftex-bibliography-commands "\\|")
385 "\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)") nil t))
386 (setq files
387 (append files
388 (split-string (reftex-match-string 4)
389 "[ \t\n\r]*,[ \t\n\r]*")))
390 (unless using-biblatex
391 (setq again nil))))))
1a9461d0 392 (when files
887a0b34 393 (setq files
3666daf6
CD
394 (mapcar
395 (lambda (x)
396 (if (or (member x reftex-bibfile-ignore-list)
397 (delq nil (mapcar (lambda (re) (string-match re x))
398 reftex-bibfile-ignore-regexps)))
399 ;; excluded file
400 nil
401 ;; find the file
402 (reftex-locate-file x "bib" master-dir)))
403 files))
1a9461d0
CD
404 (delq nil files)))
405
406(defun reftex-replace-label-list-segment (old insert &optional entirely)
79d7167f
TH
407 "Replace the segment in OLD which corresponds to INSERT.
408Works with side effects, directly changes old.
409If ENTIRELY is t, just return INSERT.
410This function also makes sure the old toc markers do not point anywhere."
1a9461d0
CD
411
412 (cond
413 (entirely
414 (reftex-silence-toc-markers old (length old))
415 insert)
416 (t (let* ((new old)
417 (file (nth 1 (car insert)))
418 (eof-list (member (list 'eof file) old))
419 (bof-list (member (list 'bof file) old))
420 n)
421 (if (not (and bof-list eof-list))
422 (error "Cannot splice")
423 ;; Splice
424 (reftex-silence-toc-markers bof-list (- (length bof-list)
425 (length eof-list)))
426 (setq n (- (length old) (length bof-list)))
427 (setcdr (nthcdr n new) (cdr insert))
428 (setcdr (nthcdr (1- (length new)) new) (cdr eof-list)))
429 new))))
430
41116c5a 431;;;###autoload
1a9461d0 432(defun reftex-section-info (file)
79d7167f
TH
433 "Return a section entry for the current match.
434Careful: This function expects the match-data to be still in place!"
1a9461d0
CD
435 (let* ((marker (set-marker (make-marker) (1- (match-beginning 3))))
436 (macro (reftex-match-string 3))
3666daf6
CD
437 (prefix (save-match-data
438 (if (string-match "begin{\\([^}]+\\)}" macro)
439 (match-string 1 macro))))
440 (level-exp (cdr (assoc macro reftex-section-levels-all)))
28b707f9 441 (level (if (symbolp level-exp)
3666daf6
CD
442 (save-match-data (funcall level-exp))
443 level-exp))
444 (star (= ?* (char-after (match-end 3))))
445 (unnumbered (or star (< level 0)))
446 (level (abs level))
1a9461d0 447 (section-number (reftex-section-number level unnumbered))
887a0b34 448 (text1 (save-match-data
3666daf6
CD
449 (save-excursion
450 (reftex-context-substring prefix))))
1a9461d0
CD
451 (literal (buffer-substring-no-properties
452 (1- (match-beginning 3))
453 (min (point-max) (+ (match-end 0) (length text1) 1))))
887a0b34 454 ;; Literal can be too short since text1 too short. No big problem.
1a9461d0
CD
455 (text (reftex-nicify-text text1)))
456
457 ;; Add section number and indentation
458 (setq text
459 (concat
460 (make-string (* reftex-level-indent level) ?\ )
461 (if (nth 1 reftex-label-menu-flags) ; section number flag
462 (concat section-number " "))
3666daf6 463 (if prefix (concat (capitalize prefix) ": ") "")
1a9461d0
CD
464 text))
465 (list 'toc "toc" text file marker level section-number
466 literal (marker-position marker))))
467
41116c5a 468;;;###autoload
1a9461d0 469(defun reftex-ensure-index-support (&optional abort)
79d7167f
TH
470 "When index support is turned off, ask to turn it on and
471set the current prefix argument so that `reftex-access-scan-info'
472will rescan the entire document."
1a9461d0
CD
473 (cond
474 (reftex-support-index t)
475 ((y-or-n-p "Turn on index support and rescan entire document? ")
476 (setq reftex-support-index 'demanded
3666daf6 477 current-prefix-arg '(16)))
1a9461d0 478 (t (if abort
3666daf6
CD
479 (error "No index support")
480 (message "No index support")
481 (ding)
482 (sit-for 1)))))
1a9461d0 483
41116c5a 484;;;###autoload
1a9461d0
CD
485(defun reftex-index-info-safe (file)
486 (reftex-with-special-syntax
487 (reftex-index-info file)))
488
489(defvar test-dummy)
41116c5a 490;;;###autoload
1a9461d0 491(defun reftex-index-info (file)
79d7167f
TH
492 "Return an index entry for the current match.
493Careful: This function expects the match-data to be still in place!"
1a9461d0
CD
494 (catch 'exit
495 (let* ((macro (reftex-match-string 10))
3666daf6
CD
496 (bom (match-beginning 10))
497 (boa (match-end 10))
498 (entry (or (assoc macro reftex-index-macro-alist)
499 (throw 'exit nil)))
500 (exclude (nth 3 entry))
501 ;; The following is a test if this match should be excluded
502 (test-dummy (and (fboundp exclude)
503 (funcall exclude)
504 (throw 'exit nil)))
505 (itag (nth 1 entry))
506 (prefix (nth 2 entry))
887a0b34 507 (index-tag
3666daf6
CD
508 (cond ((stringp itag) itag)
509 ((integerp itag)
510 (progn (goto-char boa)
511 (or (reftex-nth-arg itag (nth 6 entry)) "idx")))
512 (t "idx")))
513 (arg (or (progn (goto-char boa)
514 (reftex-nth-arg (nth 5 entry) (nth 6 entry)))
515 ""))
516 (end-of-args (progn (goto-char boa)
517 (reftex-move-over-touching-args)
518 (point)))
519 (end-of-context (progn (skip-chars-forward "^ \t\n\r") (point)))
520 (begin-of-context
521 (progn (goto-char bom)
522 (skip-chars-backward "^ \t\r\n")
523 (point)))
524 (context (buffer-substring-no-properties
525 begin-of-context end-of-context))
526 (key-end (if (string-match reftex-index-key-end-re arg)
527 (1+ (match-beginning 0))))
528 (rawkey (substring arg 0 key-end))
887a0b34 529
3666daf6
CD
530 (key (if prefix (concat prefix rawkey) rawkey))
531 (sortkey (downcase key))
887a0b34 532 (showkey (mapconcat 'identity
3666daf6
CD
533 (split-string key reftex-index-level-re)
534 " ! ")))
1a9461d0
CD
535 (goto-char end-of-args)
536 ;; 0 1 2 3 4 5 6 7 8 9
537 (list 'index index-tag context file bom arg key showkey sortkey key-end))))
887a0b34 538
41116c5a 539;;;###autoload
1a9461d0 540(defun reftex-short-context (env parse &optional bound derive)
79d7167f 541 "Get about one line of useful context for the label definition at point."
1a9461d0
CD
542
543 (if (consp parse)
544 (setq parse (if derive (cdr parse) (car parse))))
545
546 (reftex-nicify-text
547
548 (cond
549
550 ((null parse)
551 (save-excursion
552 (reftex-context-substring)))
553
554 ((eq parse t)
555 (if (string= env "section")
556 ;; special treatment for section labels
557 (save-excursion
558 (if (and (re-search-backward reftex-section-or-include-regexp
559 (point-min) t)
560 (match-end 2))
561 (progn
562 (goto-char (match-end 0))
563 (reftex-context-substring))
564 (if reftex-active-toc
565 (progn
566 (string-match "{\\([^}]*\\)" (nth 7 reftex-active-toc))
567 (match-string 1 (nth 7 reftex-active-toc)))
568 "SECTION HEADING NOT FOUND")))
569 (save-excursion
3666daf6
CD
570 (goto-char reftex-default-context-position)
571 (unless (eq (string-to-char env) ?\\)
572 (reftex-move-over-touching-args))
1a9461d0
CD
573 (reftex-context-substring))))
574
575 ((stringp parse)
576 (save-excursion
577 (if (re-search-backward parse bound t)
578 (progn
579 (goto-char (match-end 0))
580 (reftex-context-substring))
581 "NO MATCH FOR CONTEXT REGEXP")))
582
583 ((integerp parse)
584 (or (save-excursion
585 (goto-char reftex-default-context-position)
586 (reftex-nth-arg
587 parse
588 (nth 6 (assoc env reftex-env-or-mac-alist))))
589 ""))
590
591 ((fboundp parse)
592 ;; A hook function. Call it.
593 (save-excursion
594 (condition-case error-var
595 (funcall parse env)
596 (error (format "HOOK ERROR: %s" (cdr error-var))))))
597 (t
5181ff9f 598 "INVALID VALUE OF PARSE"))))
1a9461d0 599
41116c5a 600;;;###autoload
1a9461d0 601(defun reftex-where-am-I ()
79d7167f
TH
602 "Return the docstruct entry above point.
603Actually returns a cons cell in which the cdr is a flag indicating
604if the information is exact (t) or approximate (nil)."
1a9461d0
CD
605
606 (let ((docstruct (symbol-value reftex-docstruct-symbol))
3b919c9f 607 (cnt 0) rtn rtn-if-no-other
1a9461d0
CD
608 found)
609 (save-excursion
610 (while (not rtn)
611 (incf cnt)
612 (setq found (re-search-backward (reftex-everything-regexp) nil t))
613 (setq rtn
614 (cond
615 ((not found)
616 ;; no match
617 (or
618 (car (member (list 'bof (buffer-file-name)) docstruct))
619 (not (setq cnt 2))
620 (assq 'bof docstruct) ;; for safety reasons
621 'corrupted))
622 ((match-end 1)
623 ;; Label
624 (assoc (reftex-match-string 1)
625 (symbol-value reftex-docstruct-symbol)))
626 ((match-end 3)
627 ;; Section
628 (goto-char (1- (match-beginning 3)))
629 (let* ((list (member (list 'bof (buffer-file-name))
630 docstruct))
631 (endelt (car (member (list 'eof (buffer-file-name))
632 list)))
633 rtn1)
634 (while (and list (not (eq endelt (car list))))
635 (if (and (eq (car (car list)) 'toc)
636 (string= (buffer-file-name)
637 (nth 3 (car list))))
638 (cond
639 ((equal (point)
640 (or (and (markerp (nth 4 (car list)))
641 (marker-position (nth 4 (car list))))
642 (nth 8 (car list))))
643 ;; Fits with marker position or recorded position
644 (setq rtn1 (car list) list nil))
645 ((looking-at (reftex-make-regexp-allow-for-ctrl-m
646 (nth 7 (car list))))
3b919c9f 647 ;; Same title: remember, but keep looking
3666daf6 648 (setq rtn-if-no-other (car list)))))
1a9461d0
CD
649 (pop list))
650 rtn1))
651 ((match-end 7)
652 ;; Input or include...
653 (car
654 (member (list 'eof (reftex-locate-file
655 (reftex-match-string 7) "tex"
3666daf6 656 (cdr (assq 'master-dir docstruct))))
1a9461d0 657 docstruct)))
3666daf6
CD
658 ((match-end 9)
659 (assq 'appendix (symbol-value reftex-docstruct-symbol)))
660 ((match-end 10)
661 ;; Index entry
662 (when reftex-support-index
887a0b34 663 (let* ((index-info (save-excursion
3666daf6
CD
664 (reftex-index-info-safe nil)))
665 (list (member (list 'bof (buffer-file-name))
666 docstruct))
667 (endelt (car (member (list 'eof (buffer-file-name))
668 list)))
669 dist last-dist last (n 0))
670 ;; Check all index entries with equal text
671 (while (and list (not (eq endelt (car list))))
672 (when (and (eq (car (car list)) 'index)
887a0b34 673 (string= (nth 2 index-info)
3666daf6
CD
674 (nth 2 (car list))))
675 (incf n)
676 (setq dist (abs (- (point) (nth 4 (car list)))))
677 (if (or (not last-dist) (< dist last-dist))
678 (setq last-dist dist last (car list))))
679 (setq list (cdr list)))
680 ;; We are sure if we have only one, or a zero distance
681 (cond ((or (= n 1) (equal dist 0)) last)
682 ((> n 1) (setq cnt 2) last)
683 (t nil)))))
684 ((match-end 11)
1a9461d0
CD
685 (save-excursion
686 (goto-char (match-end 11))
687 (assoc (reftex-no-props
688 (reftex-nth-arg-wrapper
689 (reftex-match-string 11)))
690 (symbol-value reftex-docstruct-symbol))))
691 (t
692 (error "This should not happen (reftex-where-am-I)"))))))
3b919c9f
CD
693 ;; Check if there was only a by-name match for the section.
694 (when (and (not rtn) rtn-if-no-other)
695 (setq rtn rtn-if-no-other
3666daf6 696 cnt 2))
1a9461d0
CD
697 (cons rtn (eq cnt 1))))
698
41116c5a 699;;;###autoload
1a9461d0
CD
700(defun reftex-notice-new (&optional n force)
701 "Hook to handshake with RefTeX after something new has been inserted."
702 ;; Add a new entry to the docstruct list. If it is a section, renumber
703 ;; the following sections.
3666daf6 704 ;; FIXME: Put in a WHAT parameter and search backward until one is found.
1a9461d0
CD
705 ;; When N is given, go back that many matches of reftex-everything-regexp
706 ;; When FORCE is non-nil, also insert if `reftex-where-am-I' was uncertain.
707 (condition-case nil
708 (catch 'exit
3666daf6
CD
709 (unless reftex-mode (throw 'exit nil))
710 (reftex-access-scan-info)
711 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
712 here-I-am appendix tail entry star level
713 section-number context)
1a9461d0
CD
714
715 (save-excursion
716 (when (re-search-backward (reftex-everything-regexp) nil t (or n 1))
717
3666daf6
CD
718 ;; Find where we are
719 (setq here-I-am (reftex-where-am-I))
720 (or here-I-am (throw 'exit nil))
721 (unless (or force (cdr here-I-am)) (throw 'exit nil))
722 (setq tail (memq (car here-I-am) docstruct))
723 (or tail (throw 'exit nil))
724 (setq reftex-active-toc (reftex-last-assoc-before-elt
725 'toc (car here-I-am) docstruct)
726 appendix (reftex-last-assoc-before-elt
727 'appendix (car here-I-am) docstruct))
728
729 ;; Initialize section numbers
730 (if (eq (car (car here-I-am)) 'appendix)
731 (reftex-init-section-numbers nil t)
732 (reftex-init-section-numbers reftex-active-toc appendix))
733
734 ;; Match the section command
735 (when (re-search-forward (reftex-everything-regexp) nil t)
736 (cond
737 ((match-end 1)
738 (push (reftex-label-info (reftex-match-string 1) buffer-file-name)
739 (cdr tail)))
740
741 ((match-end 3)
742 (setq star (= ?* (char-after (match-end 3)))
743 entry (reftex-section-info (buffer-file-name))
744 level (nth 5 entry))
745 ;; Insert the section info
746 (push entry (cdr tail))
887a0b34 747
3666daf6
CD
748 ;; We are done unless we use section numbers
749 (unless (nth 1 reftex-label-menu-flags) (throw 'exit nil))
750
751 ;; Update the remaining toc items
752 (setq tail (cdr tail))
753 (while (and (setq tail (memq (assq 'toc (cdr tail)) tail))
754 (setq entry (car tail))
755 (>= (nth 5 entry) level))
756 (setq star (string-match "\\*" (nth 6 entry))
757 context (nth 2 entry)
758 section-number
759 (reftex-section-number (nth 5 entry) star))
760 (when (string-match "\\`\\([ \t]*\\)\\([.0-9A-Z]+\\)\\(.*\\)"
761 context)
762 (when (and (not appendix)
763 (>= (string-to-char (match-string 2)) ?A))
91af3942 764 ;; Just entered the appendix. Get out.
3666daf6
CD
765 (throw 'exit nil))
766
767 ;; Change the section number.
768 (setf (nth 2 entry)
769 (concat (match-string 1 context)
770 section-number
771 (match-string 3 context))))))
772 ((match-end 10)
773 ;; Index entry
774 (and reftex-support-index
775 (setq entry (reftex-index-info-safe buffer-file-name))
6b31e6b1 776 ;; FIXME: (add-to-list 'reftex--index-tags (nth 1 index-entry))
3666daf6 777 (push entry (cdr tail))))))))))
887a0b34 778
1a9461d0
CD
779 (error nil))
780 )
781
782(defsubst reftex-move-to-previous-arg (&optional bound)
79d7167f
TH
783 "Assuming that we are in front of a macro argument,
784move backward to the closing parenthesis of the previous argument.
785This function understands the splitting of macros over several lines
786in TeX."
1a9461d0
CD
787 (cond
788 ;; Just to be quick:
789 ((memq (preceding-char) '(?\] ?\})))
790 ;; Do a search
791 ((and reftex-allow-detached-macro-args
3666daf6
CD
792 (re-search-backward
793 "[]}][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t))
1a9461d0
CD
794 (goto-char (1+ (match-beginning 0)))
795 t)
796 (t nil)))
797
41116c5a 798;;;###autoload
1a9461d0 799(defun reftex-what-macro-safe (which &optional bound)
79d7167f 800 "Call `reftex-what-macro' with special syntax table."
1a9461d0
CD
801 (reftex-with-special-syntax
802 (reftex-what-macro which bound)))
803
41116c5a 804;;;###autoload
1a9461d0 805(defun reftex-what-macro (which &optional bound)
79d7167f
TH
806 "Find out if point is within the arguments of any TeX-macro.
807The return value is either (\"\\macro\" . (point)) or a list of them.
808
809If WHICH is nil, immediately return nil.
810If WHICH is 1, return innermost enclosing macro.
811If WHICH is t, return list of all macros enclosing point.
812If WHICH is a list of macros, look only for those macros and return the
813 name of the first macro in this list found to enclose point.
814If the optional BOUND is an integer, bound backwards directed
815 searches to this point. If it is nil, limit to nearest \\section -
816 like statement.
817
818This function is pretty stable, but can be fooled if the text contains
819things like \\macro{aa}{bb} where \\macro is defined to take only one
820argument. As RefTeX cannot know this, the string \"bb\" would still be
821considered an argument of macro \\macro."
1a9461d0
CD
822 (unless reftex-section-regexp (reftex-compile-variables))
823 (catch 'exit
824 (if (null which) (throw 'exit nil))
825 (let ((bound (or bound (save-excursion (re-search-backward
826 reftex-section-regexp nil 1)
827 (point))))
828 pos cmd-list cmd cnt cnt-opt entry)
829 (save-restriction
830 (save-excursion
de558d10 831 (narrow-to-region (max (point-min) bound) (point-max))
1a9461d0
CD
832 ;; move back out of the current parenthesis
833 (while (condition-case nil
5d8e0d5d
SM
834 (let ((forward-sexp-function nil))
835 (up-list -1) t)
1a9461d0
CD
836 (error nil))
837 (setq cnt 1 cnt-opt 0)
838 ;; move back over any touching sexps
839 (while (and (reftex-move-to-previous-arg bound)
3666daf6 840 (condition-case nil
5d8e0d5d
SM
841 (let ((forward-sexp-function nil))
842 (backward-sexp) t)
3666daf6
CD
843 (error nil)))
844 (if (eq (following-char) ?\[) (incf cnt-opt))
1a9461d0
CD
845 (incf cnt))
846 (setq pos (point))
847 (when (and (or (= (following-char) ?\[)
848 (= (following-char) ?\{))
849 (re-search-backward "\\\\[*a-zA-Z]+\\=" nil t))
850 (setq cmd (reftex-match-string 0))
3666daf6
CD
851 (when (looking-at "\\\\begin{[^}]*}")
852 (setq cmd (reftex-match-string 0)
853 cnt (1- cnt)))
854 ;; This does ignore optional arguments. Very hard to fix.
855 (when (setq entry (assoc cmd reftex-env-or-mac-alist))
856 (if (> cnt (or (nth 4 entry) 100))
857 (setq cmd nil)))
1a9461d0 858 (cond
3666daf6
CD
859 ((null cmd))
860 ((eq t which)
861 (push (cons cmd (point)) cmd-list))
862 ((or (eq 1 which) (member cmd which))
863 (throw 'exit (cons cmd (point))))))
1a9461d0
CD
864 (goto-char pos)))
865 (nreverse cmd-list)))))
866
41116c5a 867;;;###autoload
1a9461d0 868(defun reftex-what-environment (which &optional bound)
79d7167f
TH
869 "Find out if point is inside a LaTeX environment.
870The return value is (e.g.) either (\"equation\" . (point)) or a list of
871them.
872
873If WHICH is nil, immediately return nil.
874If WHICH is 1, return innermost enclosing environment.
875If WHICH is t, return list of all environments enclosing point.
876If WHICH is a list of environments, look only for those environments and
877 return the name of the first environment in this list found to enclose
878 point.
879
880If the optional BOUND is an integer, bound backwards directed searches to
881this point. If it is nil, limit to nearest \\section - like statement."
1a9461d0
CD
882 (unless reftex-section-regexp (reftex-compile-variables))
883 (catch 'exit
884 (save-excursion
885 (if (null which) (throw 'exit nil))
886 (let ((bound (or bound (save-excursion (re-search-backward
887 reftex-section-regexp nil 1)
888 (point))))
889 env-list end-list env)
890 (while (re-search-backward "\\\\\\(begin\\|end\\){\\([^}]+\\)}"
891 bound t)
892 (setq env (buffer-substring-no-properties
893 (match-beginning 2) (match-end 2)))
894 (cond
895 ((string= (match-string 1) "end")
3666daf6 896 (push env end-list))
1a9461d0
CD
897 ((equal env (car end-list))
898 (setq end-list (cdr end-list)))
899 ((eq t which)
900 (push (cons env (point)) env-list))
901 ((or (eq 1 which) (member env which))
902 (throw 'exit (cons env (point))))))
903 (nreverse env-list)))))
904
41116c5a 905;;;###autoload
1a9461d0 906(defun reftex-what-special-env (which &optional bound)
79d7167f
TH
907 "Run the special environment parsers and return the matches.
908
909The return value is (e.g.) either (\"my-parser-function\" . (point))
910or a list of them.
1a9461d0 911
79d7167f
TH
912If WHICH is nil, immediately return nil.
913If WHICH is 1, return innermost enclosing environment.
914If WHICH is t, return list of all environments enclosing point.
915If WHICH is a list of environments, look only for those environments and
916 return the name of the first environment in this list found to enclose
917 point."
1a9461d0
CD
918 (unless reftex-section-regexp (reftex-compile-variables))
919 (catch 'exit
920 (save-excursion
921 (if (null reftex-special-env-parsers) (throw 'exit nil))
922 (if (null which) (throw 'exit nil))
923 (let ((bound (or bound (save-excursion (re-search-backward
924 reftex-section-regexp nil 1)
925 (point))))
3666daf6
CD
926 (fun-list (if (listp which)
927 (mapcar (lambda (x) (if (memq x which) x nil))
928 reftex-special-env-parsers)
929 reftex-special-env-parsers))
1a9461d0 930 specials rtn)
3666daf6 931 ;; Call all functions
887a0b34 932 (setq specials (mapcar
3666daf6
CD
933 (lambda (fun)
934 (save-excursion
935 (setq rtn (and fun (funcall fun bound)))
936 (if rtn (cons (symbol-name fun) rtn) nil)))
937 fun-list))
938 ;; Delete the non-matches
939 (setq specials (delq nil specials))
940 ;; Sort
941 (setq specials (sort specials (lambda (a b) (> (cdr a) (cdr b)))))
887a0b34 942 (if (eq which t)
3666daf6
CD
943 specials
944 (car specials))))))
1a9461d0 945
6b31e6b1 946(defsubst reftex-move-to-next-arg (&optional _ignore)
79d7167f
TH
947 "Assuming that we are at the end of a macro name or a macro argument,
948move forward to the opening parenthesis of the next argument.
949This function understands the splitting of macros over several lines
950in TeX."
1a9461d0
CD
951 (cond
952 ;; Just to be quick:
953 ((memq (following-char) '(?\[ ?\{)))
954 ;; Do a search
955 ((and reftex-allow-detached-macro-args
3666daf6 956 (looking-at "[ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*[[{]"))
1a9461d0
CD
957 (goto-char (1- (match-end 0)))
958 t)
959 (t nil)))
960
961(defun reftex-nth-arg-wrapper (key)
962 (let ((entry (assoc key reftex-env-or-mac-alist)))
963 (reftex-nth-arg (nth 5 entry) (nth 6 entry))))
964
41116c5a 965;;;###autoload
1a9461d0 966(defun reftex-nth-arg (n &optional opt-args)
79d7167f
TH
967 "Return the Nth following {} or [] parentheses content.
968OPT-ARGS is a list of argument numbers which are optional."
1a9461d0
CD
969
970 ;; If we are sitting at a macro start, skip to end of macro name.
971 (and (eq (following-char) ?\\) (skip-chars-forward "a-zA-Z*\\\\"))
972
973 (if (= n 1000)
974 ;; Special case: Skip all touching arguments
975 (progn
3666daf6
CD
976 (reftex-move-over-touching-args)
977 (reftex-context-substring))
1a9461d0
CD
978
979 ;; Do the real thing.
980 (let ((cnt 1))
887a0b34 981
1a9461d0 982 (when (reftex-move-to-next-arg)
887a0b34 983
3666daf6
CD
984 (while (< cnt n)
985 (while (and (member cnt opt-args)
986 (eq (following-char) ?\{))
987 (incf cnt))
988 (when (< cnt n)
989 (unless (and (condition-case nil
990 (or (forward-list 1) t)
991 (error nil))
992 (reftex-move-to-next-arg)
993 (incf cnt))
994 (setq cnt 1000))))
995
996 (while (and (memq cnt opt-args)
997 (eq (following-char) ?\{))
998 (incf cnt)))
1a9461d0 999 (if (and (= n cnt)
3666daf6
CD
1000 (> (skip-chars-forward "{\\[") 0))
1001 (reftex-context-substring)
1002 nil))))
1a9461d0 1003
41116c5a 1004;;;###autoload
1a9461d0
CD
1005(defun reftex-move-over-touching-args ()
1006 (condition-case nil
1007 (while (memq (following-char) '(?\[ ?\{))
3666daf6 1008 (forward-list 1))
887a0b34 1009 (error nil)))
1a9461d0 1010
7c4d13cc 1011(defun reftex-context-substring (&optional to-end)
79d7167f
TH
1012 "Return up to 150 chars from point.
1013When point is just after a { or [, limit string to matching parenthesis"
1a9461d0 1014 (cond
7c4d13cc
CD
1015 (to-end
1016 ;; Environment - find next \end
1017 (buffer-substring-no-properties
1018 (point)
1019 (min (+ (point) 150)
3666daf6
CD
1020 (save-match-data
1021 ;; FIXME: This is not perfect
1022 (if (re-search-forward "\\\\end{" nil t)
1023 (match-beginning 0)
1024 (point-max))))))
5d8e0d5d 1025 ((memq (preceding-char) '(?\{ ?\[))
1a9461d0
CD
1026 ;; Inside a list - get only the list.
1027 (buffer-substring-no-properties
1028 (point)
1029 (min (+ (point) 150)
1030 (point-max)
1031 (condition-case nil
5d8e0d5d 1032 (let ((forward-sexp-function nil)) ;Unneeded fanciness.
1a9461d0
CD
1033 (up-list 1)
1034 (1- (point)))
1035 (error (point-max))))))
1036 (t
1037 ;; no list - just grab 150 characters
887a0b34 1038 (buffer-substring-no-properties (point)
3666daf6 1039 (min (+ (point) 150) (point-max))))))
1a9461d0
CD
1040
1041;; Variable holding the vector with section numbers
28b707f9 1042(defvar reftex-section-numbers (make-vector reftex-max-section-depth 0))
1a9461d0 1043
41116c5a 1044;;;###autoload
1a9461d0 1045(defun reftex-init-section-numbers (&optional toc-entry appendix)
79d7167f 1046 "Initialize the section numbers with zeros or with what is found in the TOC-ENTRY."
1a9461d0
CD
1047 (let* ((level (or (nth 5 toc-entry) -1))
1048 (numbers (nreverse (split-string (or (nth 6 toc-entry) "") "\\.")))
1049 (depth (1- (length reftex-section-numbers)))
1050 (i depth) number-string)
1051 (while (>= i 0)
1052 (if (> i level)
1053 (aset reftex-section-numbers i 0)
3666daf6
CD
1054 (setq number-string (or (car numbers) "0"))
1055 (if (string-match "\\`[A-Z]\\'" number-string)
1056 (aset reftex-section-numbers i
1057 (- (string-to-char number-string) ?A -1))
027a4b6b 1058 (aset reftex-section-numbers i (string-to-number number-string)))
1a9461d0
CD
1059 (pop numbers))
1060 (decf i)))
1061 (put 'reftex-section-numbers 'appendix appendix))
1062
41116c5a 1063;;;###autoload
1a9461d0 1064(defun reftex-section-number (&optional level star)
79d7167f
TH
1065 "Return a string with the current section number.
1066When LEVEL is non-nil, increase section numbers on that level."
1a9461d0 1067 (let* ((depth (1- (length reftex-section-numbers))) idx n (string "")
3666daf6
CD
1068 (appendix (get 'reftex-section-numbers 'appendix))
1069 (partspecial (and (not reftex-part-resets-chapter)
1070 (equal level 0))))
3b919c9f
CD
1071 ;; partspecial means, this is a part statement.
1072 ;; Parts do not reset the chapter counter, and the part number is
1073 ;; not included in the numbering of other sectioning levels.
1a9461d0
CD
1074 (when level
1075 (when (and (> level -1) (not star))
887a0b34 1076 (aset reftex-section-numbers
3666daf6 1077 level (1+ (aref reftex-section-numbers level))))
1a9461d0
CD
1078 (setq idx (1+ level))
1079 (when (not star)
3666daf6
CD
1080 (while (<= idx depth)
1081 (if (or (not partspecial)
1082 (not (= idx 1)))
1083 (aset reftex-section-numbers idx 0))
1084 (incf idx))))
3b919c9f 1085 (if partspecial
3666daf6
CD
1086 (setq string (concat "Part " (reftex-roman-number
1087 (aref reftex-section-numbers 0))))
3b919c9f
CD
1088 (setq idx (if reftex-part-resets-chapter 0 1))
1089 (while (<= idx depth)
3666daf6
CD
1090 (setq n (aref reftex-section-numbers idx))
1091 (if (not (and partspecial (not (equal string ""))))
1092 (setq string (concat string (if (not (string= string "")) "." "")
1093 (int-to-string n))))
1094 (incf idx))
3b919c9f 1095 (save-match-data
3666daf6
CD
1096 (if (string-match "\\`\\([@0]\\.\\)+" string)
1097 (setq string (replace-match "" nil nil string)))
1098 (if (string-match "\\(\\.0\\)+\\'" string)
1099 (setq string (replace-match "" nil nil string)))
1100 (if (and appendix
1101 (string-match "\\`[0-9]+" string))
887a0b34 1102 (setq string
3666daf6
CD
1103 (concat
1104 (char-to-string
027a4b6b 1105 (1- (+ ?A (string-to-number (match-string 0 string)))))
3666daf6 1106 (substring string (match-end 0))))))
3b919c9f 1107 (if star
3666daf6
CD
1108 (concat (make-string (1- (length string)) ?\ ) "*")
1109 string))))
3b919c9f
CD
1110
1111(defun reftex-roman-number (n)
79d7167f 1112 "Return as a string the roman number equal to N."
3b919c9f 1113 (let ((nrest n)
3666daf6
CD
1114 (string "")
1115 (list '((1000 . "M") ( 900 . "CM") ( 500 . "D") ( 400 . "CD")
1116 ( 100 . "C") ( 90 . "XC") ( 50 . "L") ( 40 . "XL")
1117 ( 10 . "X") ( 9 . "IX") ( 5 . "V") ( 4 . "IV")
1118 ( 1 . "I")))
1119 listel i s)
3b919c9f
CD
1120 (while (>= nrest 1)
1121 (setq listel (pop list)
3666daf6
CD
1122 i (car listel)
1123 s (cdr listel))
3b919c9f 1124 (while (>= nrest i)
3666daf6
CD
1125 (setq string (concat string s)
1126 nrest (- nrest i))))
3b919c9f 1127 string))
1a9461d0 1128
4f595e15
RA
1129(provide 'reftex-parse)
1130
1a9461d0 1131;;; reftex-parse.el ends here
41116c5a
GM
1132
1133;; Local Variables:
1134;; generated-autoload-file: "reftex.el"
1135;; End: