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