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