root/trunk/lisp/textmodes/reftex-index.el

Revision 4220, 87.7 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

  • Property svn:eol-style set to LF
Line 
1 ;;; reftex-index.el --- index support with RefTeX
2
3 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 ;;   2006, 2007, 2008 Free Software Foundation, Inc.
5
6 ;; Author: Carsten Dominik <dominik@science.uva.nl>
7 ;; Maintainer: auctex-devel@gnu.org
8 ;; Version: 4.31
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
15 ;; any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26
27 ;;; Commentary:
28
29 ;;; Code:
30
31 (eval-when-compile (require 'cl))
32 (provide 'reftex-index)
33 (require 'reftex)
34 ;;;
35
36 ;; START remove for XEmacs release
37 (defvar mark-active)
38 (defvar zmacs-regions)
39 (defvar transient-mark-mode)
40 (defvar TeX-master)
41 ;; END remove for XEmacs release
42 (defun reftex-index-selection-or-word (&optional arg phrase)
43   "Put selection or the word near point into the default index macro.
44 This uses the information in `reftex-index-default-macro' to make an index
45 entry.  The phrase indexed is the current selection or the word near point.
46 When called with one `C-u' prefix, let the user have a chance to edit the
47 index entry.  When called with 2 `C-u' as prefix, also ask for the index
48 macro and other stuff.
49 When called inside TeX math mode as determined by the `texmathp.el' library
50 which is part of AUCTeX, the string is first processed with the
51 `reftex-index-math-format', which see."
52   (interactive "P")
53   (let* ((use-default (not (equal arg '(16))))  ; check for double prefix
54          ;; check if we have an active selection
55          (active (if (boundp 'zmacs-regions)
56                      (and zmacs-regions (region-exists-p))  ; XEmacs
57                    (and transient-mark-mode mark-active)))  ; Emacs
58          (beg (if active
59                   (region-beginning)
60                 (save-excursion
61                   (skip-syntax-backward "w\\") (point))))
62          (end (if active
63                   (region-end)
64                 (save-excursion
65                   (skip-syntax-forward "w\\") (point))))
66          (sel (buffer-substring beg end))
67          (mathp (condition-case nil (texmathp) (error nil)))
68          (current-prefix-arg nil) ; we want to call reftex-index without prefix.
69          key def-char def-tag full-entry)
70
71     (if phrase
72         (progn
73           (reftex-index-visit-phrases-buffer)
74           (reftex-index-new-phrase sel))
75
76       (if (equal sel "")
77           ;; Nothing selected, no word, so use full reftex-index command
78           (reftex-index)
79         ;; OK, we have something to index here.
80         ;; Add the dollars when necessary
81         (setq key (if mathp
82                       (format reftex-index-math-format sel)
83                     sel))
84         ;; Get info from `reftex-index-default-macro'
85         (setq def-char  (if use-default (car reftex-index-default-macro)))
86         (setq def-tag   (if use-default (nth 1 reftex-index-default-macro)))
87         ;; Does the user want to edit the entry?
88         (setq full-entry (if arg
89                              (reftex-index-complete-key
90                               def-tag nil (cons key 0))
91                            key))
92         ;; Delete what is in the buffer and make the index entry
93         (delete-region beg end)
94         (reftex-index def-char full-entry def-tag sel)))))
95  
96 (defun reftex-index (&optional char key tag sel no-insert)
97   "Query for an index macro and insert it along with its argments.
98 The index macros available are those defined in `reftex-index-macro' or
99 by a call to `reftex-add-index-macros', typically from an AUCTeX style file.
100 RefteX provides completion for the index tag and the index key, and
101 will prompt for other arguments."
102
103   (interactive)
104
105   ;; Ensure access to scanning info
106   (reftex-ensure-index-support t)
107   (reftex-access-scan-info current-prefix-arg)
108
109   ;; Find out which macro we are going to use
110   (let* ((char (or char
111                    (reftex-select-with-char reftex-query-index-macro-prompt
112                                             reftex-query-index-macro-help)))
113          (macro (nth 1 (assoc char reftex-key-to-index-macro-alist)))
114          (entry (or (assoc macro reftex-index-macro-alist)
115                     (error "No index macro associated with %c" char)))
116          (ntag (nth 1 entry))
117          (tag (or tag (nth 1 entry)))
118          (nargs (nth 4 entry))
119          (nindex (nth 5 entry))
120          (opt-args (nth 6 entry))
121          (repeat (nth 7 entry))
122          opt tag1 value)
123
124     ;; Get the supported arguments
125     (if (stringp tag)
126         (setq tag1 tag)
127       (setq tag1 (or (reftex-index-complete-tag tag opt-args) "")))
128     (setq key (or key
129                   (reftex-index-complete-key
130                    (if (string= tag1 "") "idx" tag1)
131                    (member nindex opt-args))))
132
133     ;; Insert the macro and ask for any additional args
134     (insert macro)
135     (loop for i from 1 to nargs do
136       (setq opt (member i opt-args)
137             value (cond ((= nindex i) key)
138                         ((equal ntag i) tag1)
139                         (t (read-string (concat "Macro arg nr. "
140                                                 (int-to-string i)
141                                                 (if opt " (optional)" "")
142                                                 ": ")))))
143       (unless (and opt (string= value ""))
144         (insert (if opt "[" "{") value (if opt "]" "}"))))
145     (and repeat (stringp sel) (insert sel))
146     (and key reftex-plug-into-AUCTeX (fboundp 'LaTeX-add-index-entries)
147          (LaTeX-add-index-entries key))
148     (reftex-index-update-taglist tag1)
149     (reftex-notice-new)))
150
151 (defun reftex-default-index ()
152   (cond ((null reftex-index-default-tag) nil)
153         ((stringp reftex-index-default-tag) reftex-index-default-tag)
154         (t (or (get reftex-docstruct-symbol 'default-index-tag)
155                "idx"))))
156
157 (defun reftex-update-default-index (tag &optional tag-list)
158   (if (and (not (equal tag ""))
159            (stringp tag)
160            (eq reftex-index-default-tag 'last)
161            (or (null tag-list)
162                (member tag tag-list)))
163       (put reftex-docstruct-symbol 'default-index-tag tag)))
164
165 (defun reftex-index-complete-tag (&optional itag opt-args)
166   ;; Ask the user for a tag, completing on known tags.
167   ;; ITAG is the argument number which contains the tag.
168   ;; OPT-ARGS is a list of optional argument indices, as given by
169   ;; `reftex-parse-args'.
170   (let* ((opt (and (integerp itag) (member itag opt-args)))
171          (index-tags (cdr (assq 'index-tags
172                                 (symbol-value reftex-docstruct-symbol))))
173          (default (reftex-default-index))
174          (prompt (concat "Index tag"
175                          (if (or opt default)
176                              (format " (%s): "
177                                      (concat
178                                       (if opt "optional" "")
179                                       (if default
180                                           (concat (if opt ", " "")
181                                                   (format "default %s" default))
182                                         "")))
183                            ": ")))
184          (tag (completing-read prompt (mapcar 'list index-tags))))
185     (if (and default (equal tag "")) (setq tag default))
186     (reftex-update-default-index tag)
187     tag))
188
189 (defun reftex-index-select-tag ()
190   ;; Have the user select an index tag.
191   ;; FIXME: should we cache tag-alist, prompt and help?
192   (let* ((index-tags (cdr (assoc 'index-tags
193                                  (symbol-value reftex-docstruct-symbol))))
194          (default (reftex-default-index)))
195     (cond
196      ((null index-tags)
197       (error "No index tags available"))
198
199      ((= (length index-tags) 1)
200       ;; Just one index, use it
201       (car index-tags))
202          
203      ((> (length index-tags) 1)
204       ;; Several indices, ask.
205       (let* ((tags (copy-sequence index-tags))
206              (cnt 0)
207              tag-alist i val len tag prompt help rpl)
208         ;; Move idx and glo up in the list to ensure ?i and ?g shortcuts
209         (if (member "glo" tags)
210             (setq tags (cons "glo" (delete "glo" tags))))
211         (if (member "idx" tags)
212             (setq tags (cons "idx" (delete "idx" tags))))
213         ;; Find unique shortcuts for each index.
214         (while (setq tag (pop tags))
215           (setq len (length tag)
216                 i -1
217                 val nil)
218           (catch 'exit
219             (while (and (< (incf i) len) (null val))
220               (unless (assq (aref tag i) tag-alist)
221                 (push (list (aref tag i)
222                             tag
223                             (concat (substring tag 0 i)
224                                     "[" (substring tag i (incf i)) "]"
225                                     (substring tag i)))
226                       tag-alist)
227                 (throw 'exit t)))
228             (push (list (+ ?0 (incf cnt)) tag
229                         (concat "[" (int-to-string cnt) "]:" tag))
230                   tag-alist)))
231         (setq tag-alist (nreverse tag-alist))
232         ;; Compute Prompt and Help strings
233         (setq prompt
234               (concat
235                (format "Select Index%s: "
236                        (if default (format " (Default <%s>)" default) ""))
237                (mapconcat (lambda(x) (nth 2 x)) tag-alist "  ")))
238         (setq help
239               (concat "Select an Index\n===============\n"
240                       (if default
241                           (format "[^M]  %s (the default)\n" default)
242                         "")
243                       (mapconcat (lambda(x)
244                                    (apply 'format "[%c]   %s" x))
245                                  tag-alist "\n")))
246         ;; Query the user for an index-tag
247         (setq rpl (reftex-select-with-char prompt help 3 t))
248         (message "")
249         (if (and default (equal rpl ?\C-m))
250             default
251           (if (assq rpl tag-alist)
252               (progn
253                 (reftex-update-default-index (nth 1 (assq rpl tag-alist)))
254                 (nth 1 (assq rpl tag-alist)))
255             (error "No index tag associated with %c" rpl)))))
256      (t (error "This should not happen (reftex-index-select-tag)")))))
257
258 (defun reftex-index-complete-key (&optional tag optional initial)
259   ;; Read an index key, with completion.
260   ;; Restrict completion table on index tag TAG.
261   ;; OPTIONAL indicates if the arg is optional.
262   (let* ((table (reftex-sublist-nth
263                  (symbol-value reftex-docstruct-symbol) 6
264                  (lambda(x) (and (eq (car x) 'index)
265                                  (string= (nth 1 x) (or tag ""))))
266                  t))
267          (prompt (concat "Index key" (if optional " (optional)" "") ": "))
268          (key (completing-read prompt table nil nil initial)))
269     key))
270
271 (defun reftex-index-update-taglist (newtag)
272   ;; add NEWTAG to the list of available index tags.
273   (let ((cell (assoc 'index-tags (symbol-value reftex-docstruct-symbol))))
274     (and newtag (cdr cell) (not (member newtag (cdr cell)))
275          (push newtag (cdr cell)))))
276
277 (defvar reftex-index-map (make-sparse-keymap)
278   "Keymap used for *Index* buffers.")
279
280 (defvar reftex-index-menu)
281
282 (defvar reftex-last-index-file nil
283   "Stores the file name from which `reftex-display-index' was called.")
284 (defvar reftex-index-tag nil
285   "Stores the tag of the index in an index buffer.")
286
287 (defvar reftex-index-return-marker (make-marker)
288   "Marker which makes it possible to return from index to old position.")
289
290 (defvar reftex-index-restriction-indicator nil)
291 (defvar reftex-index-restriction-data nil)
292
293 (defun reftex-index-mode ()
294   "Major mode for managing Index buffers for LaTeX files.
295 This buffer was created with RefTeX.
296 Press `?' for a summary of important key bindings, or check the menu.
297
298 Here are all local bindings.
299
300 \\{reftex-index-map}"
301   (interactive)
302   (kill-all-local-variables)
303   (setq major-mode 'reftex-index-mode
304         mode-name "RefTeX Index")
305   (use-local-map reftex-index-map)
306   (set (make-local-variable 'revert-buffer-function) 'reftex-index-revert)
307   (set (make-local-variable 'reftex-index-restriction-data) nil)
308   (set (make-local-variable 'reftex-index-restriction-indicator) nil)
309   (setq mode-line-format
310         (list "----  " 'mode-line-buffer-identification
311               "   " 'global-mode-string
312               "  R<" 'reftex-index-restriction-indicator ">"
313               " -%-"))
314   (setq truncate-lines t)
315   (when (featurep 'xemacs)
316     ;; XEmacs needs the call to make-local-hook
317     (make-local-hook 'post-command-hook)
318     (make-local-hook 'pre-command-hook))
319   (make-local-variable 'reftex-last-follow-point)
320   (easy-menu-add reftex-index-menu reftex-index-map)
321   (add-hook 'post-command-hook 'reftex-index-post-command-hook nil t)
322   (add-hook 'pre-command-hook  'reftex-index-pre-command-hook nil t)
323   (run-hooks 'reftex-index-mode-hook))
324
325 (defconst reftex-index-help
326 "                      AVAILABLE KEYS IN INDEX BUFFER
327                       ==============================
328 ! A..Z     Goto the section of entries starting with this letter.
329 n / p      next-entry / previous-entry
330 SPC / TAB  Show/Goto the corresponding entry in the LaTeX document.
331 RET        Goto the entry and hide the *Index* window (also on mouse-2).
332 q / k      Hide/Kill *Index* buffer.
333 C-c =      Switch to the TOC buffer.
334 f / c      Toggle follow mode             / Toggle display of [c]ontext.
335 g          Refresh *Index* buffer.
336 r / C-u r  Reparse the LaTeX document     / Reparse entire LaTeX document.
337 s          Switch to a different index (for documents with multiple indices).
338 e / C-k    Edit/Kill the entry.
339 * | @      Edit specific part of entry: [*]key [|]attribute [@]visual
340            With prefix: kill that part.
341 \( )        Toggle entry's beginning/end of page range property.
342 _ ^        Add/Remove parent key (to make this item a subitem).
343 } / {      Restrict Index to a single document section / Widen.
344 < / >      When restricted, move restriction to previous/next section.")
345
346 (defun reftex-index-show-entry (data &optional no-revisit)
347   ;; Find an index entry associated with DATA and display it highlighted
348   ;; in another window.  NO-REVISIT means we are not allowed to visit
349   ;; files for this.
350   ;; Note:  This function just looks for the nearest match of the
351   ;; context string and may fail if the entry moved and an identical
352   ;; entry is close to the old position.  Frequent rescans make this
353   ;; safer.
354   (let* ((file (nth 3 data))
355          (literal (nth 2 data))
356          (pos (nth 4 data))
357          (re (regexp-quote literal))
358          (match
359           (cond
360            ((or (not no-revisit)
361                 (reftex-get-buffer-visiting file))
362             (switch-to-buffer-other-window
363              (reftex-get-file-buffer-force file nil))
364             (goto-char (or pos (point-min)))
365             (or (looking-at re)
366                 (reftex-nearest-match re (length literal))))
367            (t (message reftex-no-follow-message) nil))))
368     (when match
369       (goto-char (match-beginning 0))
370       (recenter '(4))
371       (reftex-highlight 0 (match-beginning 0) (match-end 0) (current-buffer)))
372     match))
373
374 (defun reftex-display-index (&optional tag overriding-restriction redo
375                                        &rest locations)
376   "Display a buffer with an index compiled from the current document.
377 When the document has multiple indices, first prompts for the correct one.
378 When index support is turned off, offer to turn it on.
379 With one or two `C-u' prefixes, rescan document first.
380 With prefix 2, restrict index to current document section.
381 With prefix 3, restrict index to region."
382
383   (interactive)
384
385   ;; Ensure access to scanning info and rescan buffer if prefix are is '(4).
386   (let ((current-prefix-arg current-prefix-arg))
387     (reftex-ensure-index-support t)
388     (reftex-access-scan-info current-prefix-arg))
389
390   (set-marker reftex-index-return-marker (point))
391   (setq reftex-last-follow-point 1)
392
393   ;; Determine the correct index to process
394   (let* ((docstruct (symbol-value reftex-docstruct-symbol))
395          (docstruct-symbol reftex-docstruct-symbol)
396          (index-tag (or tag (reftex-index-select-tag)))
397          (master (reftex-TeX-master-file))
398          (calling-file (buffer-file-name))
399          (restriction
400           (or overriding-restriction
401               (and (not redo)
402                    (reftex-get-restriction current-prefix-arg docstruct))))
403          (locations
404           ;; See if we are on an index macro as initial position
405           (or locations
406               (let* ((what-macro (reftex-what-macro-safe 1))
407                      (macro (car what-macro))
408                      (here-I-am (when (member macro reftex-macros-with-index)
409                                   (save-excursion
410                                     (goto-char (+ (cdr what-macro)
411                                                   (length macro)))
412                                     (reftex-move-over-touching-args)
413                                     (reftex-where-am-I)))))
414                 (if (eq (car (car here-I-am)) 'index)
415                     (list (car here-I-am))))))
416          buffer-name)
417
418     (setq buffer-name (reftex-make-index-buffer-name index-tag))
419
420     ;; Goto the buffer and put it into the correct mode
421                       
422     (when (or restriction current-prefix-arg)
423          (reftex-kill-buffer buffer-name))
424
425     (if (get-buffer-window buffer-name)
426         (select-window (get-buffer-window buffer-name))
427       (let ((default-major-mode 'reftex-index-mode))
428         (switch-to-buffer buffer-name)))
429
430     (or (eq major-mode 'reftex-index-mode) (reftex-index-mode))
431
432     ;; If the buffer is currently restricted, empty it to force update.
433     (when reftex-index-restriction-data
434       (reftex-erase-buffer))
435     (set (make-local-variable 'reftex-last-index-file) calling-file)
436     (set (make-local-variable 'reftex-index-tag) index-tag)
437     (set (make-local-variable 'reftex-docstruct-symbol) docstruct-symbol)
438     (if restriction
439         (setq reftex-index-restriction-indicator (car restriction)
440               reftex-index-restriction-data (cdr restriction))
441       (if (not redo)
442           (setq reftex-index-restriction-indicator nil
443                 reftex-index-restriction-data nil)))
444     (when (= (buffer-size) 0)
445       ;; buffer is empty - fill it
446       (message "Building %s buffer..." buffer-name)
447
448       (setq buffer-read-only nil)
449       (insert (format
450 "INDEX <%s> on %s
451 Restriction: <%s>
452 SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help
453 ------------------------------------------------------------------------------
454 " index-tag (abbreviate-file-name master)
455 (if (eq (car (car reftex-index-restriction-data)) 'toc)
456     (nth 2 (car reftex-index-restriction-data))
457   reftex-index-restriction-indicator)))
458
459       (if (reftex-use-fonts)
460           (put-text-property 1 (point) 'face reftex-index-header-face))
461       (put-text-property 1 (point) 'intangible t)
462
463       (reftex-insert-index docstruct index-tag)
464       (goto-char (point-min))
465       (run-hooks 'reftex-display-copied-context-hook)
466       (message "Building %s buffer...done." buffer-name)
467       (setq buffer-read-only t))
468     (and locations (apply 'reftex-find-start-point (point) locations))
469     (if reftex-index-restriction-indicator
470         (message "Index restricted: <%s>" reftex-index-restriction-indicator))))
471
472 (defun reftex-insert-index (docstruct tag &optional update-one remark)
473   ;; Insert an index into the current buffer.  Entries are from the
474   ;; DOCSTRUCT.
475   ;; TAG is the subindex to process.
476   ;; UPDATE-ONE: When non-nil, delete the entry at point and replace
477   ;; it with whatever the DOCSTRUCT contains.
478   ;; REMARK can be a note to add to the entry.
479   (let* ((all docstruct)
480          (indent "   ")
481          (context reftex-index-include-context)
482          (context-indent (concat indent "  "))
483          (section-chars (mapcar 'identity reftex-index-section-letters))
484          (this-section-char 0)
485          (font (reftex-use-fonts))
486          (bor (car reftex-index-restriction-data))
487          (eor (nth 1 reftex-index-restriction-data))
488          (mouse-face
489           (if (memq reftex-highlight-selection '(mouse both))
490               reftex-mouse-selected-face
491             nil))
492          (index-face (reftex-verified-face reftex-label-face
493                                            'font-lock-constant-face
494                                            'font-lock-reference-face))
495          sublist cell from to first-char)
496
497     ;; Make the sublist and sort it
498     (when bor
499       (setq all (or (memq bor all) all)))
500
501     (while (setq cell (pop all))
502       (if (eq cell eor)
503           (setq all nil)
504         (and (eq (car cell) 'index)
505              (equal (nth 1 cell) tag)
506              (push cell sublist))))
507     (setq sublist (sort (nreverse sublist)
508                         (lambda (a b) (string< (nth 8 a) (nth 8 b)))))
509
510     (when update-one
511       ;; Delete the entry at place
512       (and (bolp) (forward-char 1))
513       (delete-region (previous-single-property-change (1+ (point)) :data)
514                      (or (next-single-property-change (point) :data)
515                          (point-max))))
516
517     ;; Walk through the list and insert all entries
518     (while (setq cell (pop sublist))
519       (unless update-one
520         (setq first-char (upcase (string-to-char (nth 6 cell))))
521         (when (and (not (equal first-char this-section-char))
522                    (member first-char section-chars))
523           ;; There is a new initial letter, so start a new section
524           (reftex-index-insert-new-letter first-char font)
525           (setq section-chars (delete first-char section-chars)
526                 this-section-char first-char))
527         (when (= this-section-char 0)
528           (setq this-section-char ?!)
529           (reftex-index-insert-new-letter this-section-char font)))
530
531       (setq from (point))
532       (insert indent (nth 7 cell))
533       (when font
534         (setq to (point))
535         (put-text-property
536          (- (point) (length (nth 7 cell))) to
537          'face index-face)
538         (goto-char to))
539
540       (when (or remark (nth 9 cell))
541         (and (< (current-column) 40)
542              ;; FIXME: maybe this is too slow?
543              (insert (make-string (max (- 40 (current-column)) 0) ?\ )))
544         (and (nth 9 cell) (insert "   " (substring (nth 5 cell) (nth 9 cell))))
545         (and remark (insert "     " remark)))
546
547       (insert "\n")
548       (setq to (point))
549
550       (when context
551         (insert context-indent (nth 2 cell) "\n")
552         (setq to (point)))
553       (put-text-property from to :data cell)
554       (when mouse-face
555         (put-text-property from (1- to)
556                            'mouse-face mouse-face))
557       (goto-char to))))
558
559
560 (defun reftex-index-insert-new-letter (letter &optional font)
561   ;; Start a new section in the index
562   (let ((from (point)))
563     (insert "\n" letter letter letter
564             "-----------------------------------------------------------------")
565     (when font
566       (put-text-property from (point) 'face reftex-index-section-face))
567     (insert "\n")))
568
569 (defun reftex-get-restriction (arg docstruct)
570   ;; Interprete the prefix ARG and derive index restriction specs.
571   (let* ((beg (min (point) (or (condition-case nil (mark) (error nil))
572                                (point-max))))
573          (end (max (point) (or (condition-case nil (mark) (error nil))
574                                (point-min))))
575          bor eor label here-I-am)
576     (cond
577      ((eq arg 2)
578       (setq here-I-am (car (reftex-where-am-I))
579             bor (if (eq (car here-I-am) 'toc)
580                     here-I-am
581                   (reftex-last-assoc-before-elt
582                    'toc here-I-am docstruct))
583             eor (car (memq (assq 'toc (cdr (memq bor docstruct))) docstruct))
584             label (nth 6 bor)))
585      ((eq arg 3)
586       (save-excursion
587         (setq label "region")
588         (goto-char beg)
589         (setq bor (car (reftex-where-am-I)))
590         (setq bor (nth 1 (memq bor docstruct)))
591         (goto-char end)
592         (setq eor (nth 1 (memq (car (reftex-where-am-I)) docstruct)))))
593      (t nil))
594     (if (and label (or bor eor))
595         (list label bor eor)
596       nil)))
597
598 (defun reftex-index-pre-command-hook ()
599   ;; Used as pre command hook in *Index* buffer
600   (reftex-unhighlight 0)
601   (reftex-unhighlight 1))
602
603 (defun reftex-index-post-command-hook ()
604   ;; Used in the post-command-hook for the *Index* buffer
605   (when (get-text-property (point) :data)
606     (and (> (point) 1)
607          (not (get-text-property (point) 'intangible))
608          (memq reftex-highlight-selection '(cursor both))
609          (reftex-highlight 1
610            (or (previous-single-property-change (1+ (point)) :data)
611                (point-min))
612            (or (next-single-property-change (point) :data)
613                (point-max)))))
614   (if (integerp reftex-index-follow-mode)
615       ;; Remove delayed action
616       (setq reftex-index-follow-mode t)
617     (and reftex-index-follow-mode
618          (not (equal reftex-last-follow-point (point)))
619          ;; Show context in other window
620          (setq reftex-last-follow-point (point))
621          (condition-case nil
622              (reftex-index-visit-location nil (not reftex-revisit-to-follow))
623            (error t)))))
624
625 (defun reftex-index-show-help ()
626   "Show a summary of special key bindings."
627   (interactive)
628   (with-output-to-temp-buffer "*RefTeX Help*"
629     (princ reftex-index-help))
630   (reftex-enlarge-to-fit "*RefTeX Help*" t)
631   ;; If follow mode is active, arrange to delay it one command
632   (if reftex-index-follow-mode
633       (setq reftex-index-follow-mode 1)))
634
635 (defun reftex-index-next (&optional arg)
636   "Move to next selectable item."
637   (interactive "p")
638   (setq reftex-callback-fwd t)
639   (or (eobp) (forward-char 1))
640   (goto-char (or (next-single-property-change (point) :data)
641                  (point)))
642   (unless (get-text-property (point) :data)
643     (goto-char (or (next-single-property-change (point) :data)
644                    (point)))))
645 (defun reftex-index-previous (&optional arg)
646   "Move to previous selectable item."
647   (interactive "p")
648   (setq reftex-callback-fwd nil)
649   (goto-char (or (previous-single-property-change (point) :data)
650                  (point)))
651   (unless (get-text-property (point) :data)
652     (goto-char (or (previous-single-property-change (point) :data)
653                    (point)))))
654 (defun reftex-index-toggle-follow ()
655   "Toggle follow (other window follows with context)."
656   (interactive)
657   (setq reftex-last-follow-point -1)
658   (setq reftex-index-follow-mode (not reftex-index-follow-mode)))
659 (defun reftex-index-toggle-context ()
660   "Toggle inclusion of label context in *Index* buffer.
661 Label context is only displayed when the labels are there as well."
662   (interactive)
663   (setq reftex-index-include-context (not reftex-index-include-context))
664   (reftex-index-revert))
665 (defun reftex-index-view-entry ()
666   "View document location in other window."
667   (interactive)
668   (reftex-index-visit-location))
669 (defun reftex-index-goto-entry-and-hide ()
670   "Go to document location in other window.  Hide the *Index* window."
671   (interactive)
672   (reftex-index-visit-location 'hide))
673 (defun reftex-index-goto-entry ()
674   "Go to document location in other window. *Index* window stays."
675   (interactive)
676   (reftex-index-visit-location t))
677 (defun reftex-index-mouse-goto-line-and-hide (ev)
678   "Go to document location in other window.  Hide the *Index* window."
679   (interactive "e")
680   (mouse-set-point ev)
681   (reftex-index-visit-location 'hide))
682 (defun reftex-index-quit ()
683   "Hide the *Index* window and do not move point."
684   (interactive)
685   (or (one-window-p) (delete-window))
686   (switch-to-buffer (marker-buffer reftex-index-return-marker))
687   (goto-char (or (marker-position reftex-index-return-marker) (point))))
688 (defun reftex-index-quit-and-kill ()
689   "Kill the *Index* buffer."
690   (interactive)
691   (kill-buffer (current-buffer))
692   (or (one-window-p) (delete-window))
693   (switch-to-buffer (marker-buffer reftex-index-return-marker))
694   (goto-char (or (marker-position reftex-index-return-marker) (point))))
695 (defun reftex-index-goto-toc (&rest ignore)
696   "Switch to the table of contents of the current document.
697 The function will go to the section where the entry at point was defined."
698   (interactive)
699   (if (get-text-property (point) :data)
700       (reftex-index-goto-entry)
701     (switch-to-buffer (marker-buffer reftex-index-return-marker)))
702   (delete-other-windows)
703   (reftex-toc))
704 (defun reftex-index-rescan (&rest ignore)
705   "Regenerate the *Index* buffer after reparsing file of section at point."
706   (interactive)
707   (let ((index-tag reftex-index-tag))
708     (if (and reftex-enable-partial-scans
709              (null current-prefix-arg))
710         (let* ((data (get-text-property (point) :data))
711                (file (nth 3 data))
712                (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
713           (if (not file)
714               (error "Don't know which file to rescan.  Try `C-u r'")
715             (switch-to-buffer (reftex-get-file-buffer-force file))
716             (setq current-prefix-arg '(4))
717             (reftex-display-index index-tag nil 'redo line)))
718       (reftex-index-Rescan))
719     (reftex-kill-temporary-buffers)))
720 (defun reftex-index-Rescan (&rest ignore)
721   "Regenerate the *Index* buffer after reparsing the entire document."
722   (interactive)
723   (let ((index-tag reftex-index-tag)
724         (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
725     (switch-to-buffer
726      (reftex-get-file-buffer-force reftex-last-index-file))
727     (setq current-prefix-arg '(16))
728     (reftex-display-index index-tag nil 'redo line)))
729 (defun reftex-index-revert (&rest ignore)
730   "Regenerate the *Index* from the internal lists.  No reparsing os done."
731   (interactive)
732   (let ((buf (current-buffer))
733         (index-tag reftex-index-tag)
734         (data (get-text-property (point) :data))
735         (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
736     (switch-to-buffer
737      (reftex-get-file-buffer-force reftex-last-index-file))
738     (reftex-erase-buffer buf)
739     (setq current-prefix-arg nil
740           reftex-last-follow-point 1)
741     (reftex-display-index index-tag nil 'redo data line)))
742 (defun reftex-index-switch-index-tag (&rest ignore)
743   "Switch to a different index of the same document."
744   (interactive)
745   (switch-to-buffer
746    (reftex-get-file-buffer-force reftex-last-index-file))
747   (setq current-prefix-arg nil)
748   (reftex-display-index nil nil 'redo))
749
750 (defun reftex-index-restrict-to-section (&optional force)
751   "Restrict index to entries defined in same document sect. as entry at point."
752   ;; Optional FORCE means, even if point is not on an index entry.
753   (interactive)
754   (let* ((data (get-text-property (point) :data))
755          (docstruct (symbol-value reftex-docstruct-symbol))
756          bor eor)
757     (if (and (not data) force)
758         (setq data (assq 'toc docstruct)))
759     (when data
760       (setq bor (reftex-last-assoc-before-elt 'toc data docstruct)
761             eor (car (memq (assq 'toc (cdr (memq bor docstruct)))
762                            docstruct))
763             reftex-index-restriction-data (list bor eor)
764             reftex-index-restriction-indicator (nth 6 bor) )))
765   (reftex-index-revert))
766
767 (defun reftex-index-widen (&rest ignore)
768   "Show the unrestricted index (all entries)."
769   (interactive)
770   (setq reftex-index-restriction-indicator nil
771         reftex-index-restriction-data nil)
772   (reftex-index-revert)
773   (message "Index widened"))
774 (defun reftex-index-restriction-forward (&rest ignore)
775   "Restrict to previous section.
776 When index is currently unrestricted, restrict it to a section.
777 When index is restricted, select the next section as restriction criterion."
778   (interactive)
779   (let* ((docstruct (symbol-value reftex-docstruct-symbol))
780          (bor (nth 1 reftex-index-restriction-data)))
781     (if (or (not bor)
782             (not (eq (car bor) 'toc)))
783         (reftex-index-restrict-to-section t)
784       (setq reftex-index-restriction-indicator (nth 6 bor)
785             reftex-index-restriction-data
786             (list bor
787                   (car (memq (assq 'toc (cdr (memq bor docstruct)))
788                              docstruct))))
789       (reftex-index-revert))))
790 (defun reftex-index-restriction-backward (&rest ignore)
791   "Restrict to next section.
792 When index is currently unrestricted, restrict it to a section.
793 When index is restricted, select the previous section as restriction criterion."
794   (interactive)
795   (let* ((docstruct (symbol-value reftex-docstruct-symbol))
796          (eor (car reftex-index-restriction-data))
797          (bor (reftex-last-assoc-before-elt 'toc eor docstruct t)))
798     (if (or (not bor)
799             (not (eq (car bor) 'toc)))
800         (reftex-index-restrict-to-section t)
801       (setq reftex-index-restriction-indicator (nth 6 bor)
802             reftex-index-restriction-data
803             (list bor eor))
804       (reftex-index-revert))))
805
806 (defun reftex-index-visit-location (&optional final no-revisit)
807   ;; Visit the tex file corresponding to the index entry on the current line.
808   ;; If FINAL is t, stay there
809   ;; If FINAL is 'hide, hide the *Index* window.
810   ;; Otherwise, move cursor back into *Index* window.
811   ;; NO-REVISIT means don't visit files, just use live biffers.
812
813   (let* ((data (get-text-property (point)