* lisp/emacs-lisp/package.el: Some speed optimizations on menu refresh
[emacs.git] / lisp / textmodes / reftex-parse.el
blob7f186afc27cfc53978e79ff5e4f20d91d1118295
1 ;;; reftex-parse.el --- parser functions for RefTeX
3 ;; Copyright (C) 1997-2015 Free Software Foundation, Inc.
5 ;; Author: Carsten Dominik <dominik@science.uva.nl>
6 ;; Maintainer: auctex-devel@gnu.org
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
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.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;; Commentary:
25 ;;; Code:
27 (eval-when-compile (require 'cl))
29 (require 'reftex)
31 (defmacro reftex-with-special-syntax (&rest body)
32 `(let ((saved-syntax (syntax-table)))
33 (unwind-protect
34 (progn
35 (set-syntax-table reftex-syntax-table)
36 (let ((case-fold-search nil))
37 ,@body))
38 (set-syntax-table saved-syntax))))
40 ;;;###autoload
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))))
47 ;;;###autoload
48 (defun reftex-parse-all ()
49 "Re-parse entire document."
50 (interactive)
51 (reftex-access-scan-info '(16)))
53 (defvar reftex--index-tags)
55 ;;;###autoload
56 (defun reftex-do-parse (rescan &optional file)
57 "Do a document rescan.
58 When allowed, do only a partial scan from FILE."
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)))
67 ;; Partial scans only when allowed
68 (unless reftex-enable-partial-scans
69 (setq rescan 1))
71 ;; Do the scanning.
73 (let* ((old-list (symbol-value reftex-docstruct-symbol))
74 (master (reftex-TeX-master-file))
75 (true-master (file-truename master))
76 (master-dir (file-name-as-directory (file-name-directory master)))
77 (file (or file (buffer-file-name)))
78 (true-file (file-truename file))
79 (bibview-cache (assq 'bibview-cache old-list))
80 (reftex--index-tags (cdr (assq 'index-tags old-list)))
81 from-file appendix docstruct tmp)
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))
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)"))))
99 ;; Reset index-tags if we scan everything
100 (if (equal rescan 1) (setq reftex--index-tags nil))
102 ;; Find active toc entry and initialize section-numbers
103 (setq reftex-active-toc (reftex-last-assoc-before-elt
104 'toc (list 'bof from-file) old-list)
105 appendix (reftex-last-assoc-before-elt
106 'appendix (list 'bof from-file) old-list))
108 (reftex-init-section-numbers reftex-active-toc appendix)
110 (if (eq rescan 1)
111 (message "Scanning entire document...")
112 (message "Scanning document from %s..." from-file))
114 (reftex-with-special-syntax
115 (save-window-excursion
116 (save-excursion
117 (unwind-protect
118 (setq docstruct
119 (reftex-parse-from-file
120 from-file docstruct master-dir))
121 (reftex-kill-temporary-buffers)))))
123 (message "Scanning document... done")
125 ;; Turn the list around.
126 (setq docstruct (nreverse docstruct))
128 ;; Set or insert
129 (setq docstruct (reftex-replace-label-list-segment
130 old-list docstruct (eq rescan 1)))
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)))
145 (and reftex--index-tags
146 (setq reftex--index-tags (sort reftex--index-tags 'string<)))
147 (let ((index-tag-cell (assq 'index-tags docstruct)))
148 (if index-tag-cell
149 (setcdr index-tag-cell reftex--index-tags)
150 (push (cons 'index-tags reftex--index-tags) docstruct)))
151 (unless (assq 'xr docstruct)
152 (let* ((allxr (reftex-all-assq 'xr-doc docstruct))
153 (alist (mapcar
154 (lambda (x)
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
165 (concat "\\`\\("
166 (mapconcat 'identity allprefix "\\|")
167 "\\)")
168 "\\\\\\\\\\\\"))) ; this will never match
169 (push (list 'xr alist regexp) docstruct)))
171 (set reftex-docstruct-symbol docstruct)
172 (put reftex-docstruct-symbol 'modified t)))
174 ;;;###autoload
175 (defun reftex-everything-regexp ()
176 (if reftex-support-index
177 reftex-everything-regexp
178 reftex-everything-regexp-no-index))
180 ;; NB this is a global autoload - see reftex.el.
181 ;;;###autoload
182 (defun reftex-all-document-files (&optional relative)
183 "Return a list of all files belonging to the current document.
184 When RELATIVE is non-nil, give file names relative to directory
185 of 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)))
199 ;; Bound in the caller, reftex-do-parse.
200 (defun reftex-parse-from-file (file docstruct master-dir)
201 "Scan the buffer for labels and save them in a list."
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)
209 (catch 'exit
210 (setq file-found (reftex-locate-file file "tex" master-dir))
211 (if (and (not file-found)
212 (setq buf (reftex-get-buffer-visiting file)))
213 (setq file-found (buffer-file-name buf)))
215 (unless file-found
216 (push (list 'file-error file) docstruct)
217 (throw 'exit nil))
219 (save-excursion
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)))))
228 ;; Begin of file mark
229 (setq file (buffer-file-name))
230 (push (list 'bof file) docstruct)
232 (reftex-with-special-syntax
233 (save-excursion
234 (save-restriction
235 (widen)
236 (goto-char 1)
238 (while (re-search-forward regexp nil t)
240 (cond
242 ((match-end 1)
243 ;; It is a label
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))
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)))
255 (push (reftex-label-info (reftex-match-string 1) file bound)
256 docstruct)))
258 ((match-end 3)
259 ;; It is a section
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))
271 ;; Insert in List
272 (setq toc-entry (funcall reftex-section-info-function file))
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)))
283 (push toc-entry docstruct)
284 (setq reftex-active-toc toc-entry)))
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
290 (unless (delq nil (mapcar
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))))
299 ((match-end 9)
300 ;; Appendix starts here
301 (reftex-init-section-numbers nil t)
302 (push (cons 'appendix t) docstruct))
304 ((match-end 10)
305 ;; Index entry
306 (when reftex-support-index
307 (setq index-entry (reftex-index-info file))
308 (when index-entry
309 (add-to-list 'reftex--index-tags (nth 1 index-entry))
310 (push index-entry docstruct))))
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)")))
334 ;; Find bibliography statement
335 (when (setq tmp (reftex-locate-bibliography-files master-dir))
336 (push (cons 'bib tmp) docstruct))
338 (goto-char 1)
339 (when (re-search-forward
340 "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t)
341 (push (cons 'thebib file) docstruct))
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))
350 ;; End of file mark
351 (push (list 'eof file) docstruct)))))
353 ;; Kill the scanned buffer
354 (reftex-kill-temporary-buffers next-buf))
356 ;; Return the list
357 docstruct))
359 (defun reftex-using-biblatex-p ()
360 "Return non-nil if we are using biblatex rather than bibtex."
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
366 (re-search-forward "^[^%\n]*?\\\\usepackage.*{biblatex}" nil t))))
368 ;;;###autoload
369 (defun reftex-locate-bibliography-files (master-dir &optional files)
370 "Scan buffer for bibliography macros and return file list."
371 (unless files
372 (save-excursion
373 (goto-char (point-min))
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))))))
392 (when files
393 (setq files
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
401 ;; find the file
402 (reftex-locate-file x "bib" master-dir)))
403 files))
404 (delq nil files)))
406 (defun reftex-replace-label-list-segment (old insert &optional entirely)
407 "Replace the segment in OLD which corresponds to INSERT.
408 Works with side effects, directly changes old.
409 If ENTIRELY is t, just return INSERT.
410 This function also makes sure the old toc markers do not point anywhere."
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))
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))))
431 ;;;###autoload
432 (defun reftex-section-info (file)
433 "Return a section entry for the current match.
434 Careful: This function expects the match-data to be still in place!"
435 (let* ((marker (set-marker (make-marker) (1- (match-beginning 3))))
436 (macro (reftex-match-string 3))
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)))
441 (level (if (symbolp level-exp)
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))
447 (section-number (reftex-section-number level unnumbered))
448 (text1 (save-match-data
449 (save-excursion
450 (reftex-context-substring prefix))))
451 (literal (buffer-substring-no-properties
452 (1- (match-beginning 3))
453 (min (point-max) (+ (match-end 0) (length text1) 1))))
454 ;; Literal can be too short since text1 too short. No big problem.
455 (text (reftex-nicify-text text1)))
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 " "))
463 (if prefix (concat (capitalize prefix) ": ") "")
464 text))
465 (list 'toc "toc" text file marker level section-number
466 literal (marker-position marker))))
468 ;;;###autoload
469 (defun reftex-ensure-index-support (&optional abort)
470 "When index support is turned off, ask to turn it on and
471 set the current prefix argument so that `reftex-access-scan-info'
472 will rescan the entire document."
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
477 current-prefix-arg '(16)))
478 (t (if abort
479 (error "No index support")
480 (message "No index support")
481 (ding)
482 (sit-for 1)))))
484 ;;;###autoload
485 (defun reftex-index-info-safe (file)
486 (reftex-with-special-syntax
487 (reftex-index-info file)))
489 (defvar test-dummy)
490 ;;;###autoload
491 (defun reftex-index-info (file)
492 "Return an index entry for the current match.
493 Careful: This function expects the match-data to be still in place!"
494 (catch 'exit
495 (let* ((macro (reftex-match-string 10))
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))
507 (index-tag
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))
530 (key (if prefix (concat prefix rawkey) rawkey))
531 (sortkey (downcase key))
532 (showkey (mapconcat 'identity
533 (split-string key reftex-index-level-re)
534 " ! ")))
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))))
539 ;;;###autoload
540 (defun reftex-short-context (env parse &optional bound derive)
541 "Get about one line of useful context for the label definition at point."
543 (if (consp parse)
544 (setq parse (if derive (cdr parse) (car parse))))
546 (reftex-nicify-text
548 (cond
550 ((null parse)
551 (save-excursion
552 (reftex-context-substring)))
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
570 (goto-char reftex-default-context-position)
571 (unless (eq (string-to-char env) ?\\)
572 (reftex-move-over-touching-args))
573 (reftex-context-substring))))
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")))
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 ""))
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))))))
598 "INVALID VALUE OF PARSE"))))
600 ;;;###autoload
601 (defun reftex-where-am-I ()
602 "Return the docstruct entry above point.
603 Actually returns a cons cell in which the cdr is a flag indicating
604 if the information is exact (t) or approximate (nil)."
606 (let ((docstruct (symbol-value reftex-docstruct-symbol))
607 (cnt 0) rtn rtn-if-no-other
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
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))))
647 ;; Same title: remember, but keep looking
648 (setq rtn-if-no-other (car list)))))
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"
656 (cdr (assq 'master-dir docstruct))))
657 docstruct)))
658 ((match-end 9)
659 (assq 'appendix (symbol-value reftex-docstruct-symbol)))
660 ((match-end 10)
661 ;; Index entry
662 (when reftex-support-index
663 (let* ((index-info (save-excursion
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)
673 (string= (nth 2 index-info)
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)
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))))
692 (error "This should not happen (reftex-where-am-I)"))))))
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
696 cnt 2))
697 (cons rtn (eq cnt 1))))
699 ;;;###autoload
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.
704 ;; FIXME: Put in a WHAT parameter and search backward until one is found.
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
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)
715 (save-excursion
716 (when (re-search-backward (reftex-everything-regexp) nil t (or n 1))
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))
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))
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)))
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))
748 ;; We are done unless we use section numbers
749 (unless (nth 1 reftex-label-menu-flags) (throw 'exit nil))
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))
764 ;; Just entered the appendix. Get out.
765 (throw 'exit nil))
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))
776 ;; FIXME: (add-to-list 'reftex--index-tags (nth 1 index-entry))
777 (push entry (cdr tail))))))))))
779 (error nil))
782 (defsubst reftex-move-to-previous-arg (&optional bound)
783 "Assuming that we are in front of a macro argument,
784 move backward to the closing parenthesis of the previous argument.
785 This function understands the splitting of macros over several lines
786 in TeX."
787 (cond
788 ;; Just to be quick:
789 ((memq (preceding-char) '(?\] ?\})))
790 ;; Do a search
791 ((and reftex-allow-detached-macro-args
792 (re-search-backward
793 "[]}][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t))
794 (goto-char (1+ (match-beginning 0)))
796 (t nil)))
798 ;;;###autoload
799 (defun reftex-what-macro-safe (which &optional bound)
800 "Call `reftex-what-macro' with special syntax table."
801 (reftex-with-special-syntax
802 (reftex-what-macro which bound)))
804 ;;;###autoload
805 (defun reftex-what-macro (which &optional bound)
806 "Find out if point is within the arguments of any TeX-macro.
807 The return value is either (\"\\macro\" . (point)) or a list of them.
809 If WHICH is nil, immediately return nil.
810 If WHICH is 1, return innermost enclosing macro.
811 If WHICH is t, return list of all macros enclosing point.
812 If 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.
814 If 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.
818 This function is pretty stable, but can be fooled if the text contains
819 things like \\macro{aa}{bb} where \\macro is defined to take only one
820 argument. As RefTeX cannot know this, the string \"bb\" would still be
821 considered an argument of macro \\macro."
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
831 (narrow-to-region (max (point-min) bound) (point-max))
832 ;; move back out of the current parenthesis
833 (while (condition-case nil
834 (let ((forward-sexp-function nil))
835 (up-list -1) t)
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)
840 (condition-case nil
841 (let ((forward-sexp-function nil))
842 (backward-sexp) t)
843 (error nil)))
844 (if (eq (following-char) ?\[) (incf cnt-opt))
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))
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)))
858 (cond
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))))))
864 (goto-char pos)))
865 (nreverse cmd-list)))))
867 ;;;###autoload
868 (defun reftex-what-environment (which &optional bound)
869 "Find out if point is inside a LaTeX environment.
870 The return value is (e.g.) either (\"equation\" . (point)) or a list of
871 them.
873 If WHICH is nil, immediately return nil.
874 If WHICH is 1, return innermost enclosing environment.
875 If WHICH is t, return list of all environments enclosing point.
876 If 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.
880 If the optional BOUND is an integer, bound backwards directed searches to
881 this point. If it is nil, limit to nearest \\section - like statement."
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")
896 (push env end-list))
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)))))
905 ;;;###autoload
906 (defun reftex-what-special-env (which &optional bound)
907 "Run the special environment parsers and return the matches.
909 The return value is (e.g.) either (\"my-parser-function\" . (point))
910 or a list of them.
912 If WHICH is nil, immediately return nil.
913 If WHICH is 1, return innermost enclosing environment.
914 If WHICH is t, return list of all environments enclosing point.
915 If 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."
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))))
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))
930 specials rtn)
931 ;; Call all functions
932 (setq specials (mapcar
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)))))
942 (if (eq which t)
943 specials
944 (car specials))))))
946 (defsubst reftex-move-to-next-arg (&optional _ignore)
947 "Assuming that we are at the end of a macro name or a macro argument,
948 move forward to the opening parenthesis of the next argument.
949 This function understands the splitting of macros over several lines
950 in TeX."
951 (cond
952 ;; Just to be quick:
953 ((memq (following-char) '(?\[ ?\{)))
954 ;; Do a search
955 ((and reftex-allow-detached-macro-args
956 (looking-at "[ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*[[{]"))
957 (goto-char (1- (match-end 0)))
959 (t nil)))
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))))
965 ;;;###autoload
966 (defun reftex-nth-arg (n &optional opt-args)
967 "Return the Nth following {} or [] parentheses content.
968 OPT-ARGS is a list of argument numbers which are optional."
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*\\\\"))
973 (if (= n 1000)
974 ;; Special case: Skip all touching arguments
975 (progn
976 (reftex-move-over-touching-args)
977 (reftex-context-substring))
979 ;; Do the real thing.
980 (let ((cnt 1))
982 (when (reftex-move-to-next-arg)
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))))
996 (while (and (memq cnt opt-args)
997 (eq (following-char) ?\{))
998 (incf cnt)))
999 (if (and (= n cnt)
1000 (> (skip-chars-forward "{\\[") 0))
1001 (reftex-context-substring)
1002 nil))))
1004 ;;;###autoload
1005 (defun reftex-move-over-touching-args ()
1006 (condition-case nil
1007 (while (memq (following-char) '(?\[ ?\{))
1008 (forward-list 1))
1009 (error nil)))
1011 (defun reftex-context-substring (&optional to-end)
1012 "Return up to 150 chars from point.
1013 When point is just after a { or [, limit string to matching parenthesis"
1014 (cond
1015 (to-end
1016 ;; Environment - find next \end
1017 (buffer-substring-no-properties
1018 (point)
1019 (min (+ (point) 150)
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))))))
1025 ((memq (preceding-char) '(?\{ ?\[))
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
1032 (let ((forward-sexp-function nil)) ;Unneeded fanciness.
1033 (up-list 1)
1034 (1- (point)))
1035 (error (point-max))))))
1037 ;; no list - just grab 150 characters
1038 (buffer-substring-no-properties (point)
1039 (min (+ (point) 150) (point-max))))))
1041 ;; Variable holding the vector with section numbers
1042 (defvar reftex-section-numbers (make-vector reftex-max-section-depth 0))
1044 ;;;###autoload
1045 (defun reftex-init-section-numbers (&optional toc-entry appendix)
1046 "Initialize the section numbers with zeros or with what is found in the TOC-ENTRY."
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)
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))
1058 (aset reftex-section-numbers i (string-to-number number-string)))
1059 (pop numbers))
1060 (decf i)))
1061 (put 'reftex-section-numbers 'appendix appendix))
1063 ;;;###autoload
1064 (defun reftex-section-number (&optional level star)
1065 "Return a string with the current section number.
1066 When LEVEL is non-nil, increase section numbers on that level."
1067 (let* ((depth (1- (length reftex-section-numbers))) idx n (string "")
1068 (appendix (get 'reftex-section-numbers 'appendix))
1069 (partspecial (and (not reftex-part-resets-chapter)
1070 (equal level 0))))
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.
1074 (when level
1075 (when (and (> level -1) (not star))
1076 (aset reftex-section-numbers
1077 level (1+ (aref reftex-section-numbers level))))
1078 (setq idx (1+ level))
1079 (when (not star)
1080 (while (<= idx depth)
1081 (if (or (not partspecial)
1082 (not (= idx 1)))
1083 (aset reftex-section-numbers idx 0))
1084 (incf idx))))
1085 (if partspecial
1086 (setq string (concat "Part " (reftex-roman-number
1087 (aref reftex-section-numbers 0))))
1088 (setq idx (if reftex-part-resets-chapter 0 1))
1089 (while (<= idx depth)
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))
1095 (save-match-data
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))
1102 (setq string
1103 (concat
1104 (char-to-string
1105 (1- (+ ?A (string-to-number (match-string 0 string)))))
1106 (substring string (match-end 0))))))
1107 (if star
1108 (concat (make-string (1- (length string)) ?\ ) "*")
1109 string))))
1111 (defun reftex-roman-number (n)
1112 "Return as a string the roman number equal to N."
1113 (let ((nrest n)
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)
1120 (while (>= nrest 1)
1121 (setq listel (pop list)
1122 i (car listel)
1123 s (cdr listel))
1124 (while (>= nrest i)
1125 (setq string (concat string s)
1126 nrest (- nrest i))))
1127 string))
1129 (provide 'reftex-parse)
1131 ;;; reftex-parse.el ends here
1133 ;; Local Variables:
1134 ;; generated-autoload-file: "reftex.el"
1135 ;; End: