Mercurial > emacs
comparison lisp/textmodes/reftex-index.el @ 25280:9b601931b795
Initial revision
author | Carsten Dominik <dominik@science.uva.nl> |
---|---|
date | Mon, 16 Aug 1999 07:42:41 +0000 |
parents | |
children | 4c4fabd16782 |
comparison
equal
deleted
inserted
replaced
25279:03cb8fb8ab28 | 25280:9b601931b795 |
---|---|
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 |