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