25280
|
1 ;;; reftex-index.el - Index support with RefTeX
|
|
2 ;;; Version: 4.5
|
|
3 ;;;
|
|
4 ;;; See main file reftex.el for licensing information
|
|
5
|
|
6 (provide 'reftex-index)
|
|
7 (require 'reftex)
|
|
8 ;;;
|
|
9
|
|
10 (defvar mark-active)
|
|
11 (defvar zmacs-regions)
|
|
12 (defun reftex-index-selection-or-word (&optional arg)
|
|
13 "Put selection or the word near point into the default index macro.
|
|
14 This uses the information in `reftex-index-default-macro' to make an index
|
|
15 entry. The phrase indexed is the current selection or the word near point.
|
|
16 When called with one `C-u' prefix, let the user have a chance to edit the
|
|
17 index entry. When called with 2 `C-u' as prefix, also ask for the index
|
|
18 macro and other stuff.
|
|
19 When called inside TeX math mode as determined by the `texmathp.el' library
|
|
20 which is part of AUCTeX, the string is first processed with the
|
|
21 `reftex-index-math-format', which see."
|
|
22 (interactive "P")
|
|
23 (let* ((use-default (not (equal arg '(16)))) ; check for double prefix
|
|
24 ;; check if we have an active selection
|
|
25 (active (if (boundp 'zmacs-regions)
|
|
26 (and zmacs-regions (region-exists-p)) ; XEmacs
|
|
27 (and transient-mark-mode mark-active))) ; Emacs
|
|
28 (beg (if active
|
|
29 (region-beginning)
|
|
30 (save-excursion
|
|
31 (skip-syntax-backward "w\\") (point))))
|
|
32 (end (if active
|
|
33 (region-end)
|
|
34 (save-excursion
|
|
35 (skip-syntax-forward "w\\") (point))))
|
|
36 (sel (buffer-substring beg end))
|
|
37 (mathp (condition-case nil (texmathp) (error nil)))
|
|
38 (current-prefix-arg nil) ; we want to call reftex-index without prefix.
|
|
39 key def-char def-tag full-entry repeat-word)
|
|
40
|
|
41 (if (equal sel "")
|
|
42 ;; Nothing selecte, no word, so use full reftex-index command
|
|
43 (reftex-index)
|
|
44 ;; OK, we have something to index here.
|
|
45 ;; Add the dollars when necessary
|
|
46 (setq key (if mathp
|
|
47 (format reftex-index-math-format sel)
|
|
48 sel))
|
|
49 ;; Get info from `reftex-index-default-macro'
|
|
50 (setq def-char (if use-default (car reftex-index-default-macro)))
|
|
51 (setq def-tag (if use-default (nth 1 reftex-index-default-macro)))
|
|
52 ;; Does the user want to edit the entry?
|
|
53 (setq full-entry (if arg
|
|
54 (reftex-index-complete-key
|
|
55 def-tag nil (cons key 0))
|
|
56 key))
|
|
57 ;; Do we neet to repeat the word outside the macro?
|
|
58 (setq repeat-word (if use-default
|
|
59 (nth 2 reftex-index-default-macro)
|
|
60 (y-or-n-p "Repeat phrase outside macro? ")))
|
|
61 ;; Delete what is in the buffer and make the index entry
|
|
62 (delete-region beg end)
|
|
63 (reftex-index def-char full-entry def-tag (if repeat-word sel nil)))))
|
|
64
|
|
65 (defun reftex-index (&optional char key tag postfix no-insert)
|
|
66 "Query for an index macro and insert it along with its argments.
|
|
67 The index macros available are those defined in `reftex-index-macro' or
|
|
68 by a call to `reftex-add-index-macros', typically from an AUCTeX style file.
|
|
69 RefteX provides completion for the index tag and the index key, and
|
|
70 will prompt for other arguments."
|
|
71
|
|
72 (interactive)
|
|
73
|
|
74 ;; Ensure access to scanning info
|
|
75 (reftex-ensure-index-support t)
|
|
76 (reftex-access-scan-info current-prefix-arg)
|
|
77
|
|
78 ;; Find out which macro we are going to use
|
|
79 (let* ((char (or char
|
|
80 (reftex-select-with-char reftex-query-index-macro-prompt
|
|
81 reftex-query-index-macro-help)))
|
|
82 (macro (nth 1 (assoc char reftex-key-to-index-macro-alist)))
|
|
83 (entry (or (assoc macro reftex-index-macro-alist)
|
|
84 (error "No index macro associated with %c" char)))
|
|
85 (ntag (nth 1 entry))
|
|
86 (tag (or tag (nth 1 entry)))
|
|
87 (nargs (nth 4 entry))
|
|
88 (nindex (nth 5 entry))
|
|
89 (opt-args (nth 6 entry))
|
|
90 opt tag1 value)
|
|
91
|
|
92 ;; Get the supported arguments
|
|
93 (if (stringp tag)
|
|
94 (setq tag1 tag)
|
|
95 (setq tag1 (or (reftex-index-complete-tag tag opt-args) "")))
|
|
96 (setq key (or key
|
|
97 (reftex-index-complete-key
|
|
98 (if (string= tag1 "") "idx" tag1)
|
|
99 (member nindex opt-args))))
|
|
100
|
|
101 ;; Insert the macro and ask for any additional args
|
|
102 (insert macro)
|
|
103 (loop for i from 1 to nargs do
|
|
104 (setq opt (member i opt-args)
|
|
105 value (cond ((= nindex i) key)
|
|
106 ((equal ntag i) tag1)
|
|
107 (t (read-string (concat "Macro arg nr. "
|
|
108 (int-to-string i)
|
|
109 (if opt " (optional)" "")
|
|
110 ": ")))))
|
|
111 (unless (and opt (string= value ""))
|
|
112 (insert (if opt "[" "{") value (if opt "]" "}"))))
|
|
113 (and (stringp postfix) (insert postfix))
|
|
114 (and key reftex-plug-into-AUCTeX (fboundp 'LaTeX-add-index-entries)
|
|
115 (LaTeX-add-index-entries key))
|
|
116 (reftex-index-update-taglist tag1)
|
|
117 (reftex-notice-new)))
|
|
118
|
|
119 (defun reftex-default-index ()
|
|
120 (cond ((null reftex-index-default-tag) nil)
|
|
121 ((stringp reftex-index-default-tag) reftex-index-default-tag)
|
|
122 (t (or (get reftex-docstruct-symbol 'default-index-tag)
|
|
123 "idx"))))
|
|
124
|
|
125 (defun reftex-update-default-index (tag &optional tag-list)
|
|
126 (if (and (not (equal tag ""))
|
|
127 (stringp tag)
|
|
128 (eq reftex-index-default-tag 'last)
|
|
129 (or (null tag-list)
|
|
130 (member tag tag-list)))
|
|
131 (put reftex-docstruct-symbol 'default-index-tag tag)))
|
|
132
|
|
133 (defun reftex-index-complete-tag (&optional itag opt-args)
|
|
134 ;; Ask the user for a tag, completing on known tags.
|
|
135 ;; ITAG is the argument number which contains the tag.
|
|
136 ;; OPT-ARGS is a list of optional argument indices, as given by
|
|
137 ;; `reftex-parse-args'.
|
|
138 (let* ((opt (and (integerp itag) (member itag opt-args)))
|
|
139 (index-tags (cdr (assq 'index-tags
|
|
140 (symbol-value reftex-docstruct-symbol))))
|
|
141 (default (reftex-default-index))
|
|
142 (prompt (concat "Index tag"
|
|
143 (if default (format " (default: %s)" default) "")
|
|
144 (if opt " (optional)" "") ": "))
|
|
145 (tag (completing-read prompt (mapcar 'list index-tags))))
|
|
146 (if (and default (equal tag "")) (setq tag default))
|
|
147 (reftex-update-default-index tag)
|
|
148 tag))
|
|
149
|
|
150 (defun reftex-index-select-tag ()
|
|
151 ;; Have the user select an index tag.
|
|
152 ;; FIXME: should we cache tag-alist, prompt and help?
|
|
153 (let* ((index-tags (cdr (assoc 'index-tags
|
|
154 (symbol-value reftex-docstruct-symbol))))
|
|
155 (default (reftex-default-index)))
|
|
156 (cond
|
|
157 ((null index-tags)
|
|
158 (error "No index tags available"))
|
|
159
|
|
160 ((= (length index-tags) 1)
|
|
161 ;; Just one index, use it
|
|
162 (car index-tags))
|
|
163
|
|
164 ((> (length index-tags) 1)
|
|
165 ;; Several indices, ask.
|
|
166 (let* ((tags (copy-sequence index-tags))
|
|
167 (cnt 0)
|
|
168 tag-alist i val len tag prompt help rpl)
|
|
169 ;; Move idx and glo up in the list to ensure ?i and ?g shortcuts
|
|
170 (if (member "glo" tags)
|
|
171 (setq tags (cons "glo" (delete "glo" tags))))
|
|
172 (if (member "idx" tags)
|
|
173 (setq tags (cons "idx" (delete "idx" tags))))
|
|
174 ;; Find unique shortcuts for each index.
|
|
175 (while (setq tag (pop tags))
|
|
176 (setq len (length tag)
|
|
177 i -1
|
|
178 val nil)
|
|
179 (catch 'exit
|
|
180 (while (and (< (incf i) len) (null val))
|
|
181 (unless (assq (aref tag i) tag-alist)
|
|
182 (push (list (aref tag i)
|
|
183 tag
|
|
184 (concat (substring tag 0 i)
|
|
185 "[" (substring tag i (incf i)) "]"
|
|
186 (substring tag i)))
|
|
187 tag-alist)
|
|
188 (throw 'exit t)))
|
|
189 (push (list (+ ?0 (incf cnt)) tag
|
|
190 (concat "[" (int-to-string cnt) "]:" tag))
|
|
191 tag-alist)))
|
|
192 (setq tag-alist (nreverse tag-alist))
|
|
193 ;; Compute Prompt and Help strings
|
|
194 (setq prompt
|
|
195 (concat
|
|
196 (format "Select Index%s: "
|
|
197 (if default (format " (Default <%s>)" default) ""))
|
|
198 (mapconcat (lambda(x) (nth 2 x)) tag-alist " ")))
|
|
199 (setq help
|
|
200 (concat "Select an Index\n===============\n"
|
|
201 (if default
|
|
202 (format "[^M] %s (the default)\n" default)
|
|
203 "")
|
|
204 (mapconcat (lambda(x)
|
|
205 (apply 'format "[%c] %s" x))
|
|
206 tag-alist "\n")))
|
|
207 ;; Query the user for an index-tag
|
|
208 (setq rpl (reftex-select-with-char prompt help 3 t))
|
|
209 (message "")
|
|
210 (if (and default (equal rpl ?\C-m))
|
|
211 default
|
|
212 (if (assq rpl tag-alist)
|
|
213 (progn
|
|
214 (reftex-update-default-index (nth 1 (assq rpl tag-alist)))
|
|
215 (nth 1 (assq rpl tag-alist)))
|
|
216 (error "No index tag associated with %c" rpl)))))
|
|
217 (t (error "This should not happen (reftex-index-select-tag)")))))
|
|
218
|
|
219 (defun reftex-index-complete-key (&optional tag optional initial)
|
|
220 ;; Read an index key, with completion.
|
|
221 ;; Restrict completion table on index tag TAG.
|
|
222 ;; OPTIONAL indicates if the arg is optional.
|
|
223 (let* ((table (reftex-sublist-nth
|
|
224 (symbol-value reftex-docstruct-symbol) 6
|
|
225 (lambda(x) (and (eq (car x) 'index)
|
|
226 (string= (nth 1 x) (or tag ""))))
|
|
227 t))
|
|
228 (prompt (concat "Index key" (if optional " (optional)" "") ": "))
|
|
229 (key (completing-read prompt table nil nil initial)))
|
|
230 key))
|
|
231
|
|
232 (defun reftex-index-update-taglist (newtag)
|
|
233 ;; add NEWTAG to the list of available index tags.
|
|
234 (let ((cell (assoc 'index-tags (symbol-value reftex-docstruct-symbol))))
|
|
235 (and newtag (cdr cell) (not (member newtag (cdr cell)))
|
|
236 (push newtag (cdr cell)))))
|
|
237
|
|
238 (defvar reftex-last-index-file)
|
|
239 (defun reftex-index-globally (&optional data call-file)
|
|
240 "Index a word with a global search and replace.
|
|
241 This works very much like `reftex-query-replace-document', but the
|
|
242 defaults for the search and replace strings are derived from
|
|
243 local context.
|
|
244 When there is an index entry, we try to index similar words. The word
|
|
245 to search for is either a word in direct contact with the index macro
|
|
246 (like `\\index{WORD}WORD' or `WORD\\index{WORD}') or the index key.
|
|
247 The replacement text is the index macro with all its arguments and the
|
|
248 attached word.
|
|
249 When there is no index entry at point, we search for the word near point
|
|
250 and propose to index it like this: `\\index{word}word'.
|
|
251 You get a chance to edit the search and replacement strings.
|
|
252 DATA can be a docstruct entry describing an index entry, and then the
|
|
253 defaults will be derived from it.
|
|
254 CALL-FILE may be the file from where to call the global search command."
|
|
255 (interactive)
|
|
256 (let* ((call-file (cond (call-file call-file)
|
|
257 (reftex-mode (buffer-file-name))
|
|
258 ((eq major-mode 'reftex-index-mode)
|
|
259 reftex-last-index-file)
|
|
260 (t (error "Need a call file here"))))
|
|
261 (pos (point))
|
|
262 (data (cond
|
|
263 (data data)
|
|
264 ((and reftex-mode
|
|
265 (save-excursion
|
|
266 (forward-char 20)
|
|
267 (re-search-backward reftex-everything-regexp nil t)
|
|
268 (< (count-lines (min pos (point)) (max pos (point)))
|
|
269 2)))
|
|
270 (reftex-index-info (buffer-file-name)))
|
|
271 (t nil)))
|
|
272 (ksep (car reftex-index-special-chars))
|
|
273 (words-include-escapes t)
|
|
274 (case-replace nil)
|
|
275 (case-fold-search t)
|
|
276 word rpl start analyze-list pre key attr actual post)
|
|
277
|
|
278 ;; Find the word and construct the replacement string
|
|
279 (if (and data (eq (car data) 'index))
|
|
280 ;; OK, we have an index entry
|
|
281 (progn
|
|
282 (setq analyze-list (reftex-index-analyze-entry data)
|
|
283 pre (car analyze-list)
|
|
284 key (nth 1 analyze-list)
|
|
285 attr (nth 2 analyze-list)
|
|
286 actual (nth 3 analyze-list)
|
|
287 post (nth 4 analyze-list))
|
|
288 (when (string-match (concat "\\<\\(\\sw+\\)" reftex-index-re) pre)
|
|
289 (setq word (match-string 1 pre)
|
|
290 pre (concat "<<<1>>>" (substring pre (match-end 1)))
|
|
291 rpl (concat pre key attr actual post)))
|
|
292 (when (string-match "}\\(\\sw+\\)\\>[^}]*\\'" post)
|
|
293 (setq word (match-string 1 post)
|
|
294 post (concat (substring post 0 (match-beginning 1))
|
|
295 "<<<1>>>")
|
|
296 rpl (concat pre key attr actual post)))
|
|
297 (when (and (not word) key)
|
|
298 (if (string-match (concat ".*" (regexp-quote ksep)) key)
|
|
299 (setq word (substring key (match-end 0)))
|
|
300 (setq word key))
|
|
301 (setq rpl (concat pre key attr actual post))))
|
|
302 ;; No index entry, just use local word.
|
|
303 (setq word (save-excursion
|
|
304 (buffer-substring-no-properties
|
|
305 (progn (skip-syntax-backward "w") (point))
|
|
306 (progn (skip-syntax-forward "w") (point))))
|
|
307 rpl (concat "\\index{" word "}<<<1>>>")))
|
|
308 ;; Quote what is necessary
|
|
309 (setq word (regexp-quote (downcase word)))
|
|
310 (setq start 0)
|
|
311 (while (setq start (string-match "\\\\" rpl start))
|
|
312 (setq rpl (replace-match "\\\\" t t rpl)
|
|
313 start (+ 2 start)))
|
|
314 ;; We used <<<1>>> instead of \1 to avoid the quoting. Fix this now.
|
|
315 (if (string-match "<<<1>>>" rpl)
|
|
316 (setq rpl (replace-match "\\1" t t rpl)))
|
|
317
|
|
318 ;; Give the user a chance to edit the strings
|
|
319 (setq word (read-string "Search: "
|
|
320 (if word (format "\\<\\(%s\\)\\>" word)))
|
|
321 rpl (read-string "Replace with: " rpl))
|
|
322
|
|
323 ;; Execute the command
|
|
324 (save-excursion
|
|
325 (switch-to-buffer (get-file-buffer call-file))
|
|
326 (condition-case nil
|
|
327 (reftex-query-replace-document word rpl)
|
|
328 (error nil)))))
|
|
329
|
|
330 (defvar reftex-index-map (make-sparse-keymap)
|
|
331 "Keymap used for *Index* buffers.")
|
|
332
|
|
333 (defvar reftex-index-menu)
|
|
334
|
|
335 (defvar reftex-last-index-file nil
|
|
336 "Stores the file name from which `reftex-display-index' was called.")
|
|
337 (defvar reftex-index-tag nil
|
|
338 "Stores the tag of the index in an index buffer.")
|
|
339
|
|
340 (defvar reftex-index-return-marker (make-marker)
|
|
341 "Marker which makes it possible to return from index to old position.")
|
|
342
|
|
343 (defvar reftex-index-restriction-indicator nil)
|
|
344 (defvar reftex-index-restriction-data nil)
|
|
345
|
|
346 (defun reftex-index-mode ()
|
|
347 "Major mode for managing Index buffers for LaTeX files.
|
|
348 This buffer was created with RefTeX.
|
|
349 Press `?' for a summary of important key bindings, or check the menu.
|
|
350
|
|
351 Here are all local bindings.
|
|
352
|
|
353 \\{reftex-index-map}"
|
|
354 (interactive)
|
|
355 (kill-all-local-variables)
|
|
356 (setq major-mode 'reftex-index-mode
|
|
357 mode-name "RefTeX Index")
|
|
358 (use-local-map reftex-index-map)
|
|
359 (set (make-local-variable 'revert-buffer-function) 'reftex-index-revert)
|
|
360 (set (make-local-variable 'reftex-index-restriction-data) nil)
|
|
361 (set (make-local-variable 'reftex-index-restriction-indicator) nil)
|
|
362 (setq mode-line-format
|
|
363 (list "---- " 'mode-line-buffer-identification
|
|
364 " " 'global-mode-string
|
|
365 " R<" 'reftex-index-restriction-indicator ">"
|
|
366 " -%-"))
|
|
367 (setq truncate-lines t)
|
|
368 (make-local-hook 'post-command-hook)
|
|
369 (make-local-hook 'pre-command-hook)
|
|
370 (make-local-variable 'reftex-last-follow-point)
|
|
371 (easy-menu-add reftex-index-menu reftex-index-map)
|
|
372 (add-hook 'post-command-hook 'reftex-index-post-command-hook nil t)
|
|
373 (add-hook 'pre-command-hook 'reftex-index-pre-command-hook nil t)
|
|
374 (run-hooks 'reftex-index-mode-hook))
|
|
375
|
|
376 (defconst reftex-index-help
|
|
377 " AVAILABLE KEYS IN INDEX BUFFER
|
|
378 ==============================
|
|
379 ! A..Z Goto the section of entries starting with this letter.
|
|
380 n / p next-entry / previous-entry
|
|
381 SPC / TAB Show/Goto the corresponding entry in the LaTeX document.
|
|
382 RET Goto the entry and hide the *Index* window (also on mouse-2).
|
|
383 q / k Hide/Kill *Index* buffer.
|
|
384 C-c = Switch to the TOC buffer.
|
|
385 f / c Toggle follow mode / Toggle display of [c]ontext.
|
|
386 g Refresh *Index* buffer.
|
|
387 r / C-u r Reparse the LaTeX document / Reparse entire LaTeX document.
|
|
388 s Switch to a different index (for documents with multiple indices).
|
|
389 e / C-k Edit/Kill the entry.
|
|
390 * | @ Edit specific part of entry: [*]key [|]attribute [@]visual
|
|
391 With prefix: kill that part.
|
|
392 ( ) Toggle entry's beginning/end of page range property.
|
|
393 _ ^ Add/Remove parent key (to make this item a subitem).
|
|
394 & Index the same word everywhere in the document.
|
|
395 } / { Restrict Index to a single document section / Widen.
|
|
396 < / > When restricted, move restriction to previous/next section.")
|
|
397
|
|
398 (defun reftex-index-show-entry (data &optional no-revisit)
|
|
399 ;; Find an index entry associated with DATA and display it highlighted
|
|
400 ;; in another window. NO-REVISIT means we are not allowed to visit
|
|
401 ;; files for this.
|
|
402 ;; Note: This function just looks for the nearest match of the
|
|
403 ;; context string and may fail if the entry moved and an identical
|
|
404 ;; entry is close to the old position. Frequent rescans make this
|
|
405 ;; safer.
|
|
406 (let* ((file (nth 3 data))
|
|
407 (literal (nth 2 data))
|
|
408 (pos (nth 4 data))
|
|
409 (re (regexp-quote literal))
|
|
410 (match
|
|
411 (cond
|
|
412 ((or (not no-revisit)
|
|
413 (reftex-get-buffer-visiting file))
|
|
414 (switch-to-buffer-other-window
|
|
415 (reftex-get-file-buffer-force file nil))
|
|
416 (goto-char (or pos (point-min)))
|
|
417 (or (looking-at re)
|
|
418 (reftex-nearest-match re (length literal))))
|
|
419 (t (message reftex-no-follow-message) nil))))
|
|
420 (when match
|
|
421 (goto-char (match-beginning 0))
|
|
422 (recenter '(4))
|
|
423 (reftex-highlight 0 (match-beginning 0) (match-end 0) (current-buffer)))
|
|
424 match))
|
|
425
|
|
426 (defun reftex-display-index (&optional tag overriding-restriction
|
|
427 &rest locations)
|
|
428 "Display a buffer with an index compiled from the current document.
|
|
429 When the document has multiple indices, first prompts for the correct one.
|
|
430 When index support is turned off, offer to turn it on.
|
|
431 With one or two `C-u' prefixes, rescan document first.
|
|
432 With prefix 2, restrict index to current document section.
|
|
433 With prefix 3, restrict index to region."
|
|
434
|
|
435 (interactive)
|
|
436
|
|
437 ;; Ensure access to scanning info and rescan buffer if prefix are is '(4).
|
|
438 (let ((current-prefix-arg current-prefix-arg))
|
|
439 (reftex-ensure-index-support t)
|
|
440 (reftex-access-scan-info current-prefix-arg))
|
|
441
|
|
442 (set-marker reftex-index-return-marker (point))
|
|
443 (setq reftex-last-follow-point 1)
|
|
444
|
|
445 ;; Determine the correct index to process
|
|
446 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
|
|
447 (docstruct-symbol reftex-docstruct-symbol)
|
|
448 (index-tag (or tag (reftex-index-select-tag)))
|
|
449 (master (reftex-TeX-master-file))
|
|
450 (calling-file (buffer-file-name))
|
|
451 (restriction
|
|
452 (or overriding-restriction
|
|
453 (and (interactive-p)
|
|
454 (reftex-get-restriction current-prefix-arg docstruct))))
|
|
455 (locations
|
|
456 ;; See if we are on an index macro as initial position
|
|
457 (or locations
|
|
458 (let* ((what-macro (reftex-what-macro-safe 1))
|
|
459 (macro (car what-macro))
|
|
460 (here-I-am (when (member macro reftex-macros-with-index)
|
|
461 (save-excursion
|
|
462 (goto-char (+ (cdr what-macro)
|
|
463 (length macro)))
|
|
464 (reftex-move-over-touching-args)
|
|
465 (reftex-where-am-I)))))
|
|
466 (if (eq (car (car here-I-am)) 'index)
|
|
467 (list (car here-I-am))))))
|
|
468 buffer-name)
|
|
469
|
|
470 (setq buffer-name (reftex-make-index-buffer-name index-tag))
|
|
471
|
|
472 ;; Goto the buffer and put it into the correct mode
|
|
473
|
|
474 (when (or restriction current-prefix-arg)
|
|
475 (reftex-kill-buffer buffer-name))
|
|
476
|
|
477 (if (get-buffer-window buffer-name)
|
|
478 (select-window (get-buffer-window buffer-name))
|
|
479 (let ((default-major-mode 'reftex-index-mode))
|
|
480 (switch-to-buffer buffer-name)))
|
|
481
|
|
482 (or (eq major-mode 'reftex-index-mode) (reftex-index-mode))
|
|
483
|
|
484 ;; If the buffer is currently restricted, empty it to force update.
|
|
485 (when reftex-index-restriction-data
|
|
486 (reftex-erase-buffer))
|
|
487 (set (make-local-variable 'reftex-last-index-file) calling-file)
|
|
488 (set (make-local-variable 'reftex-index-tag) index-tag)
|
|
489 (set (make-local-variable 'reftex-docstruct-symbol) docstruct-symbol)
|
|
490 (if restriction
|
|
491 (setq reftex-index-restriction-indicator (car restriction)
|
|
492 reftex-index-restriction-data (cdr restriction))
|
|
493 (if (interactive-p)
|
|
494 (setq reftex-index-restriction-indicator nil
|
|
495 reftex-index-restriction-data nil)))
|
|
496 (when (= (buffer-size) 0)
|
|
497 ;; buffer is empty - fill it
|
|
498 (message "Building %s buffer..." buffer-name)
|
|
499
|
|
500 (setq buffer-read-only nil)
|
|
501 (insert (format
|
|
502 "INDEX <%s> on %s
|
|
503 Restriction: <%s>
|
|
504 SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help
|
|
505 ------------------------------------------------------------------------------
|
|
506 " index-tag (abbreviate-file-name master)
|
|
507 (if (eq (car (car reftex-index-restriction-data)) 'toc)
|
|
508 (nth 2 (car reftex-index-restriction-data))
|
|
509 reftex-index-restriction-indicator)))
|
|
510
|
|
511 (if (reftex-use-fonts)
|
|
512 (put-text-property 1 (point) 'face reftex-index-header-face))
|
|
513 (put-text-property 1 (point) 'intangible t)
|
|
514
|
|
515 (reftex-insert-index docstruct index-tag)
|
|
516 (goto-char (point-min))
|
|
517 (run-hooks 'reftex-display-copied-context-hook)
|
|
518 (message "Building %s buffer...done." buffer-name)
|
|
519 (setq buffer-read-only t))
|
|
520 (and locations (apply 'reftex-find-start-point (point) locations))
|
|
521 (if reftex-index-restriction-indicator
|
|
522 (message "Index restricted: <%s>" reftex-index-restriction-indicator))))
|
|
523
|
|
524 (defun reftex-insert-index (docstruct tag &optional update-one remark)
|
|
525 ;; Insert an index into the current buffer. Entries are from the
|
|
526 ;; DOCSTRUCT.
|
|
527 ;; TAG is the subindex to process.
|
|
528 ;; UPDATE-ONE: When non-nil, delete the entry at point and replace
|
|
529 ;; it with whatever the DOCSTRUCT contains.
|
|
530 ;; REMARK can be a note to add to the entry.
|
|
531 (let* ((all docstruct)
|
|
532 (indent " ")
|
|
533 (context reftex-index-include-context)
|
|
534 (context-indent (concat indent " "))
|
|
535 (section-chars (mapcar 'identity reftex-index-section-letters))
|
|
536 (this-section-char 0)
|
|
537 (font (reftex-use-fonts))
|
|
538 (bor (car reftex-index-restriction-data))
|
|
539 (eor (nth 1 reftex-index-restriction-data))
|
|
540 (mouse-face
|
|
541 (if (memq reftex-highlight-selection '(mouse both))
|
|
542 reftex-mouse-selected-face
|
|
543 nil))
|
|
544 (index-face (reftex-verified-face reftex-label-face
|
|
545 'font-lock-constant-face
|
|
546 'font-lock-reference-face))
|
|
547 sublist cell from to first-char)
|
|
548
|
|
549 ;; Make the sublist and sort it
|
|
550 (when bor
|
|
551 (setq all (or (memq bor all) all)))
|
|
552
|
|
553 (while (setq cell (pop all))
|
|
554 (if (eq cell eor)
|
|
555 (setq all nil)
|
|
556 (and (eq (car cell) 'index)
|
|
557 (equal (nth 1 cell) tag)
|
|
558 (push cell sublist))))
|
|
559 (setq sublist (sort (nreverse sublist)
|
|
560 (lambda (a b) (string< (nth 8 a) (nth 8 b)))))
|
|
561
|
|
562 (when update-one
|
|
563 ;; Delete the entry at place
|
|
564 (and (bolp) (forward-char 1))
|
|
565 (delete-region (previous-single-property-change (1+ (point)) :data)
|
|
566 (or (next-single-property-change (point) :data)
|
|
567 (point-max))))
|
|
568
|
|
569 ;; Walk through the list and insert all entries
|
|
570 (while (setq cell (pop sublist))
|
|
571 (unless update-one
|
|
572 (setq first-char (upcase (string-to-char (nth 6 cell))))
|
|
573 (when (and (not (equal first-char this-section-char))
|
|
574 (member first-char section-chars))
|
|
575 ;; There is a new initial letter, so start a new section
|
|
576 (reftex-index-insert-new-letter first-char font)
|
|
577 (setq section-chars (delete first-char section-chars)
|
|
578 this-section-char first-char))
|
|
579 (when (= this-section-char 0)
|
|
580 (setq this-section-char ?!)
|
|
581 (reftex-index-insert-new-letter this-section-char font)))
|
|
582
|
|
583 (setq from (point))
|
|
584 (insert indent (nth 7 cell))
|
|
585 (when font
|
|
586 (setq to (point))
|
|
587 (put-text-property
|
|
588 (- (point) (length (nth 7 cell))) to
|
|
589 'face index-face)
|
|
590 (goto-char to))
|
|
591
|
|
592 (when (or remark (nth 9 cell))
|
|
593 (and (< (current-column) 40)
|
|
594 ;; FIXME: maybe this is too slow?
|
|
595 (insert (make-string (max (- 40 (current-column)) 0) ?\ )))
|
|
596 (and (nth 9 cell) (insert " " (substring (nth 5 cell) (nth 9 cell))))
|
|
597 (and remark (insert " " remark)))
|
|
598
|
|
599 (insert "\n")
|
|
600 (setq to (point))
|
|
601
|
|
602 (when context
|
|
603 (insert context-indent (nth 2 cell) "\n")
|
|
604 (setq to (point)))
|
|
605 (put-text-property from to :data cell)
|
|
606 (when mouse-face
|
|
607 (put-text-property from (1- to)
|
|
608 'mouse-face mouse-face))
|
|
609 (goto-char to))))
|
|
610
|
|
611
|
|
612 (defun reftex-index-insert-new-letter (letter &optional font)
|
|
613 ;; Start a new section in the index
|
|
614 (let ((from (point)))
|
|
615 (insert "\n" letter letter letter
|
|
616 "-----------------------------------------------------------------")
|
|
617 (when font
|
|
618 (put-text-property from (point) 'face reftex-index-section-face))
|
|
619 (insert "\n")))
|
|
620
|
|
621 (defun reftex-get-restriction (arg docstruct)
|
|
622 ;; Interprete the prefix ARG and derive index restriction specs.
|
|
623 (let* ((beg (min (point) (or (condition-case nil (mark) (error nil))
|
|
624 (point-max))))
|
|
625 (end (max (point) (or (condition-case nil (mark) (error nil))
|
|
626 (point-min))))
|
|
627 bor eor label here-I-am)
|
|
628 (cond
|
|
629 ((eq arg 2)
|
|
630 (setq here-I-am (car (reftex-where-am-I))
|
|
631 bor (if (eq (car here-I-am) 'toc)
|
|
632 here-I-am
|
|
633 (reftex-last-assoc-before-elt
|
|
634 'toc here-I-am docstruct))
|
|
635 eor (car (memq (assq 'toc (cdr (memq bor docstruct))) docstruct))
|
|
636 label (nth 6 bor)))
|
|
637 ((eq arg 3)
|
|
638 (save-excursion
|
|
639 (setq label "region")
|
|
640 (goto-char beg)
|
|
641 (setq bor (car (reftex-where-am-I)))
|
|
642 (setq bor (nth 1 (memq bor docstruct)))
|
|
643 (goto-char end)
|
|
644 (setq eor (nth 1 (memq (car (reftex-where-am-I)) docstruct)))))
|
|
645 (t nil))
|
|
646 (if (and label (or bor eor))
|
|
647 (list label bor eor)
|
|
648 nil)))
|
|
649
|
|
650 (defun reftex-index-pre-command-hook ()
|
|
651 ;; Used as pre command hook in *Index* buffer
|
|
652 (reftex-unhighlight 0)
|
|
653 (reftex-unhighlight 1))
|
|
654
|
|
655 (defun reftex-index-post-command-hook ()
|
|
656 ;; Used in the post-command-hook for the *Index* buffer
|
|
657 (when (get-text-property (point) :data)
|
|
658 (and (> (point) 1)
|
|
659 (not (get-text-property (point) 'intangible))
|
|
660 (memq reftex-highlight-selection '(cursor both))
|
|
661 (reftex-highlight 1
|
|
662 (or (previous-single-property-change (1+ (point)) :data)
|
|
663 (point-min))
|
|
664 (or (next-single-property-change (point) :data)
|
|
665 (point-max)))))
|
|
666 (if (integerp reftex-index-follow-mode)
|
|
667 ;; Remove delayed action
|
|
668 (setq reftex-index-follow-mode t)
|
|
669 (and reftex-index-follow-mode
|
|
670 (not (equal reftex-last-follow-point (point)))
|
|
671 ;; Show context in other window
|
|
672 (setq reftex-last-follow-point (point))
|
|
673 (condition-case nil
|
|
674 (reftex-index-visit-location nil (not reftex-revisit-to-follow))
|
|
675 (error t)))))
|
|
676
|
|
677 (defun reftex-index-show-help ()
|
|
678 "Show a summary of special key bindings."
|
|
679 (interactive)
|
|
680 (with-output-to-temp-buffer "*RefTeX Help*"
|
|
681 (princ reftex-index-help))
|
|
682 (reftex-enlarge-to-fit "*RefTeX Help*" t)
|
|
683 ;; If follow mode is active, arrange to delay it one command
|
|
684 (if reftex-index-follow-mode
|
|
685 (setq reftex-index-follow-mode 1)))
|
|
686
|
|
687 (defun reftex-index-next (&optional arg)
|
|
688 "Move to next selectable item."
|
|
689 (interactive "p")
|
|
690 (setq reftex-callback-fwd t)
|
|
691 (or (eobp) (forward-char 1))
|
|
692 (goto-char (or (next-single-property-change (point) :data)
|
|
693 (point)))
|
|
694 (unless (get-text-property (point) :data)
|
|
695 (goto-char (or (next-single-property-change (point) :data)
|
|
696 (point)))))
|
|
697 (defun reftex-index-previous (&optional arg)
|
|
698 "Move to previous selectable item."
|
|
699 (interactive "p")
|
|
700 (setq reftex-callback-fwd nil)
|
|
701 (goto-char (or (previous-single-property-change (point) :data)
|
|
702 (point)))
|
|
703 (unless (get-text-property (point) :data)
|
|
704 (goto-char (or (previous-single-property-change (point) :data)
|
|
705 (point)))))
|
|
706 (defun reftex-index-toggle-follow ()
|
|
707 "Toggle follow (other window follows with context)."
|
|
708 (interactive)
|
|
709 (setq reftex-last-follow-point -1)
|
|
710 (setq reftex-index-follow-mode (not reftex-index-follow-mode)))
|
|
711 (defun reftex-index-toggle-context ()
|
|
712 "Toggle inclusion of label context in *Index* buffer.
|
|
713 Label context is only displayed when the labels are there as well."
|
|
714 (interactive)
|
|
715 (setq reftex-index-include-context (not reftex-index-include-context))
|
|
716 (reftex-index-revert))
|
|
717 (defun reftex-index-view-entry ()
|
|
718 "View document location in other window."
|
|
719 (interactive)
|
|
720 (reftex-index-visit-location))
|
|
721 (defun reftex-index-goto-entry-and-hide ()
|
|
722 "Go to document location in other window. Hide the *Index* window."
|
|
723 (interactive)
|
|
724 (reftex-index-visit-location 'hide))
|
|
725 (defun reftex-index-goto-entry ()
|
|
726 "Go to document location in other window. *Index* window stays."
|
|
727 (interactive)
|
|
728 (reftex-index-visit-location t))
|
|
729 (defun reftex-index-mouse-goto-line-and-hide (ev)
|
|
730 "Go to document location in other window. Hide the *Index* window."
|
|
731 (interactive "e")
|
|
732 (mouse-set-point ev)
|
|
733 (reftex-index-visit-location 'hide))
|
|
734 (defun reftex-index-quit ()
|
|
735 "Hide the *Index* window and do not move point."
|
|
736 (interactive)
|
|
737 (or (one-window-p) (delete-window))
|
|
738 (switch-to-buffer (marker-buffer reftex-index-return-marker))
|
|
739 (goto-char (or (marker-position reftex-index-return-marker) (point))))
|
|
740 (defun reftex-index-quit-and-kill ()
|
|
741 "Kill the *Index* buffer."
|
|
742 (interactive)
|
|
743 (kill-buffer (current-buffer))
|
|
744 (or (one-window-p) (delete-window))
|
|
745 (switch-to-buffer (marker-buffer reftex-index-return-marker))
|
|
746 (goto-char (or (marker-position reftex-index-return-marker) (point))))
|
|
747 (defun reftex-index-goto-toc (&rest ignore)
|
|
748 "Switch to the table of contents of the current document.
|
|
749 The function will go to the section where the entry at point was defined."
|
|
750 (interactive)
|
|
751 (if (get-text-property (point) :data)
|
|
752 (reftex-index-goto-entry)
|
|
753 (switch-to-buffer (marker-buffer reftex-index-return-marker)))
|
|
754 (delete-other-windows)
|
|
755 (reftex-toc))
|
|
756 (defun reftex-index-rescan (&rest ignore)
|
|
757 "Regenerate the *Index* buffer after reparsing file of section at point."
|
|
758 (interactive)
|
|
759 (let ((index-tag reftex-index-tag))
|
|
760 (if (and reftex-enable-partial-scans
|
|
761 (null current-prefix-arg))
|
|
762 (let* ((data (get-text-property (point) :data))
|
|
763 (file (nth 3 data))
|
|
764 (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
|
|
765 (if (not file)
|
|
766 (error "Don't know which file to rescan. Try `C-u r'")
|
|
767 (switch-to-buffer (reftex-get-file-buffer-force file))
|
|
768 (setq current-prefix-arg '(4))
|
|
769 (reftex-display-index index-tag nil line)))
|
|
770 (reftex-index-Rescan))
|
|
771 (reftex-kill-temporary-buffers)))
|
|
772 (defun reftex-index-Rescan (&rest ignore)
|
|
773 "Regenerate the *Index* buffer after reparsing the entire document."
|
|
774 (interactive)
|
|
775 (let ((index-tag reftex-index-tag)
|
|
776 (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
|
|
777 (switch-to-buffer
|
|
778 (reftex-get-file-buffer-force reftex-last-index-file))
|
|
779 (setq current-prefix-arg '(16))
|
|
780 (reftex-display-index index-tag nil line)))
|
|
781 (defun reftex-index-revert (&rest ignore)
|
|
782 "Regenerate the *Index* from the internal lists. No reparsing os done."
|
|
783 (interactive)
|
|
784 (let ((buf (current-buffer))
|
|
785 (index-tag reftex-index-tag)
|
|
786 (data (get-text-property (point) :data))
|
|
787 (line (+ (count-lines (point-min) (point)) (if (bolp) 1 0))))
|
|
788 (switch-to-buffer
|
|
789 (reftex-get-file-buffer-force reftex-last-index-file))
|
|
790 (reftex-erase-buffer buf)
|
|
791 (setq current-prefix-arg nil
|
|
792 reftex-last-follow-point 1)
|
|
793 (reftex-display-index index-tag nil data line)))
|
|
794 (defun reftex-index-switch-index-tag (&rest ignore)
|
|
795 "Switch to a different index of the same document."
|
|
796 (interactive)
|
|
797 (switch-to-buffer
|
|
798 (reftex-get-file-buffer-force reftex-last-index-file))
|
|
799 (setq current-prefix-arg nil)
|
|
800 (reftex-display-index))
|
|
801
|
|
802 (defun reftex-index-restrict-to-section (&optional force)
|
|
803 "Restrict index to entries defined in same document sect. as entry at point."
|
|
804 ;; Optional FORCE means, even if point is not on an index entry.
|
|
805 (interactive)
|
|
806 (let* ((data (get-text-property (point) :data))
|
|
807 (docstruct (symbol-value reftex-docstruct-symbol))
|
|
808 bor eor)
|
|
809 (if (and (not data) force)
|
|
810 (setq data (assq 'toc docstruct)))
|
|
811 (when data
|
|
812 (setq bor (reftex-last-assoc-before-elt 'toc data docstruct)
|
|
813 eor (car (memq (assq 'toc (cdr (memq bor docstruct)))
|
|
814 docstruct))
|
|
815 reftex-index-restriction-data (list bor eor)
|
|
816 reftex-index-restriction-indicator (nth 6 bor) )))
|
|
817 (reftex-index-revert))
|
|
818
|
|
819 (defun reftex-index-widen (&rest ignore)
|
|
820 "Show the unrestricted index (all entries)."
|
|
821 (interactive)
|
|
822 (setq reftex-index-restriction-indicator nil
|
|
823 reftex-index-restriction-data nil)
|
|
824 (reftex-index-revert)
|
|
825 (message "Index widened"))
|
|
826 (defun reftex-index-restriction-forward (&rest ignore)
|
|
827 "Restrict to previous section.
|
|
828 When index is currently unrestricted, restrict it to a section.
|
|
829 When index is restricted, select the next section as restriction criterion."
|
|
830 (interactive)
|
|
831 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
|
|
832 (bor (nth 1 reftex-index-restriction-data)))
|
|
833 (if (or (not bor)
|
|
834 (not (eq (car bor) 'toc)))
|
|
835 (reftex-index-restrict-to-section t)
|
|
836 (setq reftex-index-restriction-indicator (nth 6 bor)
|
|
837 reftex-index-restriction-data
|
|
838 (list bor
|
|
839 (car (memq (assq 'toc (cdr (memq bor docstruct)))
|
|
840 docstruct))))
|
|
841 (reftex-index-revert))))
|
|
842 (defun reftex-index-restriction-backward (&rest ignore)
|
|
843 "Restrict to next section.
|
|
844 When index is currently unrestricted, restrict it to a section.
|
|
845 When index is restricted, select the previous section as restriction criterion."
|
|
846 (interactive)
|
|
847 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
|
|
848 (eor (car reftex-index-restriction-data))
|
|
849 (bor (reftex-last-assoc-before-elt 'toc eor docstruct t)))
|
|
850 (if (or (not bor)
|
|
851 (not (eq (car bor) 'toc)))
|
|
852 (reftex-index-restrict-to-section t)
|
|
853 (setq reftex-index-restriction-indicator (nth 6 bor)
|
|
854 reftex-index-restriction-data
|
|
855 (list bor eor))
|
|
856 (reftex-index-revert))))
|
|
857
|
|
858 (defun reftex-index-visit-location (&optional final no-revisit)
|
|
859 ;; Visit the tex file corresponding to the index entry on the current line.
|
|
860 ;; If FINAL is t, stay there
|
|
861 ;; If FINAL is 'hide, hide the *Index* window.
|
|
862 ;; Otherwise, move cursor back into *Index* window.
|
|
863 ;; NO-REVISIT means don't visit files, just use live biffers.
|
|
864
|
|
865 (let* ((data (get-text-property (point) :data))
|
|
866 (index-window (selected-window))
|
|
867 show-window show-buffer match)
|
|
868
|
|
869 (unless data (error "Don't know which index entry to visit"))
|
|
870
|
|
871 (if (eq (car data) 'index)
|
|
872 (setq match (reftex-index-show-entry data no-revisit)))
|
|
873
|
|
874 (setq show-window (selected-window)
|
|
875 show-buffer (current-buffer))
|
|
876
|
|
877 (unless match
|
|
878 (select-window index-window)
|
|
879 (error "Cannot find location"))
|
|
880
|
|
881 (select-window index-window)
|
|
882
|
|
883 ;; Use the `final' parameter to decide what to do next
|
|
884 (cond
|
|
885 ((eq final t)
|
|
886 (reftex-unhighlight 0)
|
|
887 (select-window show-window))
|
|
888 ((eq final 'hide)
|
|
889 (reftex-unhighlight 0)
|
|
890 (or (one-window-p) (delete-window))
|
|
891 (switch-to-buffer show-buffer))
|
|
892 (t nil))))
|
|
893
|
|
894 (defun reftex-index-analyze-entry (data)
|
|
895 ;; This splits the index context so that key, attribute and visual
|
|
896 ;; values are accessible individually.
|
|
897 (interactive)
|
|
898 (let* ((arg (nth 5 data))
|
|
899 (context (nth 2 data))
|
|
900 (sc reftex-index-special-chars)
|
|
901 (boa (if (string-match (regexp-quote (concat "{" arg "}")) context)
|
|
902 (1+ (match-beginning 0))
|
|
903 (error "Something is wrong here")))
|
|
904 (eoa (1- (match-end 0)))
|
|
905 (boactual (if (string-match (concat "[^" (nth 3 sc) "]" (nth 2 sc))
|
|
906 context boa)
|
|
907 (1+ (match-beginning 0))
|
|
908 eoa))
|
|
909 (boattr (if (string-match (concat "[^" (nth 3 sc) "]" (nth 1 sc))
|
|
910 context boa)
|
|
911 (1+ (match-beginning 0))
|
|
912 boactual))
|
|
913 (pre (substring context 0 boa))
|
|
914 (key (substring context boa boattr))
|
|
915 (attr (substring context boattr boactual))
|
|
916 (actual (substring context boactual eoa))
|
|
917 (post (substring context eoa)))
|
|
918 (list pre key attr actual post)))
|
|
919
|
|
920 (defun reftex-index-globalize (&optional arg)
|
|
921 "Globalize the current index entry.
|
|
922 This starts a global search and replace to index the same word
|
|
923 at other places in the document. After this function completes, you
|
|
924 need to rescan the document with `r' or `C-u r' in order to get the
|
|
925 entries into the index buffer.
|
|
926 Defaults for the search and replace strings are derived from
|
|
927 the current entry. See the command `reftex-index-globally'."
|
|
928 (interactive)
|
|
929 (let* ((data (get-text-property (point) :data))
|
|
930 (buf (current-buffer)))
|
|
931 (unless data
|
|
932 (error "No index entry at point"))
|
|
933 (reftex-index-globally data)
|
|
934 (switch-to-buffer buf)))
|
|
935
|
|
936 (defun reftex-index-edit ()
|
|
937 "Edit the index entry at point."
|
|
938 (interactive)
|
|
939 (let* ((data (get-text-property (point) :data))
|
|
940 old new)
|
|
941 (unless data (error "Don't know which index entry to edit"))
|
|
942 (reftex-index-view-entry)
|
|
943 (setq old (nth 2 data) new (read-string "Edit: " old))
|
|
944 (reftex-index-change-entry new)))
|
|
945
|
|
946 (defun reftex-index-toggle-range-beginning ()
|
|
947 "Toggle the page range start attribute `|('."
|
|
948 (interactive)
|
|
949 (let* ((data (get-text-property (point) :data))
|
|
950 (bor (concat (nth 1 reftex-index-special-chars) "("))
|
|
951 new analyze attr)
|
|
952 (unless data (error "Don't know which index entry to edit"))
|
|
953 (setq analyze (reftex-index-analyze-entry data)
|
|
954 attr (nth 2 analyze))
|
|
955 (setf (nth 2 analyze) (if (string= attr bor) "" bor))
|
|
956 (setq new (apply 'concat analyze))
|
|
957 (reftex-index-change-entry
|
|
958 new (if (string= (nth 2 analyze) bor)
|
|
959 "Entry is now START-OF-PAGE-RANGE"
|
|
960 "START-OF-PAGE-RANGE canceled"))))
|
|
961
|
|
962 (defun reftex-index-toggle-range-end ()
|
|
963 "Toggle the page-range-end attribute `|)'."
|
|
964 (interactive)
|
|
965 (let* ((data (get-text-property (point) :data))
|
|
966 (eor (concat (nth 1 reftex-index-special-chars) "("))
|
|
967 new analyze attr)
|
|
968 (unless data (error "Don't know which index entry to edit"))
|
|
969 (setq analyze (reftex-index-analyze-entry data)
|
|
970 attr (nth 2 analyze))
|
|
971 (setf (nth 2 analyze) (if (string= attr eor) "" eor))
|
|
972 (setq new (apply 'concat analyze))
|
|
973 (reftex-index-change-entry
|
|
974 new (if (string= (nth 2 analyze) eor)
|
|
975 "Entry is now END-OF-PAGE-RANGE"
|
|
976 "END-OF-PAGE-RANGE canceled"))))
|
|
977
|
|
978 (defun reftex-index-edit-key ()
|
|
979 "Edit the KEY part of the index entry."
|
|
980 (interactive)
|
|
981 (reftex-index-edit-part nil 1 "" "Key: " t))
|
|
982
|
|
983 (defun reftex-index-edit-attribute (&optional arg)
|
|
984 "EDIT the ATTRIBUTE part of the entry. With arg: remove entire ATTRIBUTE."
|
|
985 (interactive "P")
|
|
986 (reftex-index-edit-part arg 2 (nth 1 reftex-index-special-chars)
|
|
987 "Attribute: "))
|
|
988
|
|
989 (defun reftex-index-edit-visual (&optional arg)
|
|
990 "EDIT the VISUAL part of the entry. With arg: remove entire VISUAL string."
|
|
991 (interactive "P")
|
|
992 (reftex-index-edit-part arg 3 (nth 2 reftex-index-special-chars) "Visual: "))
|
|
993
|
|
994 (defun reftex-index-edit-part (arg n initial prompt &optional dont-allow-empty)
|
|
995 ;; This function does the work for all partial editing commands
|
|
996 (let* ((data (get-text-property (point) :data))
|
|
997 new analyze opart npart)
|
|
998 (unless data (error "Don't know which index entry to edit"))
|
|
999 ;; Analyze the whole context string
|
|
1000 (setq analyze (reftex-index-analyze-entry data)
|
|
1001 opart (nth n analyze))
|
|
1002 (and (> (length opart) 0) (setq opart (substring opart 1)))
|
|
1003 ;; Have the user editing the part
|
|
1004 (setq npart (if arg "" (read-string (concat prompt initial) opart)))
|
|
1005 ;; Tests:
|
|
1006 (cond ((string= npart opart)
|
|
1007 (error "Not changed"))
|
|
1008 ((string= npart "")
|
|
1009 (if dont-allow-empty
|
|
1010 (error "Illegal value")
|
|
1011 (setf (nth n analyze) npart)))
|
|
1012 (t (setf (nth n analyze) (concat initial npart))))
|
|
1013 (setq new (apply 'concat analyze))
|
|
1014 ;; Change the entry and insert the changed version into the index.
|
|
1015 (reftex-index-change-entry
|
|
1016 new (if (string= npart "")
|
|
1017 (format "Deleted: %s" opart)
|
|
1018 (format "New value is: %s" npart)))))
|
|
1019
|
|
1020 (defun reftex-index-level-down ()
|
|
1021 "Make index entry a subitem of another entry."
|
|
1022 (interactive)
|
|
1023 (let* ((data (get-text-property (point) :data))
|
|
1024 (docstruct (symbol-value reftex-docstruct-symbol))
|
|
1025 old new prefix key)
|
|
1026 (unless data (error "Don't know which index entry to change"))
|
|
1027 (setq old (nth 2 data)
|
|
1028 key (nth 6 data)
|
|
1029 prefix (completing-read
|
|
1030 "Prefix: "
|
|
1031 (reftex-sublist-nth
|
|
1032 docstruct 6
|
|
1033 (lambda (x)
|
|
1034 (and (eq (car x) 'index)
|
|
1035 (string= (nth 1 x) reftex-index-tag))) t)))
|
|
1036 (unless (string-match
|
|
1037 (concat (regexp-quote (car reftex-index-special-chars)) "\\'")
|
|
1038 prefix)
|
|
1039 (setq prefix (concat prefix (car reftex-index-special-chars))))
|
|
1040 (if (string-match (regexp-quote key) old)
|
|
1041 (setq new (replace-match (concat prefix key) t t old))
|
|
1042 (error "Cannot construct new index key"))
|
|
1043 (reftex-index-change-entry new (format "Added prefix: %s" prefix))))
|
|
1044
|
|
1045 (defun reftex-index-level-up ()
|
|
1046 "Remove the highest level of a hierarchical index entry."
|
|
1047 (interactive)
|
|
1048 (let* ((data (get-text-property (point) :data))
|
|
1049 old new prefix)
|
|
1050 (unless data (error "Don't know which entry to change"))
|
|
1051 (setq old (nth 2 data))
|
|
1052 (if (string-match (concat "{\\([^" (nth 0 reftex-index-special-chars) "]*"
|
|
1053 "[^" (nth 3 reftex-index-special-chars) "]"
|
|
1054 (regexp-quote (nth 0 reftex-index-special-chars))
|
|
1055 "\\)")
|
|
1056 old)
|
|
1057 (setq prefix (substring old (match-beginning 1) (match-end 1))
|
|
1058 new (concat (substring old 0 (match-beginning 1))
|
|
1059 (substring old (match-end 1))))
|
|
1060 (error "Entry is not a subitem"))
|
|
1061 (reftex-index-change-entry new (format "Removed prefix: %s" prefix))))
|
|
1062
|
|
1063 (defun reftex-index-kill ()
|
|
1064 "FIXME: Not yet implemented"
|
|
1065 (interactive)
|
|
1066 (error "This function is currently not implemented"))
|
|
1067
|
|
1068 (defun reftex-index-undo ()
|
|
1069 "FIXME: Not yet implemented"
|
|
1070 (interactive)
|
|
1071 (error "This function is currently not implemented"))
|
|
1072
|
|
1073 (defun reftex-index-change-entry (new &optional message)
|
|
1074 ;; Change the full context string of the index entry at point to
|
|
1075 ;; NEW. This actually edits the buffer where the entry is defined.
|
|
1076
|
|
1077 (let* ((data (get-text-property (point) :data))
|
|
1078 old beg end info)
|
|
1079 (unless data (error "Cannot change entry"))
|
|
1080 (reftex-index-view-entry)
|
|
1081 (setq beg (match-beginning 0) end (match-end 0))
|
|
1082 (setq old (nth 2 data))
|
|
1083 (and (equal old new) (error "Entry unchanged"))
|
|
1084 (save-excursion
|
|
1085 (set-buffer (get-file-buffer (nth 3 data)))
|
|
1086 (goto-char beg)
|
|
1087 (unless (looking-at (regexp-quote old))
|
|
1088 (error "This should not happen (reftex-index-change-entry)"))
|
|
1089 (delete-region beg end)
|
|
1090 (insert new)
|
|
1091 (goto-char (1- beg))
|
|
1092 (when (and (re-search-forward (reftex-everything-regexp) nil t)
|
|
1093 (match-end 10)
|
|
1094 (< (abs (- (match-beginning 10) beg)) (length new))
|
|
1095 (setq info (reftex-index-info-safe buffer-file-name)))
|
|
1096 (setcdr data (cdr info))))
|
|
1097 (let ((buffer-read-only nil))
|
|
1098 (save-excursion
|
|
1099 (reftex-insert-index (list data) reftex-index-tag t
|
|
1100 "EDITED")))
|
|
1101 (setq reftex-last-follow-point 1)
|
|
1102 (and message (message message))))
|
|
1103
|
|
1104 ;; Index map
|
|
1105 (define-key reftex-index-map (if (featurep 'xemacs) [(button2)] [(mouse-2)])
|
|
1106 'reftex-index-mouse-goto-line-and-hide)
|
|
1107
|
|
1108 (substitute-key-definition
|
|
1109 'next-line 'reftex-index-next reftex-index-map global-map)
|
|
1110 (substitute-key-definition
|
|
1111 'previous-line 'reftex-index-previous reftex-index-map global-map)
|
|
1112
|
|
1113 (loop for x in
|
|
1114 '(("n" . reftex-index-next)
|
|
1115 ("p" . reftex-index-previous)
|
|
1116 ("?" . reftex-index-show-help)
|
|
1117 (" " . reftex-index-view-entry)
|
|
1118 ("\C-m" . reftex-index-goto-entry-and-hide)
|
|
1119 ("\C-i" . reftex-index-goto-entry)
|
|
1120 ("\C-k" . reftex-index-kill)
|
|
1121 ("r" . reftex-index-rescan)
|
|
1122 ("R" . reftex-index-Rescan)
|
|
1123 ("g" . revert-buffer)
|
|
1124 ("q" . reftex-index-quit)
|
|
1125 ("k" . reftex-index-quit-and-kill)
|
|
1126 ("f" . reftex-index-toggle-follow)
|
|
1127 ("s" . reftex-index-switch-index-tag)
|
|
1128 ("e" . reftex-index-edit)
|
|
1129 ("^" . reftex-index-level-up)
|
|
1130 ("_" . reftex-index-level-down)
|
|
1131 ("}" . reftex-index-restrict-to-section)
|
|
1132 ("{" . reftex-index-widen)
|
|
1133 (">" . reftex-index-restriction-forward)
|
|
1134 ("<" . reftex-index-restriction-backward)
|
|
1135 ("(" . reftex-index-toggle-range-beginning)
|
|
1136 (")" . reftex-index-toggle-range-end)
|
|
1137 ("|" . reftex-index-edit-attribute)
|
|
1138 ("@" . reftex-index-edit-visual)
|
|
1139 ("*" . reftex-index-edit-key)
|
|
1140 ("&" . reftex-index-globalize)
|
|
1141 ("\C-c=". reftex-index-goto-toc)
|
|
1142 ("c" . reftex-index-toggle-context))
|
|
1143 do (define-key reftex-index-map (car x) (cdr x)))
|
|
1144
|
|
1145 (loop for key across "0123456789" do
|
|
1146 (define-key reftex-index-map (vector (list key)) 'digit-argument))
|
|
1147 (define-key reftex-index-map "-" 'negative-argument)
|
|
1148
|
|
1149 ;; The capital letters and the exclamation mark
|
|
1150 (loop for key across (concat "!" reftex-index-section-letters) do
|
|
1151 (define-key reftex-index-map (vector (list key))
|
|
1152 (list 'lambda '() '(interactive)
|
|
1153 (list 'reftex-index-goto-letter key))))
|
|
1154
|
|
1155 (defun reftex-index-goto-letter (char)
|
|
1156 "Go to the CHAR section in the index."
|
|
1157 (let ((pos (point))
|
|
1158 (case-fold-search nil))
|
|
1159 (goto-line 3)
|
|
1160 (if (re-search-forward (concat "^" (char-to-string char)) nil t)
|
|
1161 (progn
|
|
1162 (beginning-of-line)
|
|
1163 (recenter 0)
|
|
1164 (reftex-index-next))
|
|
1165 (goto-char pos)
|
|
1166 (error "This <%s> index does not contain entries starting with `%c'"
|
|
1167 reftex-index-tag char))))
|
|
1168
|
|
1169 (easy-menu-define
|
|
1170 reftex-index-menu reftex-index-map
|
|
1171 "Menu for Index buffer"
|
|
1172 `("Index"
|
|
1173 ["Goto section A-Z"
|
|
1174 (message "To go to a section, just press any of: !%s"
|
|
1175 reftex-index-section-letters) t]
|
|
1176 ["Show Entry" reftex-index-view-entry t]
|
|
1177 ["Go To Entry" reftex-index-goto-entry t]
|
|
1178 ["Exit & Go To Entry" reftex-index-goto-entry-and-hide t]
|
|
1179 ["Table of Contents" reftex-index-goto-toc t]
|
|
1180 ["Quit" reftex-index-quit t]
|
|
1181 "--"
|
|
1182 ("Update"
|
|
1183 ["Rebuilt *Index* Buffer" revert-buffer t]
|
|
1184 "--"
|
|
1185 ["Rescan One File" reftex-index-rescan reftex-enable-partial-scans]
|
|
1186 ["Rescan Entire Document" reftex-index-Rescan t])
|
|
1187 ("Restrict"
|
|
1188 ["Restrict to section" reftex-index-restrict-to-section t]
|
|
1189 ["Widen" reftex-index-widen reftex-index-restriction-indicator]
|
|
1190 ["Next Section" reftex-index-restriction-forward
|
|
1191 reftex-index-restriction-indicator]
|
|
1192 ["Previous Section" reftex-index-restriction-backward
|
|
1193 reftex-index-restriction-indicator])
|
|
1194 ("Edit"
|
|
1195 ["Edit Entry" reftex-index-edit t]
|
|
1196 ["Edit Key" reftex-index-edit-key t]
|
|
1197 ["Edit Attribute" reftex-index-edit-attribute t]
|
|
1198 ["Edit Visual" reftex-index-edit-visual t]
|
|
1199 "--"
|
|
1200 ["Add Parentkey" reftex-index-level-down t]
|
|
1201 ["Remove Parentkey " reftex-index-level-up t]
|
|
1202 "--"
|
|
1203 ["Make Start-of-Range" reftex-index-toggle-range-beginning t]
|
|
1204 ["Make End-of-Range" reftex-index-toggle-range-end t]
|
|
1205 "--"
|
|
1206 ["Globalize" reftex-index-globalize t]
|
|
1207 ["Kill Entry" reftex-index-kill nil]
|
|
1208 "--"
|
|
1209 ["Undo" reftex-index-undo nil])
|
|
1210 ("Options"
|
|
1211 ["Context" reftex-index-toggle-context :style toggle
|
|
1212 :selected reftex-index-include-context]
|
|
1213 "--"
|
|
1214 ["Follow Mode" reftex-index-toggle-follow :style toggle
|
|
1215 :selected reftex-index-follow-mode])
|
|
1216 "--"
|
|
1217 ["Help" reftex-index-show-help t]))
|
|
1218
|
|
1219 ;;; reftex-index.el ends here
|