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