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