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