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