1 ;;; reftex-parse.el --- parser functions for RefTeX
3 ;; Copyright (C) 1997-2017 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 <https://www.gnu.org/licenses/>.
27 (eval-when-compile (require 'cl-lib
))
31 (defmacro reftex-with-special-syntax
(&rest body
)
32 `(let ((saved-syntax (syntax-table)))
35 (set-syntax-table reftex-syntax-table
)
36 (let ((case-fold-search nil
))
38 (set-syntax-table saved-syntax
))))
41 (defun reftex-parse-one ()
44 (let ((reftex-enable-partial-scans t
))
45 (reftex-access-scan-info '(4))))
48 (defun reftex-parse-all ()
49 "Re-parse entire document."
51 (reftex-access-scan-info '(16)))
53 (defvar reftex--index-tags
)
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
)
63 ((equal rescan
'(4)) t
)
64 ((equal rescan
'(16)) 1)
67 ;; Partial scans only when allowed
68 (unless reftex-enable-partial-scans
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
89 (when (string= true-file true-master
)
90 ;; Scan whole document because this file is the master
93 ;; From which file do we start?
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
)
111 (message "Scanning entire document...")
112 (message "Scanning document from %s..." from-file
))
114 (reftex-with-special-syntax
115 (save-window-excursion
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
))
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
)))
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
))
155 (if (setq tmp
(reftex-locate-file (nth 2 x
) "tex"
158 (message "Can't find external document %s"
162 (alist (delq nil alist
))
163 (allprefix (delq nil
(mapcar 'car alist
)))
164 (regexp (if allprefix
166 (mapconcat 'identity allprefix
"\\|")
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
)))
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.
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
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
)))
190 (while (setq tmp
(assoc 'bof all
))
191 (setq file
(nth 1 tmp
)
192 all
(cdr (memq tmp all
)))
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))
204 file-found tmp include-file
207 toc-entry index-entry next-buf buf
)
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
)))
216 (push (list 'file-error file
) docstruct
)
221 (message "Scanning file %s" file
)
224 (reftex-get-file-buffer-force
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
238 (while (re-search-forward regexp nil t
)
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
)
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))
272 (setq toc-entry
(funcall reftex-section-info-function file
))
274 (eq ;; Either both are t or both are nil.
275 (= (char-after bound
) ?%
)
276 (string-suffix-p ".dtx" file
)))
277 ;; It can happen that section info returns nil
278 (setq level
(nth 5 toc-entry
))
279 (setq highest-level
(min highest-level level
))
280 (if (= level highest-level
)
283 (car (rassoc level reftex-section-levels-all
))
286 (push toc-entry docstruct
)
287 (setq reftex-active-toc toc-entry
)))
290 ;; It's an include or input
291 (setq include-file
(reftex-match-string 7))
292 ;; Test if this file should be ignored
293 (unless (delq nil
(mapcar
294 (lambda (x) (string-match x include-file
))
295 reftex-no-include-regexps
))
298 (reftex-parse-from-file
300 docstruct master-dir
))))
303 ;; Appendix starts here
304 (reftex-init-section-numbers nil t
)
305 (push (cons 'appendix t
) docstruct
))
309 (when reftex-support-index
310 (setq index-entry
(reftex-index-info file
))
312 (cl-pushnew (nth 1 index-entry
) reftex--index-tags
:test
#'equal
)
313 (push index-entry docstruct
))))
316 ;; A macro with label
318 (let* ((mac (reftex-match-string 11))
319 (label (progn (goto-char (match-end 11))
322 (reftex-nth-arg-wrapper
324 (typekey (nth 1 (assoc mac reftex-env-or-mac-alist
)))
325 (entry (progn (if typekey
327 (goto-char (match-end 0))
329 (goto-char (match-end 11))
330 (reftex-move-over-touching-args))
332 label file bound nil nil
))))
333 (push entry docstruct
))))
334 (t (error "This should not happen (reftex-parse-from-file)")))
337 ;; Find bibliography statement
338 (when (setq tmp
(reftex-locate-bibliography-files master-dir
))
339 (push (cons 'bib tmp
) docstruct
))
342 (when (re-search-forward
343 "\\(\\`\\|[\n\r]\\)[ \t]*\\\\begin{thebibliography}" nil t
)
344 (push (cons 'thebib file
) docstruct
))
346 ;; Find external document specifications
348 (while (re-search-forward "[\n\r][ \t]*\\\\externaldocument\\(\\[\\([^]]*\\)\\]\\)?{\\([^}]+\\)}" nil t
)
349 (push (list 'xr-doc
(reftex-match-string 2)
350 (reftex-match-string 3))
354 (push (list 'eof file
) docstruct
)))))
356 ;; Kill the scanned buffer
357 (reftex-kill-temporary-buffers next-buf
))
362 (defun reftex-using-biblatex-p ()
363 "Return non-nil if we are using biblatex rather than bibtex."
364 (if (boundp 'TeX-active-styles
)
365 ;; the sophisticated AUCTeX way
366 (member "biblatex" TeX-active-styles
)
367 ;; poor-man's check...
369 (re-search-forward "^[^%\n]*?\\\\usepackage.*{biblatex}" nil t
))))
372 (defun reftex-locate-bibliography-files (master-dir &optional files
)
373 "Scan buffer for bibliography macros and return file list."
376 (goto-char (point-min))
377 ;; when biblatex is used, multiple \bibliography or
378 ;; \addbibresource macros are allowed. With plain bibtex, only
379 ;; the first is used.
380 (let ((using-biblatex (reftex-using-biblatex-p))
385 ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
386 "\\(^\\)[^%\n\r]*\\\\\\("
387 (mapconcat 'identity reftex-bibliography-commands
"\\|")
388 "\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)") nil t
))
391 (split-string (reftex-match-string 4)
392 "[ \t\n\r]*,[ \t\n\r]*")))
393 (unless using-biblatex
394 (setq again nil
))))))
399 (if (or (member x reftex-bibfile-ignore-list
)
400 (delq nil
(mapcar (lambda (re) (string-match re x
))
401 reftex-bibfile-ignore-regexps
)))
405 (reftex-locate-file x
"bib" master-dir
)))
409 (defun reftex-replace-label-list-segment (old insert
&optional entirely
)
410 "Replace the segment in OLD which corresponds to INSERT.
411 Works with side effects, directly changes old.
412 If ENTIRELY is t, just return INSERT.
413 This function also makes sure the old toc markers do not point anywhere."
417 (reftex-silence-toc-markers old
(length old
))
420 (file (nth 1 (car insert
)))
421 (eof-list (member (list 'eof file
) old
))
422 (bof-list (member (list 'bof file
) old
))
424 (if (not (and bof-list eof-list
))
425 (error "Cannot splice")
427 (reftex-silence-toc-markers bof-list
(- (length bof-list
)
429 (setq n
(- (length old
) (length bof-list
)))
430 (setcdr (nthcdr n new
) (cdr insert
))
431 (setcdr (nthcdr (1- (length new
)) new
) (cdr eof-list
)))
435 (defun reftex-section-info (file)
436 "Return a section entry for the current match.
437 Careful: This function expects the match-data to be still in place!"
438 (let* ((marker (set-marker (make-marker) (1- (match-beginning 3))))
439 (macro (reftex-match-string 3))
440 (prefix (save-match-data
441 (if (string-match "begin{\\([^}]+\\)}" macro
)
442 (match-string 1 macro
))))
443 (level-exp (cdr (assoc macro reftex-section-levels-all
)))
444 (level (if (symbolp level-exp
)
445 (save-match-data (funcall level-exp
))
447 (star (= ?
* (char-after (match-end 3))))
448 (unnumbered (or star
(< level
0)))
450 (section-number (reftex-section-number level unnumbered
))
451 (text1 (save-match-data
453 (reftex-context-substring prefix
))))
454 (literal (buffer-substring-no-properties
455 (1- (match-beginning 3))
456 (min (point-max) (+ (match-end 0) (length text1
) 1))))
457 ;; Literal can be too short since text1 too short. No big problem.
458 (text (reftex-nicify-text text1
)))
460 ;; Add section number and indentation
463 (make-string (* reftex-level-indent level
) ?\
)
464 (if (nth 1 reftex-label-menu-flags
) ; section number flag
465 (concat section-number
" "))
466 (if prefix
(concat (capitalize prefix
) ": ") "")
468 (list 'toc
"toc" text file marker level section-number
469 literal
(marker-position marker
))))
472 (defun reftex-ensure-index-support (&optional abort
)
473 "When index support is turned off, ask to turn it on and
474 set the current prefix argument so that `reftex-access-scan-info'
475 will rescan the entire document."
477 (reftex-support-index t
)
478 ((y-or-n-p "Turn on index support and rescan entire document? ")
479 (setq reftex-support-index
'demanded
480 current-prefix-arg
'(16)))
482 (error "No index support")
483 (message "No index support")
488 (defun reftex-index-info-safe (file)
489 (reftex-with-special-syntax
490 (reftex-index-info file
)))
494 (defun reftex-index-info (file)
495 "Return an index entry for the current match.
496 Careful: This function expects the match-data to be still in place!"
498 (let* ((macro (reftex-match-string 10))
499 (bom (match-beginning 10))
501 (entry (or (assoc macro reftex-index-macro-alist
)
503 (exclude (nth 3 entry
))
504 ;; The following is a test if this match should be excluded
505 (test-dummy (and (fboundp exclude
)
509 (prefix (nth 2 entry
))
511 (cond ((stringp itag
) itag
)
513 (progn (goto-char boa
)
514 (or (reftex-nth-arg itag
(nth 6 entry
)) "idx")))
516 (arg (or (progn (goto-char boa
)
517 (reftex-nth-arg (nth 5 entry
) (nth 6 entry
)))
519 (end-of-args (progn (goto-char boa
)
520 (reftex-move-over-touching-args)
522 (end-of-context (progn (skip-chars-forward "^ \t\n\r") (point)))
524 (progn (goto-char bom
)
525 (skip-chars-backward "^ \t\r\n")
527 (context (buffer-substring-no-properties
528 begin-of-context end-of-context
))
529 (key-end (if (string-match reftex-index-key-end-re arg
)
530 (1+ (match-beginning 0))))
531 (rawkey (substring arg
0 key-end
))
533 (key (if prefix
(concat prefix rawkey
) rawkey
))
534 (sortkey (downcase key
))
535 (showkey (mapconcat 'identity
536 (split-string key reftex-index-level-re
)
538 (goto-char end-of-args
)
539 ;; 0 1 2 3 4 5 6 7 8 9
540 (list 'index index-tag context file bom arg key showkey sortkey key-end
))))
543 (defun reftex-short-context (env parse
&optional bound derive
)
544 "Get about one line of useful context for the label definition at point."
547 (setq parse
(if derive
(cdr parse
) (car parse
))))
555 (reftex-context-substring)))
558 (if (string= env
"section")
559 ;; special treatment for section labels
561 (if (and (re-search-backward reftex-section-or-include-regexp
565 (goto-char (match-end 0))
566 (reftex-context-substring))
567 (if reftex-active-toc
569 (string-match "{\\([^}]*\\)" (nth 7 reftex-active-toc
))
570 (match-string 1 (nth 7 reftex-active-toc
)))
571 "SECTION HEADING NOT FOUND")))
573 (goto-char reftex-default-context-position
)
574 (unless (eq (string-to-char env
) ?
\\)
575 (reftex-move-over-touching-args))
576 (reftex-context-substring))))
580 (if (re-search-backward parse bound t
)
582 (goto-char (match-end 0))
583 (reftex-context-substring))
584 "NO MATCH FOR CONTEXT REGEXP")))
588 (goto-char reftex-default-context-position
)
591 (nth 6 (assoc env reftex-env-or-mac-alist
))))
595 ;; A hook function. Call it.
597 (condition-case error-var
599 (error (format "HOOK ERROR: %s" (cdr error-var
))))))
601 "INVALID VALUE OF PARSE"))))
604 (defun reftex-where-am-I ()
605 "Return the docstruct entry above point.
606 Actually returns a cons cell in which the cdr is a flag indicating
607 if the information is exact (t) or approximate (nil)."
609 (let ((docstruct (symbol-value reftex-docstruct-symbol
))
610 (cnt 0) rtn rtn-if-no-other
615 (setq found
(re-search-backward (reftex-everything-regexp) nil t
))
621 (car (member (list 'bof
(buffer-file-name)) docstruct
))
623 (assq 'bof docstruct
) ;; for safety reasons
627 (assoc (reftex-match-string 1)
628 (symbol-value reftex-docstruct-symbol
)))
631 (goto-char (1- (match-beginning 3)))
632 (let* ((list (member (list 'bof
(buffer-file-name))
634 (endelt (car (member (list 'eof
(buffer-file-name))
637 (while (and list
(not (eq endelt
(car list
))))
638 (if (and (eq (car (car list
)) 'toc
)
639 (string= (buffer-file-name)
643 (or (and (markerp (nth 4 (car list
)))
644 (marker-position (nth 4 (car list
))))
646 ;; Fits with marker position or recorded position
647 (setq rtn1
(car list
) list nil
))
648 ((looking-at (reftex-make-regexp-allow-for-ctrl-m
650 ;; Same title: remember, but keep looking
651 (setq rtn-if-no-other
(car list
)))))
655 ;; Input or include...
657 (member (list 'eof
(reftex-locate-file
658 (reftex-match-string 7) "tex"
659 (cdr (assq 'master-dir docstruct
))))
662 (assq 'appendix
(symbol-value reftex-docstruct-symbol
)))
665 (when reftex-support-index
666 (let* ((index-info (save-excursion
667 (reftex-index-info-safe nil
)))
668 (list (member (list 'bof
(buffer-file-name))
670 (endelt (car (member (list 'eof
(buffer-file-name))
672 dist last-dist last
(n 0))
673 ;; Check all index entries with equal text
674 (while (and list
(not (eq endelt
(car list
))))
675 (when (and (eq (car (car list
)) 'index
)
676 (string= (nth 2 index-info
)
679 (setq dist
(abs (- (point) (nth 4 (car list
)))))
680 (if (or (not last-dist
) (< dist last-dist
))
681 (setq last-dist dist last
(car list
))))
682 (setq list
(cdr list
)))
683 ;; We are sure if we have only one, or a zero distance
684 (cond ((or (= n
1) (equal dist
0)) last
)
685 ((> n
1) (setq cnt
2) last
)
689 (goto-char (match-end 11))
690 (assoc (reftex-no-props
691 (reftex-nth-arg-wrapper
692 (reftex-match-string 11)))
693 (symbol-value reftex-docstruct-symbol
))))
695 (error "This should not happen (reftex-where-am-I)"))))))
696 ;; Check if there was only a by-name match for the section.
697 (when (and (not rtn
) rtn-if-no-other
)
698 (setq rtn rtn-if-no-other
700 (cons rtn
(eq cnt
1))))
703 (defun reftex-notice-new (&optional n force
)
704 "Hook to handshake with RefTeX after something new has been inserted."
705 ;; Add a new entry to the docstruct list. If it is a section, renumber
706 ;; the following sections.
707 ;; FIXME: Put in a WHAT parameter and search backward until one is found.
708 ;; When N is given, go back that many matches of reftex-everything-regexp
709 ;; When FORCE is non-nil, also insert if `reftex-where-am-I' was uncertain.
712 (unless reftex-mode
(throw 'exit nil
))
713 (reftex-access-scan-info)
714 (let* ((docstruct (symbol-value reftex-docstruct-symbol
))
715 here-I-am appendix tail entry star level
716 section-number context
)
719 (when (re-search-backward (reftex-everything-regexp) nil t
(or n
1))
722 (setq here-I-am
(reftex-where-am-I))
723 (or here-I-am
(throw 'exit nil
))
724 (unless (or force
(cdr here-I-am
)) (throw 'exit nil
))
725 (setq tail
(memq (car here-I-am
) docstruct
))
726 (or tail
(throw 'exit nil
))
727 (setq reftex-active-toc
(reftex-last-assoc-before-elt
728 'toc
(car here-I-am
) docstruct
)
729 appendix
(reftex-last-assoc-before-elt
730 'appendix
(car here-I-am
) docstruct
))
732 ;; Initialize section numbers
733 (if (eq (car (car here-I-am
)) 'appendix
)
734 (reftex-init-section-numbers nil t
)
735 (reftex-init-section-numbers reftex-active-toc appendix
))
737 ;; Match the section command
738 (when (re-search-forward (reftex-everything-regexp) nil t
)
741 (push (reftex-label-info (reftex-match-string 1) buffer-file-name
)
745 (setq star
(= ?
* (char-after (match-end 3)))
746 entry
(reftex-section-info (buffer-file-name))
748 ;; Insert the section info
749 (push entry
(cdr tail
))
751 ;; We are done unless we use section numbers
752 (unless (nth 1 reftex-label-menu-flags
) (throw 'exit nil
))
754 ;; Update the remaining toc items
755 (setq tail
(cdr tail
))
756 (while (and (setq tail
(memq (assq 'toc
(cdr tail
)) tail
))
757 (setq entry
(car tail
))
758 (>= (nth 5 entry
) level
))
759 (setq star
(string-match "\\*" (nth 6 entry
))
760 context
(nth 2 entry
)
762 (reftex-section-number (nth 5 entry
) star
))
763 (when (string-match "\\`\\([ \t]*\\)\\([.0-9A-Z]+\\)\\(.*\\)"
765 (when (and (not appendix
)
766 (>= (string-to-char (match-string 2)) ?A
))
767 ;; Just entered the appendix. Get out.
770 ;; Change the section number.
772 (concat (match-string 1 context
)
774 (match-string 3 context
))))))
777 (and reftex-support-index
778 (setq entry
(reftex-index-info-safe buffer-file-name
))
779 ;; FIXME: (add-to-list 'reftex--index-tags (nth 1 index-entry))
780 (push entry
(cdr tail
))))))))))
785 (defsubst reftex-move-to-previous-arg
(&optional bound
)
786 "Assuming that we are in front of a macro argument,
787 move backward to the closing parenthesis of the previous argument.
788 This function understands the splitting of macros over several lines
792 ((memq (preceding-char) '(?\
] ?\
})))
794 ((and reftex-allow-detached-macro-args
796 "[]}][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t
))
797 (goto-char (1+ (match-beginning 0)))
802 (defun reftex-what-macro-safe (which &optional bound
)
803 "Call `reftex-what-macro' with special syntax table."
804 (reftex-with-special-syntax
805 (reftex-what-macro which bound
)))
808 (defun reftex-what-macro (which &optional bound
)
809 "Find out if point is within the arguments of any TeX-macro.
810 The return value is either (\"\\macro\" . (point)) or a list of them.
812 If WHICH is nil, immediately return nil.
813 If WHICH is 1, return innermost enclosing macro.
814 If WHICH is t, return list of all macros enclosing point.
815 If WHICH is a list of macros, look only for those macros and return the
816 name of the first macro in this list found to enclose point.
817 If the optional BOUND is an integer, bound backwards directed
818 searches to this point. If it is nil, limit to nearest \\section -
821 This function is pretty stable, but can be fooled if the text contains
822 things like \\macro{aa}{bb} where \\macro is defined to take only one
823 argument. As RefTeX cannot know this, the string \"bb\" would still be
824 considered an argument of macro \\macro."
825 (unless reftex-section-regexp
(reftex-compile-variables))
827 (if (null which
) (throw 'exit nil
))
828 (let ((bound (or bound
(save-excursion (re-search-backward
829 reftex-section-regexp nil
1)
831 pos cmd-list cmd cnt cnt-opt entry
)
834 (narrow-to-region (max (point-min) bound
) (point-max))
835 ;; move back out of the current parenthesis
836 (while (condition-case nil
837 (let ((forward-sexp-function nil
))
840 (setq cnt
1 cnt-opt
0)
841 ;; move back over any touching sexps
842 (while (and (reftex-move-to-previous-arg bound
)
844 (let ((forward-sexp-function nil
))
847 (if (eq (following-char) ?\
[) (cl-incf cnt-opt
))
850 (when (and (or (= (following-char) ?\
[)
851 (= (following-char) ?\
{))
852 (re-search-backward "\\\\[*a-zA-Z]+\\=" nil t
))
853 (setq cmd
(reftex-match-string 0))
854 (when (looking-at "\\\\begin{[^}]*}")
855 (setq cmd
(reftex-match-string 0)
857 ;; This does ignore optional arguments. Very hard to fix.
858 (when (setq entry
(assoc cmd reftex-env-or-mac-alist
))
859 (if (> cnt
(or (nth 4 entry
) 100))
864 (push (cons cmd
(point)) cmd-list
))
865 ((or (eq 1 which
) (member cmd which
))
866 (throw 'exit
(cons cmd
(point))))))
868 (nreverse cmd-list
)))))
871 (defun reftex-what-environment (which &optional bound
)
872 "Find out if point is inside a LaTeX environment.
873 The return value is (e.g.) either (\"equation\" . (point)) or a list of
876 If WHICH is nil, immediately return nil.
877 If WHICH is 1, return innermost enclosing environment.
878 If WHICH is t, return list of all environments enclosing point.
879 If WHICH is a list of environments, look only for those environments and
880 return the name of the first environment in this list found to enclose
883 If the optional BOUND is an integer, bound backwards directed searches to
884 this point. If it is nil, limit to nearest \\section - like statement."
885 (unless reftex-section-regexp
(reftex-compile-variables))
888 (if (null which
) (throw 'exit nil
))
889 (let ((bound (or bound
(save-excursion (re-search-backward
890 reftex-section-regexp nil
1)
892 env-list end-list env
)
893 (while (re-search-backward "\\\\\\(begin\\|end\\){\\([^}]+\\)}"
895 (setq env
(buffer-substring-no-properties
896 (match-beginning 2) (match-end 2)))
898 ((string= (match-string 1) "end")
900 ((equal env
(car end-list
))
901 (setq end-list
(cdr end-list
)))
903 (push (cons env
(point)) env-list
))
904 ((or (eq 1 which
) (member env which
))
905 (throw 'exit
(cons env
(point))))))
906 (nreverse env-list
)))))
909 (defun reftex-what-special-env (which &optional bound
)
910 "Run the special environment parsers and return the matches.
912 The return value is (e.g.) either (\"my-parser-function\" . (point))
915 If WHICH is nil, immediately return nil.
916 If WHICH is 1, return innermost enclosing environment.
917 If WHICH is t, return list of all environments enclosing point.
918 If WHICH is a list of environments, look only for those environments and
919 return the name of the first environment in this list found to enclose
921 (unless reftex-section-regexp
(reftex-compile-variables))
924 (if (null reftex-special-env-parsers
) (throw 'exit nil
))
925 (if (null which
) (throw 'exit nil
))
926 (let ((bound (or bound
(save-excursion (re-search-backward
927 reftex-section-regexp nil
1)
929 (fun-list (if (listp which
)
930 (mapcar (lambda (x) (if (memq x which
) x nil
))
931 reftex-special-env-parsers
)
932 reftex-special-env-parsers
))
934 ;; Call all functions
935 (setq specials
(mapcar
938 (setq rtn
(and fun
(funcall fun bound
)))
939 (if rtn
(cons (symbol-name fun
) rtn
) nil
)))
941 ;; Delete the non-matches
942 (setq specials
(delq nil specials
))
944 (setq specials
(sort specials
(lambda (a b
) (> (cdr a
) (cdr b
)))))
949 (defsubst reftex-move-to-next-arg
(&optional _ignore
)
950 "Assuming that we are at the end of a macro name or a macro argument,
951 move forward to the opening parenthesis of the next argument.
952 This function understands the splitting of macros over several lines
956 ((memq (following-char) '(?\
[ ?\
{)))
958 ((and reftex-allow-detached-macro-args
959 (looking-at "[ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*[[{]"))
960 (goto-char (1- (match-end 0)))
964 (defun reftex-nth-arg-wrapper (key)
965 (let ((entry (assoc key reftex-env-or-mac-alist
)))
966 (reftex-nth-arg (nth 5 entry
) (nth 6 entry
))))
969 (defun reftex-nth-arg (n &optional opt-args
)
970 "Return the Nth following {} or [] parentheses content.
971 OPT-ARGS is a list of argument numbers which are optional."
973 ;; If we are sitting at a macro start, skip to end of macro name.
974 (and (eq (following-char) ?
\\) (skip-chars-forward "a-zA-Z*\\\\"))
977 ;; Special case: Skip all touching arguments
979 (reftex-move-over-touching-args)
980 (reftex-context-substring))
982 ;; Do the real thing.
985 (when (reftex-move-to-next-arg)
988 (while (and (member cnt opt-args
)
989 (eq (following-char) ?\
{))
992 (unless (and (condition-case nil
993 (or (forward-list 1) t
)
995 (reftex-move-to-next-arg)
999 (while (and (memq cnt opt-args
)
1000 (eq (following-char) ?\
{))
1003 (> (skip-chars-forward "{\\[") 0))
1004 (reftex-context-substring)
1008 (defun reftex-move-over-touching-args ()
1010 (while (memq (following-char) '(?\
[ ?\
{))
1014 (defun reftex-context-substring (&optional to-end
)
1015 "Return up to 150 chars from point.
1016 When point is just after a { or [, limit string to matching parenthesis"
1019 ;; Environment - find next \end
1020 (buffer-substring-no-properties
1022 (min (+ (point) 150)
1024 ;; FIXME: This is not perfect
1025 (if (re-search-forward "\\\\end{" nil t
)
1028 ((memq (preceding-char) '(?\
{ ?\
[))
1029 ;; Inside a list - get only the list.
1030 (buffer-substring-no-properties
1032 (min (+ (point) 150)
1035 (let ((forward-sexp-function nil
)) ;Unneeded fanciness.
1038 (error (point-max))))))
1040 ;; no list - just grab 150 characters
1041 (buffer-substring-no-properties (point)
1042 (min (+ (point) 150) (point-max))))))
1044 ;; Variable holding the vector with section numbers
1045 (defvar reftex-section-numbers
(make-vector reftex-max-section-depth
0))
1048 (defun reftex-init-section-numbers (&optional toc-entry appendix
)
1049 "Initialize the section numbers with zeros or with what is found in the TOC-ENTRY."
1050 (let* ((level (or (nth 5 toc-entry
) -
1))
1051 (numbers (nreverse (split-string (or (nth 6 toc-entry
) "") "\\.")))
1052 (depth (1- (length reftex-section-numbers
)))
1053 (i depth
) number-string
)
1056 (aset reftex-section-numbers i
0)
1057 (setq number-string
(or (car numbers
) "0"))
1058 (if (string-match "\\`[A-Z]\\'" number-string
)
1059 (aset reftex-section-numbers i
1060 (- (string-to-char number-string
) ?A -
1))
1061 (aset reftex-section-numbers i
(string-to-number number-string
)))
1064 (put 'reftex-section-numbers
'appendix appendix
))
1067 (defun reftex-section-number (&optional level star
)
1068 "Return a string with the current section number.
1069 When LEVEL is non-nil, increase section numbers on that level."
1070 (let* ((depth (1- (length reftex-section-numbers
))) idx n
(string "")
1071 (appendix (get 'reftex-section-numbers
'appendix
))
1072 (partspecial (and (not reftex-part-resets-chapter
)
1074 ;; partspecial means, this is a part statement.
1075 ;; Parts do not reset the chapter counter, and the part number is
1076 ;; not included in the numbering of other sectioning levels.
1078 (when (and (> level -
1) (not star
))
1079 (aset reftex-section-numbers
1080 level
(1+ (aref reftex-section-numbers level
))))
1081 (setq idx
(1+ level
))
1083 (while (<= idx depth
)
1084 (if (or (not partspecial
)
1086 (aset reftex-section-numbers idx
0))
1089 (setq string
(concat "Part " (reftex-roman-number
1090 (aref reftex-section-numbers
0))))
1091 (setq idx
(if reftex-part-resets-chapter
0 1))
1092 (while (<= idx depth
)
1093 (setq n
(aref reftex-section-numbers idx
))
1094 (if (not (and partspecial
(not (equal string
""))))
1095 (setq string
(concat string
(if (not (string= string
"")) "." "")
1096 (int-to-string n
))))
1099 (if (string-match "\\`\\([@0]\\.\\)+" string
)
1100 (setq string
(replace-match "" nil nil string
)))
1101 (if (string-match "\\(\\.0\\)+\\'" string
)
1102 (setq string
(replace-match "" nil nil string
)))
1104 (string-match "\\`[0-9]+" string
))
1108 (1- (+ ?A
(string-to-number (match-string 0 string
)))))
1109 (substring string
(match-end 0))))))
1111 (concat (make-string (1- (length string
)) ?\
) "*")
1114 (defun reftex-roman-number (n)
1115 "Return as a string the roman number equal to N."
1118 (list '((1000 .
"M") ( 900 .
"CM") ( 500 .
"D") ( 400 .
"CD")
1119 ( 100 .
"C") ( 90 .
"XC") ( 50 .
"L") ( 40 .
"XL")
1120 ( 10 .
"X") ( 9 .
"IX") ( 5 .
"V") ( 4 .
"IV")
1124 (setq listel
(pop list
)
1128 (setq string
(concat string s
)
1129 nrest
(- nrest i
))))
1132 (provide 'reftex-parse
)
1134 ;;; reftex-parse.el ends here
1137 ;; generated-autoload-file: "reftex-loaddefs.el"