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