Mercurial > emacs
comparison lisp/textmodes/reftex-index.el @ 26910:489a5439b988
* reftex.el (reftex-compile-variables): respect new structure of
`reftex-index-macro'
(reftex-compile-variables): Use the changed structure of
`reftex-label-alist'.
* reftex-vars.el (reftex-index-math-format,
(reftex-toc-max-level): New option.
reftex-index-phrases-search-whole-words,
reftex-index-phrases-case-fold-search,
reftex-index-phrases-skip-indexed-matches,
reftex-index-phrases-wrap-long-lines,
reftex-index-phrases-sort-prefers-entry,
reftex-index-phrases-sort-in-blocks): New options.
(reftex-index-macros): Option structure changed.
(reftex-index-macros-builtin): Added `repeat' item to each entry.
(reftex-label-alist): Additional item in each entry to specify if
the environment should be listed in the TOC.
(eval-when-compile (require 'cl)) added.
* reftex-index.el (reftex-index-selection-or-word): No longer
deals with "repeat".
(reftex-index): "repeat property in `reftex-index-macro-alist' is
now used.
(reftex-index-phrases-comment-regexp,
reftex-index-phrases-macrodef-regexp,
reftex-index-phrases-phrase-regexp1,
reftex-index-phrases-phrase-regexp2,
reftex-index-phrases-phrase-regexp12, reftex-index-phrases-help):
New constants.
(reftex-index-phrases-macro-data, reftex-index-phrases-files,
reftex-index-phrases-font-lock-keywords,
reftex-index-phrases-font-lock-defaults, reftex-index-phrases-map,
reftex-index-phrases-restrict-file): New variables.
(reftex-index-phrase-selection-or-word,
reftex-index-visit-phrases-buffer,
reftex-index-initialize-phrases-buffer,
reftex-index-phrases-save-and-return, reftex-index-phrases-mode,
reftex-index-next-phrase, reftex-index-this-phrase,
reftex-index-all-phrases, reftex-index-region-phrases,
reftex-index-phrases-parse-header,
reftex-index-phrases-toggle-restricted, reftex-index-new-phrase,
reftex-index-find-next-conflict-phrase, reftex-index-phrases-info,
reftex-index-phrases-set-macro-key, reftex-index-sort-phrases,
reftex-compare-phrase-lines, reftex-index-make-phrase-regexp,
reftex-index-simplify-phrase, reftex-index-phrases-find-dup-re,
reftex-index-make-replace-string,
reftex-query-index-phrase-globally, reftex-query-index-phrase,
reftex-index-phrase-match-is-indexed,
reftex-index-phrases-fixup-line,
reftex-index-phrases-replace-space,
reftex-index-select-phrases-macro): New functions.
(reftex-index-globalize, reftex-index-globally): functions removed
(eval-when-compile (require 'cl)) added.
* reftex-toc.el (reftex-toc-mode): Create new indicator for max
level.
(reftex-toc-max-level-indicator): New variable.
(reftex-toc-max-level): New command.
(reftex-toc-map): New keybinding `t'.
(reftex-toc-help): Constant updated.
(eval-when-compile (require 'cl)) added.
* reftex-ref.el (reftex-offer-label-menu): Prefix to `t' command key
can change `reftex-toc-max-level'
(eval-when-compile (require 'cl)) added.
* reftex-sel (reftex-insert-docstruct): Respect
`reftex-toc-max-level'
(eval-when-compile (require 'cl)) added.
* reftex-auc.el (eval-when-compile (require 'cl)) added.
* reftex-vcr.el (eval-when-compile (require 'cl)) added.
* reftex-cite.el (reftex-citep, reftex-citet): New commands.
(reftex-citation, reftex-do-citation,
reftex-figure-out-cite-format): Additional argument FORMAT-KEY to
preselect a citation format.
(eval-when-compile (require 'cl)) added.
* reftex-parse.el (reftex-context-substring): Optional parameter
to-end
(reftex-section-info): Deal with environment matches.
(eval-when-compile (require 'cl)) added.
* reftex-global.el (eval-when-compile (require 'cl)) added.
author | Carsten Dominik <dominik@science.uva.nl> |
---|---|
date | Wed, 15 Dec 1999 17:02:38 +0000 |
parents | 7ed67319c5aa |
children | 083669ed376a |
comparison
equal
deleted
inserted
replaced
26909:5a2ef05e2490 | 26910:489a5439b988 |
---|---|
1 ;;; reftex-index.el - Index support with RefTeX | 1 ;;; reftex-index.el - Index support with RefTeX |
2 ;;; Version: 4.6 | 2 ;;; Version: 4.9 |
3 ;;; | 3 ;;; |
4 ;;; See main file reftex.el for licensing information | 4 ;;; See main file reftex.el for licensing information |
5 | 5 |
6 (eval-when-compile (require 'cl)) | |
6 (provide 'reftex-index) | 7 (provide 'reftex-index) |
7 (require 'reftex) | 8 (require 'reftex) |
8 ;;; | 9 ;;; |
9 | 10 |
10 (defvar mark-active) | 11 (defvar mark-active) |
11 (defvar zmacs-regions) | 12 (defvar zmacs-regions) |
12 (defvar transient-mark-mode) | 13 (defvar transient-mark-mode) |
13 (defun reftex-index-selection-or-word (&optional arg) | 14 (defun reftex-index-selection-or-word (&optional arg phrase) |
14 "Put selection or the word near point into the default index macro. | 15 "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 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 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 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 index entry. When called with 2 `C-u' as prefix, also ask for the index |
35 (save-excursion | 36 (save-excursion |
36 (skip-syntax-forward "w\\") (point)))) | 37 (skip-syntax-forward "w\\") (point)))) |
37 (sel (buffer-substring beg end)) | 38 (sel (buffer-substring beg end)) |
38 (mathp (condition-case nil (texmathp) (error nil))) | 39 (mathp (condition-case nil (texmathp) (error nil))) |
39 (current-prefix-arg nil) ; we want to call reftex-index without prefix. | 40 (current-prefix-arg nil) ; we want to call reftex-index without prefix. |
40 key def-char def-tag full-entry repeat-word) | 41 key def-char def-tag full-entry) |
41 | 42 |
42 (if (equal sel "") | 43 (if phrase |
43 ;; Nothing selecte, no word, so use full reftex-index command | 44 (progn |
44 (reftex-index) | 45 (reftex-index-visit-phrases-buffer) |
45 ;; OK, we have something to index here. | 46 (reftex-index-new-phrase sel)) |
46 ;; Add the dollars when necessary | 47 |
47 (setq key (if mathp | 48 (if (equal sel "") |
48 (format reftex-index-math-format sel) | 49 ;; Nothing selected, no word, so use full reftex-index command |
49 sel)) | 50 (reftex-index) |
50 ;; Get info from `reftex-index-default-macro' | 51 ;; OK, we have something to index here. |
51 (setq def-char (if use-default (car reftex-index-default-macro))) | 52 ;; Add the dollars when necessary |
52 (setq def-tag (if use-default (nth 1 reftex-index-default-macro))) | 53 (setq key (if mathp |
53 ;; Does the user want to edit the entry? | 54 (format reftex-index-math-format sel) |
54 (setq full-entry (if arg | 55 sel)) |
55 (reftex-index-complete-key | 56 ;; Get info from `reftex-index-default-macro' |
56 def-tag nil (cons key 0)) | 57 (setq def-char (if use-default (car reftex-index-default-macro))) |
57 key)) | 58 (setq def-tag (if use-default (nth 1 reftex-index-default-macro))) |
58 ;; Do we neet to repeat the word outside the macro? | 59 ;; Does the user want to edit the entry? |
59 (setq repeat-word (if use-default | 60 (setq full-entry (if arg |
60 (nth 2 reftex-index-default-macro) | 61 (reftex-index-complete-key |
61 (y-or-n-p "Repeat phrase outside macro? "))) | 62 def-tag nil (cons key 0)) |
62 ;; Delete what is in the buffer and make the index entry | 63 key)) |
63 (delete-region beg end) | 64 ;; Delete what is in the buffer and make the index entry |
64 (reftex-index def-char full-entry def-tag (if repeat-word sel nil))))) | 65 (delete-region beg end) |
65 | 66 (reftex-index def-char full-entry def-tag sel))))) |
66 (defun reftex-index (&optional char key tag postfix no-insert) | 67 |
68 (defun reftex-index (&optional char key tag sel no-insert) | |
67 "Query for an index macro and insert it along with its argments. | 69 "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 | 70 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. | 71 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 | 72 RefteX provides completion for the index tag and the index key, and |
71 will prompt for other arguments." | 73 will prompt for other arguments." |
86 (ntag (nth 1 entry)) | 88 (ntag (nth 1 entry)) |
87 (tag (or tag (nth 1 entry))) | 89 (tag (or tag (nth 1 entry))) |
88 (nargs (nth 4 entry)) | 90 (nargs (nth 4 entry)) |
89 (nindex (nth 5 entry)) | 91 (nindex (nth 5 entry)) |
90 (opt-args (nth 6 entry)) | 92 (opt-args (nth 6 entry)) |
93 (repeat (nth 7 entry)) | |
91 opt tag1 value) | 94 opt tag1 value) |
92 | 95 |
93 ;; Get the supported arguments | 96 ;; Get the supported arguments |
94 (if (stringp tag) | 97 (if (stringp tag) |
95 (setq tag1 tag) | 98 (setq tag1 tag) |
109 (int-to-string i) | 112 (int-to-string i) |
110 (if opt " (optional)" "") | 113 (if opt " (optional)" "") |
111 ": "))))) | 114 ": "))))) |
112 (unless (and opt (string= value "")) | 115 (unless (and opt (string= value "")) |
113 (insert (if opt "[" "{") value (if opt "]" "}")))) | 116 (insert (if opt "[" "{") value (if opt "]" "}")))) |
114 (and (stringp postfix) (insert postfix)) | 117 (and repeat (stringp sel) (insert sel)) |
115 (and key reftex-plug-into-AUCTeX (fboundp 'LaTeX-add-index-entries) | 118 (and key reftex-plug-into-AUCTeX (fboundp 'LaTeX-add-index-entries) |
116 (LaTeX-add-index-entries key)) | 119 (LaTeX-add-index-entries key)) |
117 (reftex-index-update-taglist tag1) | 120 (reftex-index-update-taglist tag1) |
118 (reftex-notice-new))) | 121 (reftex-notice-new))) |
119 | 122 |
234 ;; add NEWTAG to the list of available index tags. | 237 ;; add NEWTAG to the list of available index tags. |
235 (let ((cell (assoc 'index-tags (symbol-value reftex-docstruct-symbol)))) | 238 (let ((cell (assoc 'index-tags (symbol-value reftex-docstruct-symbol)))) |
236 (and newtag (cdr cell) (not (member newtag (cdr cell))) | 239 (and newtag (cdr cell) (not (member newtag (cdr cell))) |
237 (push newtag (cdr cell))))) | 240 (push newtag (cdr cell))))) |
238 | 241 |
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) | 242 (defvar reftex-index-map (make-sparse-keymap) |
332 "Keymap used for *Index* buffers.") | 243 "Keymap used for *Index* buffers.") |
333 | 244 |
334 (defvar reftex-index-menu) | 245 (defvar reftex-index-menu) |
335 | 246 |
390 e / C-k Edit/Kill the entry. | 301 e / C-k Edit/Kill the entry. |
391 * | @ Edit specific part of entry: [*]key [|]attribute [@]visual | 302 * | @ Edit specific part of entry: [*]key [|]attribute [@]visual |
392 With prefix: kill that part. | 303 With prefix: kill that part. |
393 ( ) Toggle entry's beginning/end of page range property. | 304 ( ) Toggle entry's beginning/end of page range property. |
394 _ ^ Add/Remove parent key (to make this item a subitem). | 305 _ ^ 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. | 306 } / { Restrict Index to a single document section / Widen. |
397 < / > When restricted, move restriction to previous/next section.") | 307 < / > When restricted, move restriction to previous/next section.") |
398 | 308 |
399 (defun reftex-index-show-entry (data &optional no-revisit) | 309 (defun reftex-index-show-entry (data &optional no-revisit) |
400 ;; Find an index entry associated with DATA and display it highlighted | 310 ;; Find an index entry associated with DATA and display it highlighted |
916 (attr (substring context boattr boactual)) | 826 (attr (substring context boattr boactual)) |
917 (actual (substring context boactual eoa)) | 827 (actual (substring context boactual eoa)) |
918 (post (substring context eoa))) | 828 (post (substring context eoa))) |
919 (list pre key attr actual post))) | 829 (list pre key attr actual post))) |
920 | 830 |
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 () | 831 (defun reftex-index-edit () |
938 "Edit the index entry at point." | 832 "Edit the index entry at point." |
939 (interactive) | 833 (interactive) |
940 (let* ((data (get-text-property (point) :data)) | 834 (let* ((data (get-text-property (point) :data)) |
941 old new) | 835 old new) |
962 | 856 |
963 (defun reftex-index-toggle-range-end () | 857 (defun reftex-index-toggle-range-end () |
964 "Toggle the page-range-end attribute `|)'." | 858 "Toggle the page-range-end attribute `|)'." |
965 (interactive) | 859 (interactive) |
966 (let* ((data (get-text-property (point) :data)) | 860 (let* ((data (get-text-property (point) :data)) |
967 (eor (concat (nth 1 reftex-index-special-chars) "(")) | 861 (eor (concat (nth 1 reftex-index-special-chars) ")")) |
968 new analyze attr) | 862 new analyze attr) |
969 (unless data (error "Don't know which index entry to edit")) | 863 (unless data (error "Don't know which index entry to edit")) |
970 (setq analyze (reftex-index-analyze-entry data) | 864 (setq analyze (reftex-index-analyze-entry data) |
971 attr (nth 2 analyze)) | 865 attr (nth 2 analyze)) |
972 (setf (nth 2 analyze) (if (string= attr eor) "" eor)) | 866 (setf (nth 2 analyze) (if (string= attr eor) "" eor)) |
1136 ("(" . reftex-index-toggle-range-beginning) | 1030 ("(" . reftex-index-toggle-range-beginning) |
1137 (")" . reftex-index-toggle-range-end) | 1031 (")" . reftex-index-toggle-range-end) |
1138 ("|" . reftex-index-edit-attribute) | 1032 ("|" . reftex-index-edit-attribute) |
1139 ("@" . reftex-index-edit-visual) | 1033 ("@" . reftex-index-edit-visual) |
1140 ("*" . reftex-index-edit-key) | 1034 ("*" . reftex-index-edit-key) |
1141 ("&" . reftex-index-globalize) | |
1142 ("\C-c=". reftex-index-goto-toc) | 1035 ("\C-c=". reftex-index-goto-toc) |
1143 ("c" . reftex-index-toggle-context)) | 1036 ("c" . reftex-index-toggle-context)) |
1144 do (define-key reftex-index-map (car x) (cdr x))) | 1037 do (define-key reftex-index-map (car x) (cdr x))) |
1145 | 1038 |
1146 (loop for key across "0123456789" do | 1039 (loop for key across "0123456789" do |
1162 (progn | 1055 (progn |
1163 (beginning-of-line) | 1056 (beginning-of-line) |
1164 (recenter 0) | 1057 (recenter 0) |
1165 (reftex-index-next)) | 1058 (reftex-index-next)) |
1166 (goto-char pos) | 1059 (goto-char pos) |
1167 (error "This <%s> index does not contain entries starting with `%c'" | 1060 (if (eq char ?!) |
1168 reftex-index-tag char)))) | 1061 (error "This <%s> index does not contain entries sorted before the letters" |
1062 reftex-index-tag) | |
1063 (error "This <%s> index does not contain entries starting with `%c'" | |
1064 reftex-index-tag char))))) | |
1169 | 1065 |
1170 (easy-menu-define | 1066 (easy-menu-define |
1171 reftex-index-menu reftex-index-map | 1067 reftex-index-menu reftex-index-map |
1172 "Menu for Index buffer" | 1068 "Menu for Index buffer" |
1173 `("Index" | 1069 `("Index" |
1202 ["Remove Parentkey " reftex-index-level-up t] | 1098 ["Remove Parentkey " reftex-index-level-up t] |
1203 "--" | 1099 "--" |
1204 ["Make Start-of-Range" reftex-index-toggle-range-beginning t] | 1100 ["Make Start-of-Range" reftex-index-toggle-range-beginning t] |
1205 ["Make End-of-Range" reftex-index-toggle-range-end t] | 1101 ["Make End-of-Range" reftex-index-toggle-range-end t] |
1206 "--" | 1102 "--" |
1207 ["Globalize" reftex-index-globalize t] | |
1208 ["Kill Entry" reftex-index-kill nil] | 1103 ["Kill Entry" reftex-index-kill nil] |
1209 "--" | 1104 "--" |
1210 ["Undo" reftex-index-undo nil]) | 1105 ["Undo" reftex-index-undo nil]) |
1211 ("Options" | 1106 ("Options" |
1212 ["Context" reftex-index-toggle-context :style toggle | 1107 ["Context" reftex-index-toggle-context :style toggle |
1215 ["Follow Mode" reftex-index-toggle-follow :style toggle | 1110 ["Follow Mode" reftex-index-toggle-follow :style toggle |
1216 :selected reftex-index-follow-mode]) | 1111 :selected reftex-index-follow-mode]) |
1217 "--" | 1112 "--" |
1218 ["Help" reftex-index-show-help t])) | 1113 ["Help" reftex-index-show-help t])) |
1219 | 1114 |
1115 | |
1116 ;;---------------------------------------------------------------------- | |
1117 ;; The Index Phrases File | |
1118 | |
1119 ;; Some constants and variables | |
1120 (defconst reftex-index-phrases-comment-regexp "^[ \t]*%.*" | |
1121 "Regular expression to match comment lines in phrases buffer") | |
1122 (defconst reftex-index-phrases-macrodef-regexp | |
1123 "^\\(>>>INDEX_MACRO_DEFINITION:\\)[ \t]+\\(\\S-\\)\\( *\t[ \t]*\\)\\([^\t]*[^ \t]\\)\\( *\t[ \t]*\\)\\(\\S-+\\)" | |
1124 "Regular expression to match macro definition lines the phrases buffer.") | |
1125 ;(defconst reftex-index-phrases-macrodef-regexp | |
1126 ; "^\\(>>>INDEX_MACRO_DEFINITION:\\)[ \t]+\\(\\S-\\)\\([ \t]*\\)\\([^\t]*[^ \t]\\)\\([ \t]*\\)\\(nil\\|t\\)[ \t]*$" | |
1127 ; "Regular expression to match macro definition lines the phrases buffer. | |
1128 ;This version would allow just spaces as separators.") | |
1129 (defconst reftex-index-phrases-phrase-regexp1 | |
1130 "^\\(\\S-?\\)\\(\t\\)\\([^\t\n]*\\S-\\)\\([ \t]*\\)$" | |
1131 "Regular expression matching phrases which have no separate index key.") | |
1132 (defconst reftex-index-phrases-phrase-regexp2 | |
1133 "^\\(\\S-?\\)\\(\t\\)\\([^\t]*\\S-\\)\\(\t[ \t]*\\)\\([^\n\t]*\\S-\\)[ \t]*$" | |
1134 "Regular expression matching phrases which have a separate index key.") | |
1135 (defconst reftex-index-phrases-phrase-regexp12 | |
1136 "^\\(\\S-?\\)\\(\t\\)\\([^\n\t]*\\S-\\)\\(\\(\t[ \t]*\\)\\([^\n\t]*\\S-\\)\\)?[ \t]*$" | |
1137 "Regular expression matching all types of phrase lines.") | |
1138 (defvar reftex-index-phrases-macro-data nil | |
1139 "Alist containing the information taken from the macro definition lines. | |
1140 This gets refreshed in every phrases command.") | |
1141 (defvar reftex-index-phrases-files nil | |
1142 "List of document files relevant for the phrases file.") | |
1143 | |
1144 (defvar reftex-index-phrases-font-lock-keywords nil | |
1145 "Font lock keywords for reftex-index-phrases-mode.") | |
1146 (defvar reftex-index-phrases-font-lock-defaults nil | |
1147 "Font lock defaults for reftex-index-phrases-mode.") | |
1148 (defvar reftex-index-phrases-map (make-sparse-keymap) | |
1149 "Keymap used for *toc* buffer.") | |
1150 | |
1151 | |
1152 (defun reftex-index-phrase-selection-or-word (arg) | |
1153 "Add current selection or word at point to the phrases buffer. | |
1154 When you are in transient-mark-mode and the region is active, the | |
1155 selection will be used - otherwise the word at point. | |
1156 You get a chance to edit the entry in the phrases buffer - finish with | |
1157 `C-c C-c'." | |
1158 (interactive "P") | |
1159 (set-marker reftex-index-return-marker (point)) | |
1160 (reftex-index-selection-or-word arg 'phrase) | |
1161 (if (eq major-mode 'reftex-index-phrases-mode) | |
1162 (message | |
1163 (substitute-command-keys | |
1164 "Return to LaTeX with \\[reftex-index-phrases-save-and-return]")))) | |
1165 | |
1166 (defun reftex-index-visit-phrases-buffer () | |
1167 "Switch to the phrases buffer, initialize if empty." | |
1168 (interactive) | |
1169 (reftex-access-scan-info) | |
1170 (let* ((master (reftex-TeX-master-file)) | |
1171 (name (concat (file-name-sans-extension master) ".rip"))) | |
1172 (find-file name) | |
1173 (unless (eq major-mode 'reftex-index-phrases-mode) | |
1174 (reftex-index-phrases-mode)) | |
1175 (if (= (buffer-size) 0) | |
1176 (reftex-index-initialize-phrases-buffer master)))) | |
1177 | |
1178 (defun reftex-index-initialize-phrases-buffer (&optional master) | |
1179 "Initialize the phrases buffer by creating the header. | |
1180 If the buffer is non-empty, delete the old header first." | |
1181 (interactive) | |
1182 (let* ((case-fold-search t) | |
1183 (default-key (car reftex-index-default-macro)) | |
1184 (default-macro (nth 1 (assoc default-key | |
1185 reftex-key-to-index-macro-alist))) | |
1186 (macro-alist | |
1187 (sort (copy-sequence reftex-index-macro-alist) | |
1188 (lambda (a b) (equal (car a) default-macro)))) | |
1189 macro entry key repeat) | |
1190 | |
1191 (if master (set (make-local-variable 'TeX-master) | |
1192 (file-name-nondirectory master))) | |
1193 | |
1194 (when (> (buffer-size) 0) | |
1195 (goto-char 1) | |
1196 (set-mark (point)) | |
1197 (while (re-search-forward reftex-index-phrases-macrodef-regexp nil t) | |
1198 (end-of-line)) | |
1199 (beginning-of-line 2) | |
1200 (if (looking-at reftex-index-phrases-comment-regexp) | |
1201 (beginning-of-line 2)) | |
1202 (while (looking-at "^[ \t]*$") | |
1203 (beginning-of-line 2)) | |
1204 (cond ((fboundp 'zmacs-activate-region) (zmacs-activate-region)) | |
1205 ((boundp 'make-active) (setq mark-active t))) | |
1206 (if (yes-or-no-p "Delete and rebuilt header ") | |
1207 (delete-region (point-min) (point)))) | |
1208 | |
1209 ;; Insert the mode line | |
1210 (insert | |
1211 (format "%% -*- mode: reftex-index-phrases; TeX-master: \"%s\" -*-\n" | |
1212 (file-name-nondirectory (reftex-index-phrase-tex-master)))) | |
1213 ;; Insert the macro definitions | |
1214 (insert "% Key Macro Format Repeat\n") | |
1215 (insert "%---------------------------------------------------------------------\n") | |
1216 (while (setq entry (pop macro-alist)) | |
1217 (setq macro (car entry) | |
1218 repeat (nth 7 entry) | |
1219 key (car (delq nil (mapcar (lambda (x) (if (equal (nth 1 x) macro) | |
1220 (car x) | |
1221 nil)) | |
1222 reftex-key-to-index-macro-alist)))) | |
1223 (insert (format ">>>INDEX_MACRO_DEFINITION:\t%s\t%-20s\t%s\n" | |
1224 (char-to-string key) (concat macro "{%s}") | |
1225 (if repeat "t" "nil")))) | |
1226 (insert "%---------------------------------------------------------------------\n\n\n"))) | |
1227 | |
1228 (defvar TeX-master) | |
1229 (defun reftex-index-phrase-tex-master (&optional dir) | |
1230 "Return the name of the master file associated with a phrase buffer." | |
1231 (if (and (boundp 'TeX-master) | |
1232 (local-variable-p 'TeX-master (current-buffer)) | |
1233 (stringp TeX-master)) | |
1234 ;; We have a local variable which tells us which file to use | |
1235 (expand-file-name TeX-master dir) | |
1236 ;; have to guess | |
1237 (concat (file-name-sans-extension (buffer-file-name)) ".tex"))) | |
1238 | |
1239 (defun reftex-index-phrases-save-and-return () | |
1240 "Return to where the `reftex-index-phrase-selection-or-word' was called." | |
1241 (interactive) | |
1242 (save-buffer) | |
1243 (switch-to-buffer (marker-buffer reftex-index-return-marker)) | |
1244 (goto-char (or (marker-position reftex-index-return-marker) (point)))) | |
1245 | |
1246 | |
1247 (defvar reftex-index-phrases-menu) | |
1248 (defvar reftex-index-phrases-restrict-file nil) | |
1249 ;;;###autoload | |
1250 (defun reftex-index-phrases-mode () | |
1251 "Major mode for managing the Index phrases of a LaTeX document. | |
1252 This buffer was created with RefTeX. | |
1253 | |
1254 To insert new phrases, use | |
1255 - `C-c \\' in the LaTeX document to copy selection or word | |
1256 - `\\[reftex-index-new-phrase]' in the phrases buffer. | |
1257 | |
1258 To index phrases use one of: | |
1259 | |
1260 \\[reftex-index-this-phrase] index current phrase | |
1261 \\[reftex-index-next-phrase] index next phrase (or N with prefix arg) | |
1262 \\[reftex-index-all-phrases] index all phrases | |
1263 \\[reftex-index-remaining-phrases] index current and following phrases | |
1264 \\[reftex-index-region-phrases] index the phrases in the region | |
1265 | |
1266 You can sort the phrases in this buffer with \\[reftex-index-sort-phrases]. | |
1267 To display information about the phrase at point, use \\[reftex-index-phrases-info]. | |
1268 | |
1269 For more information see the RefTeX User Manual. | |
1270 | |
1271 Here are all local bindings. | |
1272 | |
1273 \\{reftex-index-phrases-map}" | |
1274 (interactive) | |
1275 (kill-all-local-variables) | |
1276 (setq major-mode 'reftex-index-phrases-mode | |
1277 mode-name "Phrases") | |
1278 (use-local-map reftex-index-phrases-map) | |
1279 (set (make-local-variable 'font-lock-defaults) | |
1280 reftex-index-phrases-font-lock-defaults) | |
1281 (easy-menu-add reftex-index-phrases-menu reftex-index-phrases-map) | |
1282 (set (make-local-variable 'reftex-index-phrases-marker) (make-marker)) | |
1283 (run-hooks 'reftex-index-phrases-mode-hook)) | |
1284 (add-hook 'reftex-index-phrases-mode-hook 'turn-on-font-lock) | |
1285 | |
1286 ;; Font Locking stuff | |
1287 (let ((ss (if (featurep 'xemacs) 'secondary-selection ''secondary-selection))) | |
1288 (setq reftex-index-phrases-font-lock-keywords | |
1289 (list | |
1290 (cons reftex-index-phrases-comment-regexp 'font-lock-comment-face) | |
1291 (list reftex-index-phrases-macrodef-regexp | |
1292 '(1 font-lock-type-face) | |
1293 '(2 font-lock-keyword-face) | |
1294 (list 3 ss) | |
1295 '(4 font-lock-function-name-face) | |
1296 (list 5 ss) | |
1297 '(6 font-lock-string-face)) | |
1298 (list reftex-index-phrases-phrase-regexp1 | |
1299 '(1 font-lock-keyword-face) | |
1300 (list 2 ss) | |
1301 '(3 font-lock-string-face) | |
1302 (list 4 ss)) | |
1303 (list reftex-index-phrases-phrase-regexp2 | |
1304 '(1 font-lock-keyword-face) | |
1305 (list 2 ss) | |
1306 '(3 font-lock-string-face) | |
1307 (list 4 ss) | |
1308 '(5 font-lock-function-name-face)) | |
1309 (cons "^\t$" ss))) | |
1310 (setq reftex-index-phrases-font-lock-defaults | |
1311 '((reftex-index-phrases-font-lock-keywords) | |
1312 nil t nil beginning-of-line)) | |
1313 (put 'reftex-index-phrases-mode 'font-lock-defaults | |
1314 reftex-index-phrases-font-lock-defaults) ; XEmacs | |
1315 ) | |
1316 | |
1317 (defvar reftex-index-phrases-marker) | |
1318 (defun reftex-index-next-phrase (&optional arg) | |
1319 "Index the next ARG phrases in the phrases buffer." | |
1320 (interactive "p") | |
1321 (reftex-index-phrases-parse-header t) | |
1322 (while (> arg 0) | |
1323 (decf arg) | |
1324 (end-of-line) | |
1325 (if (re-search-forward reftex-index-phrases-phrase-regexp12 nil t) | |
1326 (progn | |
1327 (goto-char (match-beginning 0)) | |
1328 (reftex-index-this-phrase)) | |
1329 (error "No more phrase lines after point")))) | |
1330 | |
1331 (defun reftex-index-this-phrase () | |
1332 "Index the phrase in the current line. | |
1333 Does a global search and replace in the entire document. At each | |
1334 match, the user will be asked to confirm the replacement." | |
1335 (interactive) | |
1336 (if (interactive-p) (reftex-index-phrases-parse-header t)) | |
1337 (save-excursion | |
1338 (beginning-of-line) | |
1339 (cond ((looking-at reftex-index-phrases-comment-regexp) | |
1340 (if (interactive-p) (error "Comment line"))) | |
1341 ((looking-at "^[ \t]*$") | |
1342 (if (interactive-p) (error "Empty line"))) | |
1343 ((looking-at reftex-index-phrases-macrodef-regexp) | |
1344 (if (interactive-p) (error "Macro definition line"))) | |
1345 ((looking-at reftex-index-phrases-phrase-regexp12) | |
1346 ;; This is a phrase | |
1347 (let* ((char (if (not (equal (match-string 1) "")) | |
1348 (string-to-char (match-string 1)))) | |
1349 (phrase (match-string 3)) | |
1350 (index-key (match-string 6)) | |
1351 (macro-data (cdr (if (null char) | |
1352 (car reftex-index-phrases-macro-data) | |
1353 (assoc char reftex-index-phrases-macro-data)))) | |
1354 (macro-fmt (car macro-data)) | |
1355 (repeat (nth 1 macro-data)) | |
1356 (files | |
1357 (cond ((and (stringp reftex-index-phrases-restrict-file) | |
1358 (file-regular-p reftex-index-phrases-restrict-file)) | |
1359 (list reftex-index-phrases-restrict-file)) | |
1360 ((stringp reftex-index-phrases-restrict-file) | |
1361 (error "Illegal restriction file %s" | |
1362 reftex-index-phrases-restrict-file)) | |
1363 (t reftex-index-phrases-files))) | |
1364 (as-words reftex-index-phrases-search-whole-words)) | |
1365 (unless macro-data | |
1366 (error "No macro associated with key %c" char)) | |
1367 (unwind-protect | |
1368 (let ((overlay-arrow-string "=>") | |
1369 (overlay-arrow-position | |
1370 reftex-index-phrases-marker) | |
1371 (replace-count 0)) | |
1372 ;; Show the overlay arrow | |
1373 (move-marker reftex-index-phrases-marker | |
1374 (match-beginning 0) (current-buffer)) | |
1375 ;; Start the query-replace | |
1376 (reftex-query-index-phrase-globally | |
1377 files phrase macro-fmt | |
1378 index-key repeat as-words) | |
1379 (message "%s replaced" | |
1380 (reftex-number replace-count "occurrence")))))) | |
1381 (t (error "Cannot parse this line"))))) | |
1382 | |
1383 (defun reftex-index-all-phrases () | |
1384 "Index all phrases in the phrases buffer. | |
1385 Calls `reftex-index-this-phrase' on each line in the buffer." | |
1386 (interactive) | |
1387 (reftex-index-region-phrases (point-min) (point-max))) | |
1388 | |
1389 (defun reftex-index-remaining-phrases () | |
1390 "Index all phrases in the phrases buffer. | |
1391 Calls `reftex-index-this-phrase' on each line ay and below point in | |
1392 the buffer." | |
1393 (interactive) | |
1394 (beginning-of-line) | |
1395 (reftex-index-region-phrases (point) (point-max))) | |
1396 | |
1397 (defun reftex-index-region-phrases (beg end) | |
1398 "Index all phrases in the phrases buffer. | |
1399 Calls `reftex-index-this-phrase' on each line in the region." | |
1400 (interactive "r") | |
1401 (reftex-index-phrases-parse-header t) | |
1402 (goto-char beg) | |
1403 (while (not (or (eobp) | |
1404 (>= (point) end))) | |
1405 (save-excursion (reftex-index-this-phrase)) | |
1406 (beginning-of-line 2))) | |
1407 | |
1408 (defun reftex-index-phrases-parse-header (&optional get-files) | |
1409 "Parse the header of a phrases file to extract the macro definitions. | |
1410 The definitions get stored in `reftex-index-phrases-macro-data'. | |
1411 Also switches to the LaTeX document to find out which files belong to | |
1412 the document and stores the list in `reftex-index-phrases-files'." | |
1413 (let* ((master (reftex-index-phrase-tex-master)) | |
1414 buf) | |
1415 (if get-files | |
1416 ;; Get the file list | |
1417 (save-excursion | |
1418 (setq buf (reftex-get-file-buffer-force master)) | |
1419 (unless buf (error "Master file %s not found" master)) | |
1420 (set-buffer buf) | |
1421 (reftex-access-scan-info) | |
1422 (setq reftex-index-phrases-files | |
1423 (reftex-all-document-files)))) | |
1424 ;; Parse the files header for macro definitions | |
1425 (setq reftex-index-phrases-macro-data nil) | |
1426 (save-excursion | |
1427 (goto-char (point-min)) | |
1428 (while (re-search-forward reftex-index-phrases-macrodef-regexp nil t) | |
1429 (push (list | |
1430 (string-to-char (match-string 2)) | |
1431 (match-string 4) | |
1432 (equal (match-string 6) "t")) | |
1433 reftex-index-phrases-macro-data)) | |
1434 ;; Reverse the list, so that the first macro is first | |
1435 (if (null reftex-index-phrases-macro-data) | |
1436 (error "No valid MACRO DEFINITION line in .rip file (make sure to use TAB separators)")) | |
1437 (setq reftex-index-phrases-macro-data | |
1438 (nreverse reftex-index-phrases-macro-data)) | |
1439 (goto-char (point-min))))) | |
1440 | |
1441 (defun reftex-index-phrases-apply-to-region (beg end) | |
1442 "Index all index phrases in the current region. | |
1443 This works exactly like global indexing from the index phrases buffer, | |
1444 but operation is restricted to the current region. This is useful if | |
1445 you need to add/change text in an already indexed document and want to | |
1446 index the new part without having to go over the unchanged parts again." | |
1447 (interactive "r") | |
1448 (let ((win-conf (current-window-configuration)) | |
1449 (reftex-index-phrases-restrict-file (buffer-file-name))) | |
1450 (save-excursion | |
1451 (save-restriction | |
1452 (narrow-to-region beg end) | |
1453 (unwind-protect | |
1454 (progn | |
1455 ;; Hide the region highlighting | |
1456 (cond ((fboundp 'zmacs-deactivate-region) (zmacs-deactivate-region)) | |
1457 ((fboundp 'deactivate-mark) (deactivate-mark))) | |
1458 (delete-other-windows) | |
1459 (reftex-index-visit-phrases-buffer) | |
1460 (reftex-index-all-phrases)) | |
1461 (set-window-configuration win-conf)))))) | |
1462 | |
1463 (defun reftex-index-new-phrase (&optional text) | |
1464 "Open a new line in the phrases buffer, insert TEXT." | |
1465 (interactive) | |
1466 (if (and text (stringp text)) | |
1467 (progn | |
1468 ;; Check if the phrase is already in the buffer | |
1469 (setq text (reftex-index-simplify-phrase text)) | |
1470 (goto-char (point-min)) | |
1471 (if (re-search-forward | |
1472 (concat "^\\(\\S-*\\)\t\\(" (regexp-quote text) | |
1473 "\\) *[\t\n]") nil t) | |
1474 (progn | |
1475 (goto-char (match-end 2)) | |
1476 (error "Phrase is already in phrases buffer"))))) | |
1477 ;; Add the new phrase line after the last in the buffer | |
1478 (goto-char (point-max)) | |
1479 (if (re-search-backward reftex-index-phrases-phrase-regexp12 nil t) | |
1480 (end-of-line)) | |
1481 (if (not (bolp)) | |
1482 (insert "\n")) | |
1483 (insert "\t") | |
1484 (if (and text (stringp text)) | |
1485 (insert text))) | |
1486 | |
1487 (defun reftex-index-find-next-conflict-phrase (&optional arg) | |
1488 "Find the next a phrase which is has conflicts in the phrase buffer. | |
1489 The command helps to find possible conflicts in the phrase indexing process. | |
1490 It searches downward from point for a phrase which is repeated elsewhere | |
1491 in the buffer, or which is a subphrase of another phrase. If such a | |
1492 phrase is found, the phrase info is displayed. | |
1493 To check the whole buffer, start at the beginning and continue by calling | |
1494 this function repeatedly." | |
1495 (interactive "P") | |
1496 (if (catch 'exit | |
1497 (while (re-search-forward reftex-index-phrases-phrase-regexp12 nil t) | |
1498 (goto-char (match-beginning 3)) | |
1499 (let* ((phrase (match-string 3)) | |
1500 (case-fold-search reftex-index-phrases-case-fold-search) | |
1501 (re (reftex-index-phrases-find-dup-re phrase t))) | |
1502 (if (save-excursion | |
1503 (goto-char (point-min)) | |
1504 (and (re-search-forward re nil t) | |
1505 (re-search-forward re nil t))) | |
1506 (throw 'exit t))))) | |
1507 (progn | |
1508 (reftex-index-phrases-info) | |
1509 (message "Phrase with match conflict discovered")) | |
1510 (goto-char (point-max)) | |
1511 (error "No further problematic phrases found"))) | |
1512 | |
1513 (defun reftex-index-phrases-info () | |
1514 "Display information about the phrase at point." | |
1515 (interactive) | |
1516 (save-excursion | |
1517 (beginning-of-line) | |
1518 (unless (looking-at reftex-index-phrases-phrase-regexp12) | |
1519 (error "Not a phrase line")) | |
1520 (save-match-data (reftex-index-phrases-parse-header t)) | |
1521 (let* ((char (if (not (equal (match-string 1) "")) | |
1522 (string-to-char (match-string 1)))) | |
1523 (phrase (match-string 3)) | |
1524 (index-key (match-string 6)) | |
1525 (index-keys (split-string | |
1526 (or index-key phrase) | |
1527 reftex-index-phrases-logical-or-regexp)) | |
1528 (macro-data (cdr (if (null char) | |
1529 (car reftex-index-phrases-macro-data) | |
1530 (assoc char reftex-index-phrases-macro-data)))) | |
1531 (macro-fmt (car macro-data)) | |
1532 (repeat (nth 1 macro-data)) | |
1533 (as-words reftex-index-phrases-search-whole-words) | |
1534 (example (reftex-index-make-replace-string | |
1535 macro-fmt (downcase phrase) (car index-keys) repeat)) | |
1536 (re (reftex-index-make-phrase-regexp phrase as-words t)) | |
1537 (re1 (reftex-index-phrases-find-dup-re phrase)) | |
1538 (re2 (reftex-index-phrases-find-dup-re phrase 'sub)) | |
1539 superphrases | |
1540 (nmatches 0) | |
1541 (ntimes1 0) | |
1542 (ntimes2 0) | |
1543 (case-fold-search reftex-index-phrases-case-fold-search) | |
1544 file files buf) | |
1545 (setq files reftex-index-phrases-files) | |
1546 (save-excursion | |
1547 (save-restriction | |
1548 (widen) | |
1549 (goto-char (point-min)) | |
1550 (while (re-search-forward re1 nil t) | |
1551 (incf ntimes1)) | |
1552 (goto-char (point-min)) | |
1553 (while (re-search-forward re2 nil t) | |
1554 (push (cons (count-lines 1 (point)) (match-string 1)) superphrases) | |
1555 (incf ntimes2)))) | |
1556 (save-excursion | |
1557 (while (setq file (pop files)) | |
1558 (setq buf (reftex-get-file-buffer-force file)) | |
1559 (when buf | |
1560 (set-buffer buf) | |
1561 (save-excursion | |
1562 (save-restriction | |
1563 (widen) | |
1564 (goto-char (point-min)) | |
1565 (let ((case-fold-search reftex-index-phrases-case-fold-search)) | |
1566 (while (re-search-forward re nil t) | |
1567 (or (reftex-in-comment) | |
1568 (incf nmatches))))))))) | |
1569 (with-output-to-temp-buffer "*Help*" | |
1570 (princ (format " Phrase: %s\n" phrase)) | |
1571 (princ (format " Macro key: %s\n" char)) | |
1572 (princ (format " Macro format: %s\n" macro-fmt)) | |
1573 (princ (format " Repeat: %s\n" repeat)) | |
1574 (cond | |
1575 (index-key | |
1576 (let ((iks index-keys) (cnt 0) ik) | |
1577 (while (setq ik (pop iks)) | |
1578 (princ (format "Index entry %d: %s\n" (incf cnt) ik))))) | |
1579 (repeat | |
1580 (princ (format " Index entry: %s\n" phrase))) | |
1581 (t | |
1582 (princ (format " Index key: <<Given by the match>>\n")))) | |
1583 (princ (format " Example: %s\n" example)) | |
1584 (terpri) | |
1585 (princ (format "Total matches: %s in %s\n" | |
1586 (reftex-number nmatches "match" "es") | |
1587 (reftex-number (length reftex-index-phrases-files) | |
1588 "LaTeX file"))) | |
1589 (princ (format " Uniqueness: Phrase occurs %s in phrase buffer\n" | |
1590 (reftex-number ntimes1 "time"))) | |
1591 (if (> ntimes2 1) | |
1592 (progn | |
1593 (princ (format " Superphrases: Phrase matches the following %s in the phrase buffer:\n" | |
1594 (reftex-number ntimes2 "line"))) | |
1595 (mapcar (lambda(x) | |
1596 (princ (format " Line %4d: %s\n" (car x) (cdr x)))) | |
1597 (nreverse superphrases)))))))) | |
1598 | |
1599 (defun reftex-index-phrases-set-macro-key () | |
1600 "Change the macro key for the current line. | |
1601 Prompts for a macro key and insert is at the beginning of the line. | |
1602 If you reply with SPACE, the macro keyn will be removed, so that the | |
1603 default macro will be used. If you reply with `RET', just prints | |
1604 information about the currently selected macro." | |
1605 (interactive) | |
1606 (reftex-index-phrases-parse-header) | |
1607 (save-excursion | |
1608 (beginning-of-line) | |
1609 (unless (or (looking-at reftex-index-phrases-phrase-regexp12) | |
1610 (looking-at "\t")) | |
1611 (error "This is not a phrase line")) | |
1612 (let* ((nc (reftex-index-select-phrases-macro 0)) | |
1613 (macro-data (assoc nc reftex-index-phrases-macro-data)) | |
1614 macro-fmt repeat) | |
1615 (cond (macro-data) | |
1616 ((equal nc ?\ ) | |
1617 (setq nc "" | |
1618 macro-data (car reftex-index-phrases-macro-data))) | |
1619 ((equal nc ?\C-m) | |
1620 (setq nc (char-after (point))) | |
1621 (if (equal nc ?\t) | |
1622 (setq nc "" | |
1623 macro-data (car reftex-index-phrases-macro-data)) | |
1624 (setq macro-data (assoc nc reftex-index-phrases-macro-data)))) | |
1625 (t (error "No macro associated with %c" nc))) | |
1626 | |
1627 (setq macro-fmt (nth 1 macro-data) | |
1628 repeat (nth 2 macro-data)) | |
1629 (if macro-data | |
1630 (progn | |
1631 (if (looking-at "[^\t]") (delete-char 1)) | |
1632 (insert nc) | |
1633 (message "Line will use %s %s repeat" macro-fmt | |
1634 (if repeat "with" "without"))) | |
1635 (error "Abort"))))) | |
1636 | |
1637 (defun reftex-index-sort-phrases (&optional chars-first) | |
1638 "Sort the phrases lines in the buffer alphabetically. | |
1639 Normally, this looks only at the phrases. With a prefix arg CHARS-FIRST, | |
1640 it first compares the macro identifying chars and then the phrases." | |
1641 (interactive "P") | |
1642 ;; Remember the current line, so that we can return | |
1643 (let ((line (buffer-substring (progn (beginning-of-line) (point)) | |
1644 (progn (end-of-line) (point)))) | |
1645 beg end) | |
1646 (goto-char (point-min)) | |
1647 ;; Find first and last phrase line in buffer | |
1648 (setq beg | |
1649 (and (re-search-forward reftex-index-phrases-phrase-regexp12 nil t) | |
1650 (match-beginning 0))) | |
1651 (goto-char (point-max)) | |
1652 (setq end (re-search-backward reftex-index-phrases-phrase-regexp12 nil t)) | |
1653 (if end (setq end (progn (goto-char end) (end-of-line) (point)))) | |
1654 ;; Take the lines, sort them and re-insert. | |
1655 (if (and beg end) | |
1656 (progn | |
1657 (message "Sorting lines...") | |
1658 (let* ((lines (split-string (buffer-substring beg end) "\n")) | |
1659 (lines1 (sort lines 'reftex-compare-phrase-lines))) | |
1660 (message "Sorting lines...done") | |
1661 (let ((inhibit-quit t)) ;; make sure we do not loose lines | |
1662 (delete-region beg end) | |
1663 (insert (mapconcat 'identity lines1 "\n")))) | |
1664 (goto-char (point-max)) | |
1665 (re-search-backward (concat "^" (regexp-quote line) "$") nil t)) | |
1666 (error "Cannot find phrases lines to sort")))) | |
1667 | |
1668 (defvar chars-first) | |
1669 (defun reftex-compare-phrase-lines (a b) | |
1670 "The comparison function used for sorting." | |
1671 (let (ca cb pa pb c-p p-p) | |
1672 (if (string-match reftex-index-phrases-phrase-regexp12 a) | |
1673 (progn | |
1674 ;; Extract macro char and phrase-or-key for a | |
1675 (setq ca (match-string 1 a) | |
1676 pa (downcase | |
1677 (or (and reftex-index-phrases-sort-prefers-entry | |
1678 (match-string 6 a)) | |
1679 (match-string 3 a)))) | |
1680 (if (string-match reftex-index-phrases-phrase-regexp12 b) | |
1681 (progn | |
1682 ;; Extract macro char and phrase-or-key for b | |
1683 (setq cb (match-string 1 b) | |
1684 pb (downcase | |
1685 (or (and reftex-index-phrases-sort-prefers-entry | |
1686 (match-string 6 b)) | |
1687 (match-string 3 b)))) | |
1688 (setq c-p (string< ca cb) | |
1689 p-p (string< pa pb)) | |
1690 ;; Do the right comparison, based on the value of `chars-first' | |
1691 ;; `chars-first' is bound locally in the calling function | |
1692 (if chars-first | |
1693 (if (string= ca cb) p-p c-p) | |
1694 (if (string= pa pb) c-p p-p))))) | |
1695 ;; If line a does not match, the answer we return determines | |
1696 ;; if non-matching lines are collected at the beginning. | |
1697 ;; When we return t here, non-matching lines form | |
1698 ;; block separators for searches. | |
1699 (not reftex-index-phrases-sort-in-blocks)))) | |
1700 | |
1701 (defvar reftex-index-phrases-menu) | |
1702 (defun reftex-index-make-phrase-regexp (phrase &optional | |
1703 as-words allow-newline) | |
1704 "Return a regexp matching PHRASE, even if distributed over lines. | |
1705 With optional arg AS-WORDS, require word boundary at beginning and end. | |
1706 With optional arg ALLOW-NEWLINE, allow single newline between words." | |
1707 (let* ((words (split-string phrase)) | |
1708 (space-re (if allow-newline | |
1709 "\\([ \t]*\\(\n[ \t]*\\)?\\|[ \t]\\)" | |
1710 "\\([ \t]+\\)"))) | |
1711 (concat (if (and as-words (string-match "\\`\\w" (car words))) | |
1712 "\\<" "") | |
1713 (mapconcat (lambda (w) (regexp-quote (downcase w))) | |
1714 words space-re) | |
1715 (if (and as-words | |
1716 (string-match "\\w\\'" (nth (1- (length words)) words))) | |
1717 "\\>" "")))) | |
1718 | |
1719 (defun reftex-index-simplify-phrase (phrase) | |
1720 "Make phrase single spaces and single line." | |
1721 (mapconcat 'identity (split-string phrase) " ")) | |
1722 | |
1723 (defun reftex-index-phrases-find-dup-re (phrase &optional sub) | |
1724 "Return a regexp which matches variations of PHRASE (with additional space). | |
1725 When SUB ins non-nil, the regexp will also match when PHRASE is a subphrase | |
1726 of another phrase. The regexp works lonly in the phrase buffer." | |
1727 (concat (if sub "^\\S-?\t\\([^\t\n]*" "^\\S-?\t") | |
1728 (mapconcat 'regexp-quote (split-string phrase) " +") | |
1729 (if sub "[^\t\n]*\\)\\([\t\n]\\|$\\)" " *\\([\t\n]\\|$\\)"))) | |
1730 | |
1731 (defun reftex-index-make-replace-string (macro-fmt match index-key | |
1732 &optional repeat mathp) | |
1733 "Return the string which can be used as replacement. | |
1734 Treats the logical `and' for index phrases." | |
1735 (let ((index-keys (split-string (or index-key match) | |
1736 reftex-index-phrases-logical-and-regexp))) | |
1737 (concat | |
1738 (mapconcat (lambda (x) | |
1739 (format macro-fmt | |
1740 (format (if mathp reftex-index-math-format "%s") x))) | |
1741 index-keys "") | |
1742 (if repeat (reftex-index-simplify-phrase match) "")))) | |
1743 | |
1744 (defun reftex-query-index-phrase-globally (files &rest args) | |
1745 "Call `reftex-query-index-phrase' for all files in FILES." | |
1746 (let ((win-conf (current-window-configuration)) | |
1747 (file)) | |
1748 (unless files (error "No files")) | |
1749 (unwind-protect | |
1750 (progn | |
1751 (switch-to-buffer-other-window (reftex-get-file-buffer-force | |
1752 (car files))) | |
1753 (catch 'no-more-files | |
1754 (while (setq file (pop files)) | |
1755 (switch-to-buffer (reftex-get-file-buffer-force file)) | |
1756 (save-excursion | |
1757 (save-restriction | |
1758 (unless (stringp reftex-index-phrases-restrict-file) | |
1759 (widen)) | |
1760 (goto-char (point-min)) | |
1761 (apply 'reftex-query-index-phrase args)))))) | |
1762 (reftex-unhighlight 0) | |
1763 (set-window-configuration win-conf)))) | |
1764 | |
1765 (defconst reftex-index-phrases-help | |
1766 " Keys for query-index search | |
1767 =========================== | |
1768 y Replace this match | |
1769 n Skip this match | |
1770 ! Replace this and all further matches in this file | |
1771 q / Q Skip match, start next file / start next phrase | |
1772 o Use a different indexing macro for this match | |
1773 1 - 9 Select one of the multiple phrases | |
1774 e Edit the replacement text | |
1775 C-r Recursive edit. | |
1776 s / S Save this buffer / Save all document buffers | |
1777 C-g Abort" | |
1778 "The help string for indexing phrases.") | |
1779 | |
1780 (defvar replace-count) | |
1781 (defun reftex-query-index-phrase (phrase macro-fmt &optional | |
1782 index-key repeat as-words) | |
1783 "Search through buffer for PHRASE, and offer to replace it with an indexed | |
1784 version. The index version is derived by applying `format' with MACRO-FMT | |
1785 to INDEX-KEY or PHRASE. When REPEAT is non-nil, the PHRASE is inserted | |
1786 again after the macro. | |
1787 AS-WORDS means, the search for PHRASE should require word boundaries at | |
1788 both ends." | |
1789 (let* ((re (reftex-index-make-phrase-regexp phrase as-words 'allow-newline)) | |
1790 (case-fold-search reftex-index-phrases-case-fold-search) | |
1791 (index-keys (split-string | |
1792 (or index-key phrase) | |
1793 reftex-index-phrases-logical-or-regexp)) | |
1794 (nkeys (length index-keys)) | |
1795 (ckey (nth 0 index-keys)) | |
1796 (all-yes nil) | |
1797 match rpl char beg end mathp) | |
1798 (unwind-protect | |
1799 (while (re-search-forward re nil t) | |
1800 (catch 'next-match | |
1801 (setq match (match-string 0)) | |
1802 (setq mathp | |
1803 (save-match-data | |
1804 (condition-case nil (texmathp) (error nil)))) | |
1805 (setq beg (car (match-data)) | |
1806 end (nth 1 (match-data))) | |
1807 (if (and reftex-index-phrases-skip-indexed-matches | |
1808 (save-match-data | |
1809 (reftex-index-phrase-match-is-indexed beg | |
1810 end))) | |
1811 (throw 'next-match nil)) | |
1812 (reftex-highlight 0 (match-beginning 0) (match-end 0)) | |
1813 (setq rpl | |
1814 (save-match-data | |
1815 (reftex-index-make-replace-string | |
1816 macro-fmt (match-string 0) ckey repeat mathp))) | |
1817 (while | |
1818 (not | |
1819 (catch 'loop | |
1820 (message "REPLACE: %s? (yn!qoe%s?)" | |
1821 rpl | |
1822 (if (> nkeys 1) | |
1823 (concat "1-" (int-to-string nkeys)) | |
1824 "")) | |
1825 (setq char (if all-yes ?y (read-char-exclusive))) | |
1826 (cond ((member char '(?y ?Y ?\ )) | |
1827 ;; Yes! | |
1828 (replace-match rpl t t) | |
1829 (incf replace-count) | |
1830 ;; See if we should insert newlines to shorten lines | |
1831 (and reftex-index-phrases-wrap-long-lines | |
1832 (reftex-index-phrases-fixup-line beg end)) | |
1833 (throw 'loop t)) | |
1834 ((member char '(?n ?N ?\C-h ?\C-?));; FIXME: DEL | |
1835 ;; No | |
1836 (throw 'loop t)) | |
1837 ((equal char ?!) | |
1838 ;; Yes for all in this buffer | |
1839 (setq all-yes t)) | |
1840 ((equal char ?q) | |
1841 ;; Stop this one in this file | |
1842 (goto-char (point-max)) | |
1843 (throw 'loop t)) | |
1844 ((equal char ?Q) | |
1845 ;; Stop this one | |
1846 (throw 'no-more-files t)) | |
1847 ((equal char ?s) | |
1848 (save-buffer)) | |
1849 ((equal char ?S) | |
1850 (reftex-save-all-document-buffers)) | |
1851 ((equal char ?\C-g) | |
1852 (keyboard-quit)) | |
1853 ((member char '(?o ?O)) | |
1854 ;; Select a differnt macro | |
1855 (let* ((nc (reftex-index-select-phrases-macro 2)) | |
1856 (macro-data | |
1857 (cdr (assoc nc reftex-index-phrases-macro-data))) | |
1858 (macro-fmt (car macro-data)) | |
1859 (repeat (nth 1 macro-data))) | |
1860 (if macro-data | |
1861 (setq rpl (save-match-data | |
1862 (reftex-index-make-replace-string | |
1863 macro-fmt match | |
1864 ckey repeat mathp))) | |
1865 (ding)))) | |
1866 ((equal char ?\?) | |
1867 ;; Help | |
1868 (with-output-to-temp-buffer "*Help*" | |
1869 (princ reftex-index-phrases-help))) | |
1870 ((equal char ?\C-r) | |
1871 ;; Recursive edit | |
1872 (save-match-data | |
1873 (save-excursion | |
1874 (message | |
1875 (substitute-command-keys | |
1876 "Recursive edit. Resume with \\[exit-recursive-edit]")) | |
1877 (recursive-edit)))) | |
1878 ((equal char ?e) | |
1879 (setq rpl (read-string "Edit: " rpl))) | |
1880 ((equal char ?0) | |
1881 (setq ckey (or index-key phrase) | |
1882 rpl (save-match-data | |
1883 (reftex-index-make-replace-string | |
1884 macro-fmt match ckey repeat mathp)))) | |
1885 ((and (> char ?0) | |
1886 (<= char (+ ?0 nkeys))) | |
1887 (setq ckey (nth (1- (- char ?0)) index-keys) | |
1888 rpl (save-match-data | |
1889 (reftex-index-make-replace-string | |
1890 macro-fmt match ckey repeat mathp)))) | |
1891 (t (ding))) | |
1892 nil))))) | |
1893 (message "") | |
1894 (setq all-yes nil) | |
1895 (reftex-unhighlight 0)))) | |
1896 | |
1897 (defun reftex-index-phrase-match-is-indexed (beg end) | |
1898 (save-excursion | |
1899 (goto-char end) | |
1900 (let* ((this-macro (car (reftex-what-macro 1))) | |
1901 (before-char (char-before beg)) | |
1902 (after-char (char-after end)) | |
1903 (before-macro | |
1904 (and (> beg 2) | |
1905 (goto-char (1- beg)) | |
1906 (memq (char-after (point)) '(?\] ?\})) | |
1907 (car (reftex-what-macro 1)))) | |
1908 (after-macro | |
1909 (and (goto-char end) | |
1910 (looking-at "\\(\\\\[a-zA-Z]+\\*?\\)[[{]") | |
1911 (match-string 1)))) | |
1912 (or (and this-macro | |
1913 (member before-char '(?\{ ?\[)) | |
1914 (member after-char '(?\} ?\])) | |
1915 (member this-macro reftex-macros-with-index)) | |
1916 (and before-macro | |
1917 (member before-macro reftex-macros-with-index)) | |
1918 (and after-macro | |
1919 (member after-macro reftex-macros-with-index)))))) | |
1920 | |
1921 | |
1922 (defun reftex-index-phrases-fixup-line (beg end) | |
1923 "Insert newlines before BEG and/or after END to shorten line." | |
1924 (let (bol eol space1 space2) | |
1925 (save-excursion | |
1926 ;; Find line boundaries and possible line breaks near BEG and END | |
1927 (beginning-of-line) | |
1928 (setq bol (point)) | |
1929 (end-of-line) | |
1930 (setq eol (point)) | |
1931 (goto-char beg) | |
1932 (skip-chars-backward "^ \n") | |
1933 (if (and (equal (preceding-char) ?\ ) | |
1934 (string-match "\\S-" (buffer-substring bol (point)))) | |
1935 (setq space1 (1- (point)))) | |
1936 (goto-char end) | |
1937 (skip-chars-forward "^ \n") | |
1938 (if (and (equal (following-char) ?\ ) | |
1939 (string-match "\\S-" (buffer-substring (point) eol))) | |
1940 (setq space2 (point))) | |
1941 ;; Now check what we have and insert the newlines | |
1942 (if (<= (- eol bol) fill-column) | |
1943 ;; Line is already short | |
1944 nil | |
1945 (cond | |
1946 ((and (not space1) (not space2))) ; No spaces available | |
1947 ((not space2) ; Do space1 | |
1948 (reftex-index-phrases-replace-space space1)) | |
1949 ((not space1) ; Do space2 | |
1950 (reftex-index-phrases-replace-space space2)) | |
1951 (t ; We have both spaces | |
1952 (let ((l1 (- space1 bol)) | |
1953 (l2 (- space2 space1)) | |
1954 (l3 (- eol space2))) | |
1955 (if (> l2 fill-column) | |
1956 ;; The central part alone is more than one line | |
1957 (progn | |
1958 (reftex-index-phrases-replace-space space1) | |
1959 (reftex-index-phrases-replace-space space2)) | |
1960 (if (> (+ l1 l2) fill-column) | |
1961 ;; Need to split beginning | |
1962 (reftex-index-phrases-replace-space space1)) | |
1963 (if (> (+ l2 l3) fill-column) | |
1964 ;; Need to split end | |
1965 (reftex-index-phrases-replace-space space2)))))))))) | |
1966 | |
1967 (defun reftex-index-phrases-replace-space (pos) | |
1968 "If there is a space at POS, replace it with a newline char. | |
1969 Does not do a save-excursion." | |
1970 (when (equal (char-after pos) ?\ ) | |
1971 (goto-char pos) | |
1972 (delete-char 1) | |
1973 (insert "\n"))) | |
1974 | |
1975 (defun reftex-index-select-phrases-macro (&optional delay) | |
1976 "Offer a list of possible index macros and have the user select one." | |
1977 (let* ((prompt (concat "Select macro: [" | |
1978 (mapconcat (lambda (x) (char-to-string (car x))) | |
1979 reftex-index-phrases-macro-data "") | |
1980 "] ")) | |
1981 (help (concat "Select an indexing macro\n========================\n" | |
1982 (mapconcat (lambda (x) | |
1983 (format " [%c] %s" | |
1984 (car x) (nth 1 x))) | |
1985 reftex-index-phrases-macro-data "\n")))) | |
1986 (reftex-select-with-char prompt help delay))) | |
1987 | |
1988 ;; Keybindings and Menu for phrases buffer | |
1989 | |
1990 (loop for x in | |
1991 '(("\C-c\C-c" . reftex-index-phrases-save-and-return) | |
1992 ("\C-c\C-x" . reftex-index-this-phrase) | |
1993 ("\C-c\C-f" . reftex-index-next-phrase) | |
1994 ("\C-c\C-r" . reftex-index-region-phrases) | |
1995 ("\C-c\C-a" . reftex-index-all-phrases) | |
1996 ("\C-c\C-d" . reftex-index-remaining-phrases) | |
1997 ("\C-c\C-s" . reftex-index-sort-phrases) | |
1998 ("\C-c\C-n" . reftex-index-new-phrase) | |
1999 ("\C-c\C-m" . reftex-index-phrases-set-macro-key) | |
2000 ("\C-c\C-i" . reftex-index-phrases-info) | |
2001 ("\C-c\C-t" . reftex-index-find-next-conflict-phrase) | |
2002 ("\C-i" . self-insert-command)) | |
2003 do (define-key reftex-index-phrases-map (car x) (cdr x))) | |
2004 | |
2005 (easy-menu-define | |
2006 reftex-index-phrases-menu reftex-index-phrases-map | |
2007 "Menu for Phrases buffer" | |
2008 '("Phrases" | |
2009 ["New Phrase" reftex-index-new-phrase t] | |
2010 ["Set Phrase Macro" reftex-index-phrases-set-macro-key t] | |
2011 ["Recreate File Header" reftex-index-initialize-phrases-buffer t] | |
2012 "--" | |
2013 ("Sort Phrases" | |
2014 ["Sort" reftex-index-sort-phrases t] | |
2015 "--" | |
2016 "Sort Options" | |
2017 ["by Search Phrase" (setq reftex-index-phrases-sort-prefers-entry nil) | |
2018 :style radio :selected (not reftex-index-phrases-sort-prefers-entry)] | |
2019 ["by Index Entry" (setq reftex-index-phrases-sort-prefers-entry t) | |
2020 :style radio :selected reftex-index-phrases-sort-prefers-entry] | |
2021 ["in Blocks" (setq reftex-index-phrases-sort-in-blocks | |
2022 (not reftex-index-phrases-sort-in-blocks)) | |
2023 :style toggle :selected reftex-index-phrases-sort-in-blocks]) | |
2024 ["Describe Phrase" reftex-index-phrases-info t] | |
2025 ["Next Phrase Conflict" reftex-index-find-next-conflict-phrase t] | |
2026 "--" | |
2027 ("Find and Index in Document" | |
2028 ["Current Phrase" reftex-index-this-phrase t] | |
2029 ["Next Phrase" reftex-index-next-phrase t] | |
2030 ["Current and Following" reftex-index-remaining-phrases t] | |
2031 ["Region Phrases" reftex-index-region-phrases t] | |
2032 ["All Phrases" reftex-index-all-phrases t] | |
2033 "--" | |
2034 "Options" | |
2035 ["Match Whole Words" (setq reftex-index-phrases-search-whole-words | |
2036 (not reftex-index-phrases-search-whole-words)) | |
2037 :style toggle :selected reftex-index-phrases-search-whole-words] | |
2038 ["Case Sensitive Search" (setq reftex-index-phrases-case-fold-search | |
2039 (not reftex-index-phrases-case-fold-search)) | |
2040 :style toggle :selected (not | |
2041 reftex-index-phrases-case-fold-search)] | |
2042 ["Wrap Long Lines" (setq reftex-index-phrases-wrap-long-lines | |
2043 (not reftex-index-phrases-wrap-long-lines)) | |
2044 :style toggle :selected reftex-index-phrases-wrap-long-lines] | |
2045 ["Skip Indexed Matches" (setq reftex-index-phrases-skip-indexed-matches | |
2046 (not reftex-index-phrases-skip-indexed-matches)) | |
2047 :style toggle :selected reftex-index-phrases-skip-indexed-matches]) | |
2048 "--" | |
2049 ["Save and Return" reftex-index-phrases-save-and-return t])) | |
2050 | |
2051 | |
1220 ;;; reftex-index.el ends here | 2052 ;;; reftex-index.el ends here |