comparison lisp/mh-e/mh-search.el @ 68192:2cfa649fa39d

* mh-customize.el (mh-index): Rename group to mh-search and sort group definition and options accordingly. (mh-index-program): Rename to mh-search-program. (mh-kill-folder-suppress-prompt-hooks): Rename mh-index-p to mh-search-p. (mh-search-mode-hook): Change group from mh-index to mh-search. (mh-index-folder): Rename to mh-search-folder. Change group from mh-index to mh-search. * mh-e.el (mh-folder-font-lock-keywords): Rename mh-index-folder to mh-search-folder. * mh-search.el (mh-indexer) Rename to mh-searcher. The commands pick and grep are searchers too but aren't indexed. (mh-index-execute-search-function): Rename to mh-search-function. (mh-index-next-result-function): Rename to mh-search-next-result-function. (mh-index-regexp-builder): Rename to mh-search-regexp-builder. (mh-search): Since redo-search-flag defaults to nil and is of lesser importance, make it an optional argument and place it after the folder and search-regexp arguments. Sync docstring with manual. (mh-search-mode-map): Autoload so that keys are shown in help even before mh-search is loaded. (mh-search-mode): Sync docstring with manual. (mh-index-do-search): Rename argument indexer to searcher. Sync docstring with manual. (mh-pick-do-search): Sync docstring with manual. (mh-index-p): Rename to mh-search-p. (mh-indexer-choices): Rename to mh-search-choices. (mh-index-choose): Rename to mh-search-choose. Rename argument indexer to searcher. (mh-swish++-execute-search, mh-swish-execute-search) (mh-mairix-execute-search, mh-namazu-execute-search): Drop "and read the results" from docstring since these functions don't. (mh-pick-execute-search, mh-grep-execute-search): Sync docstring with manual. (mh-index-generate-pretty-name): Prune -search from string so that folder names for pick searches are the same as those of other searches.
author Bill Wohler <wohler@newt.com>
date Sat, 14 Jan 2006 21:17:37 +0000
parents dcf226991252
children 5012e59a73c7
comparison
equal deleted inserted replaced
68191:80bda70f9d68 68192:2cfa649fa39d
1 ;;; mh-search -- MH-E search 1 ;;; mh-search --- MH-E search
2 2
3 ;; Copyright (C) 1993, 1995, 3 ;; Copyright (C) 1993, 1995,
4 ;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4 ;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
5 5
6 ;; Author: Indexed search by Satyaki Das <satyaki@theforce.stanford.edu> 6 ;; Author: Indexed search by Satyaki Das <satyaki@theforce.stanford.edu>
36 ;; grep 36 ;; grep
37 ;; 37 ;;
38 ;; (2) To use this package, you first have to build an index. Please 38 ;; (2) To use this package, you first have to build an index. Please
39 ;; read the documentation for `mh-search' to get started. That 39 ;; read the documentation for `mh-search' to get started. That
40 ;; documentation will direct you to the specific instructions for 40 ;; documentation will direct you to the specific instructions for
41 ;; your particular indexer. 41 ;; your particular searcher.
42 42
43 ;;; Change Log: 43 ;;; Change Log:
44 44
45 ;;; Code: 45 ;;; Code:
46 46
49 49
50 (require 'gnus-util) 50 (require 'gnus-util)
51 (require 'mh-buffers) 51 (require 'mh-buffers)
52 (require 'mh-e) 52 (require 'mh-e)
53 53
54 (defvar mh-indexer nil 54 (defvar mh-searcher nil
55 "Cached value of chosen index program.") 55 "Cached value of chosen search program.")
56 56
57 (defvar mh-index-execute-search-function nil 57 (defvar mh-search-function nil
58 "Function which executes the search program.") 58 "Function which executes the search program.")
59 59
60 (defvar mh-index-next-result-function nil 60 (defvar mh-search-next-result-function nil
61 "Function to parse the next line of output. 61 "Function to parse the next line of output.
62 Expected to return a list of three strings: name of the folder, 62 Expected to return a list of three strings: name of the folder,
63 message number, and optionally the match.") 63 message number, and optionally the match.")
64 64
65 (defvar mh-index-regexp-builder nil 65 (defvar mh-search-regexp-builder nil
66 "Function used to construct search regexp.") 66 "Function used to construct search regexp.")
67 67
68 (defvar mh-index-folder "+mhe-index" 68 (defvar mh-index-folder "+mhe-index"
69 "Folder that contains the folders resulting from the index searches.") 69 "Folder that contains the folders resulting from the index searches.")
70 70
78 78
79 79
80 ;;; MH-Search mode 80 ;;; MH-Search mode
81 81
82 ;;;###mh-autoload 82 ;;;###mh-autoload
83 (defun* mh-search (redo-search-flag folder search-regexp 83 (defun* mh-search (folder search-regexp
84 &optional window-config) 84 &optional redo-search-flag window-config)
85 "Search your MH mail. 85 "Search your MH mail.
86 86
87 With this command, you can search for messages to or from a 87 This command helps you find messages in your entire corpus of
88 particular person or about a particular subject. In fact, you can 88 mail. You can search for messages to or from a particular person
89 also search for messages containing selected strings in any 89 or about a particular subject. In fact, you can also search for
90 arbitrary header field or any string found within the messages. 90 messages containing selected strings in any arbitrary header
91 91 field or any string found within the messages.
92 Use a prefix argument REDO-SEARCH-FLAG to repeat the last search. 92
93 Out of the box, MH-E uses \"pick\" to find messages. With a
94 little extra effort, you can set an indexing program which
95 rewards you with extremely quick results. The drawback is that
96 sometimes the index does not contain the words you're looking
97 for. You can still use \"pick\" in these situations.
93 98
94 You are prompted for the FOLDER to search. This can be \"all\" to 99 You are prompted for the FOLDER to search. This can be \"all\" to
95 search all folders. For most search methods, the search works 100 search all folders. Note that the search works recursively on the
96 recursively on the listed folder. 101 listed folder.
97 102
98 Next, an MH-Search buffer appears where you can enter search 103 Next, an MH-Search buffer appears where you can enter search
99 criteria. 104 criteria SEARCH-REGEXP.
100 105
101 From: 106 From:
102 To: 107 To:
103 Cc: 108 Cc:
104 Date: 109 Date:
109 appropriate header field that is already there, or create a new 114 appropriate header field that is already there, or create a new
110 field yourself. If the string you're looking for could be 115 field yourself. If the string you're looking for could be
111 anywhere in a message, then place the string underneath the row 116 anywhere in a message, then place the string underneath the row
112 of dashes. 117 of dashes.
113 118
114 It is all right to specify several search criteria. What happens
115 then is that a logical _and_ of the various fields is performed.
116 If you prefer a logical _or_ operation, run \\[mh-search]
117 multiple times.
118
119 As an example, let's say that we want to find messages from 119 As an example, let's say that we want to find messages from
120 Ginnean about horseback riding in the Kosciusko National 120 Ginnean about horseback riding in the Kosciusko National
121 Park (Australia) during January, 1994. Normally we would start 121 Park (Australia) during January, 1994. Normally we would start
122 with a broad search and narrow it down if necessary to produce a 122 with a broad search and narrow it down if necessary to produce a
123 manageable amount of data, but we'll cut to the chase and create 123 manageable amount of data, but we'll cut to the chase and create
124 a fairly restrictive set of criteria as follows: 124 a fairly restrictive set of criteria as follows:\\<mh-search-mode-map>
125 125
126 From: ginnean 126 From: ginnean
127 To: 127 To:
128 Cc: 128 Cc:
129 Date: Jan 1994 129 Date: Jan 1994
131 -------- 131 --------
132 horse 132 horse
133 kosciusko 133 kosciusko
134 134
135 As with MH-Letter mode, MH-Search provides commands like 135 As with MH-Letter mode, MH-Search provides commands like
136 \\<mh-search-mode-map>\\[mh-to-field] to help you fill in the 136 \\[mh-to-field] to help you fill in the blanks.\\<mh-folder-mode-map>
137 blanks.
138 137
139 If you find that you do the same thing over and over when editing 138 If you find that you do the same thing over and over when editing
140 the search template, you may wish to bind some shortcuts to keys. 139 the search template, you may wish to bind some shortcuts to keys.
141 This can be done with the variable `mh-search-mode-hook', which is 140 This can be done with the variable `mh-search-mode-hook', which is
142 called when \\[mh-search] is run on a new pattern. 141 called when \\[mh-search] is run on a new pattern.\\<mh-search-mode-map>
143 142
144 To perform the search, type \\[mh-index-do-search]. 143 To perform the search, type \\[mh-index-do-search].
145 144
146 Sometimes you're searching for text that is either not indexed, 145 Sometimes you're searching for text that is either not indexed,
147 or hasn't been indexed yet. In this case you can override the 146 or hasn't been indexed yet. In this case you can override the
153 buffer is special because it displays messages from multiple 152 buffer is special because it displays messages from multiple
154 folders; each set of messages from a given folder has a heading 153 folders; each set of messages from a given folder has a heading
155 with the folder name.\\<mh-folder-mode-map> 154 with the folder name.\\<mh-folder-mode-map>
156 155
157 The appearance of the heading can be modified by customizing the 156 The appearance of the heading can be modified by customizing the
158 face `mh-index-folder'. You can jump back and forth between the 157 face `mh-search-folder'. You can jump back and forth between the
159 headings using the commands \\[mh-index-next-folder] and 158 headings using the commands \\[mh-index-next-folder] and
160 \\[mh-index-previous-folder]. 159 \\[mh-index-previous-folder].
161 160
162 In addition, the command \\[mh-index-visit-folder] can be used to 161 In addition, the command \\[mh-index-visit-folder] can be used to
163 visit the folder of the message at point. Initially, only the 162 visit the folder of the message at point. Initially, only the
167 folder. Thus, the command \\[mh-index-visit-folder] is useful to 166 folder. Thus, the command \\[mh-index-visit-folder] is useful to
168 find the actual message number of an interesting message, or to 167 find the actual message number of an interesting message, or to
169 view surrounding messages with the command \\[mh-rescan-folder]. 168 view surrounding messages with the command \\[mh-rescan-folder].
170 169
171 Because this folder is temporary, you'll probably get in the 170 Because this folder is temporary, you'll probably get in the
172 habit of killing it when you're done with 171 habit of killing it when you're done with \\[mh-kill-folder].
173 \\[mh-kill-folder]. 172
174 173 You can regenerate the results by running this command with a
175 SEARCH METHODS 174 prefix argument REDO-SEARCH-FLAG.
175
176 Note: This command uses an \"X-MHE-Checksum:\" header field to
177 cache the MD5 checksum of a message. This means that if an
178 incoming message already contains an \"X-MHE-Checksum:\" field,
179 that message might not be found by this command. The following
180 \"procmail\" recipe avoids this problem by renaming the existing
181 header field:
182
183 :0 wf
184 | formail -R \"X-MHE-Checksum\" \"X-Old-MHE-Checksum\"
185
186 Configuring Indexed Searches
176 187
177 The command \\[mh-search] runs the command defined by the option 188 The command \\[mh-search] runs the command defined by the option
178 `mh-index-program'. The default value is \"Auto-detect\" which 189 `mh-search-program'. The default value is \"Auto-detect\" which
179 means that MH-E will automatically choose one of \"swish++\", 190 means that MH-E will automatically choose one of \"swish++\",
180 \"swish-e\", \"mairix\", \"namazu\", \"pick\" and \"grep\" in 191 \"swish-e\", \"mairix\", \"namazu\", \"pick\" and \"grep\" in
181 that order. If, for example, you have both \"swish++\" and 192 that order. If, for example, you have both \"swish++\" and
182 \"mairix\" installed and you want to use \"mairix\", then you can 193 \"mairix\" installed and you want to use \"mairix\", then you can
183 set this option to \"mairix\". 194 set this option to \"mairix\".
184 195
185 *NOTE*
186
187 The \"pick\" and \"grep\" commands do not perform a
188 recursive search on the given folder.
189
190 This command uses an \"X-MHE-Checksum:\" header field to cache
191 the MD5 checksum of a message. This means that if an incoming
192 message already contains an \"X-MHE-Checksum:\" field, that
193 message might not be found by this command. The following
194 \"procmail\" recipe avoids this problem by renaming the existing
195 header field:
196
197 :0 wf
198 | formail -R \"X-MHE-Checksum\" \"X-Old-MHE-Checksum\"
199
200 The documentation for the following commands describe how to set 196 The documentation for the following commands describe how to set
201 up the various indexing programs to use with MH-E. The \"pick\" 197 up the various indexing programs to use with MH-E.
202 and \"grep\" commands do not require additional configuration.
203 198
204 - `mh-swish++-execute-search' 199 - `mh-swish++-execute-search'
205 - `mh-swish-execute-search' 200 - `mh-swish-execute-search'
206 - `mh-mairix-execute-search' 201 - `mh-mairix-execute-search'
207 - `mh-namazu-execute-search' 202 - `mh-namazu-execute-search'
208 - `mh-pick-execute-search' 203 - `mh-pick-execute-search'
209 - `mh-grep-execute-search' 204 - `mh-grep-execute-search'
210 205
211 In a program, the folder is searched with SEARCH-REGEXP. If 206 In a program, if FOLDER is \"+\" or nil, then mail in all folders
212 FOLDER is \"+\" then mail in all folders are searched. Optional 207 are searched. Optional argument WINDOW-CONFIG stores the window
213 argument WINDOW-CONFIG stores the window configuration that will 208 configuration that will be restored after the user quits the
214 be restored after the user quits the folder containing the index 209 folder containing the index search results."
215 search results."
216 (interactive 210 (interactive
217 (list current-prefix-arg 211 (list (progn
218 (progn
219 (mh-find-path) 212 (mh-find-path)
220 ;; Yes, we do want to call mh-index-choose every time in case the 213 ;; Yes, we do want to call mh-search-choose every time in case the
221 ;; user has switched the indexer manually. 214 ;; user has switched the searcher manually.
222 (unless (mh-index-choose (and current-prefix-arg 215 (unless (mh-search-choose (and current-prefix-arg
223 mh-index-previous-search 216 mh-index-previous-search
224 (cadr mh-index-previous-search))) 217 (cadr mh-index-previous-search)))
225 (error "No indexing program found")) 218 (error "No search program found"))
226 (or (and current-prefix-arg mh-index-sequence-search-flag) 219 (or (and current-prefix-arg mh-index-sequence-search-flag)
227 (and current-prefix-arg (car mh-index-previous-search)) 220 (and current-prefix-arg (car mh-index-previous-search))
228 (mh-prompt-for-folder "Search" "+" nil "all" t))) 221 (mh-prompt-for-folder "Search" "+" nil "all" t)))
229 (or (and current-prefix-arg (caddr mh-index-previous-search)) 222 (or (and current-prefix-arg (caddr mh-index-previous-search))
230 mh-index-regexp-builder 223 mh-search-regexp-builder
231 (read-string (format "%s regexp: " 224 (read-string (format "%s regexp: "
232 (upcase-initials (symbol-name mh-indexer))))) 225 (upcase-initials (symbol-name mh-searcher)))))
226 current-prefix-arg
233 (if (and (not (and current-prefix-arg 227 (if (and (not (and current-prefix-arg
234 (caddr mh-index-previous-search))) 228 (caddr mh-index-previous-search)))
235 mh-index-regexp-builder) 229 mh-search-regexp-builder)
236 (current-window-configuration) 230 (current-window-configuration)
237 nil))) 231 nil)))
238 ;; Redoing a sequence search? 232 ;; Redoing a sequence search?
239 (when (and redo-search-flag mh-index-data mh-index-sequence-search-flag 233 (when (and redo-search-flag mh-index-data mh-index-sequence-search-flag
240 (not mh-flists-called-flag)) 234 (not mh-flists-called-flag))
263 257
264 (let ((folder-path (format "%s%s" mh-user-path (substring folder 1))) 258 (let ((folder-path (format "%s%s" mh-user-path (substring folder 1)))
265 (folder-results-map (make-hash-table :test #'equal)) 259 (folder-results-map (make-hash-table :test #'equal))
266 (origin-map (make-hash-table :test #'equal))) 260 (origin-map (make-hash-table :test #'equal)))
267 ;; Run search program... 261 ;; Run search program...
268 (message "Executing %s... " mh-indexer) 262 (message "Executing %s... " mh-searcher)
269 (funcall mh-index-execute-search-function folder-path search-regexp) 263 (funcall mh-search-function folder-path search-regexp)
270 264
271 ;; Parse indexer output. 265 ;; Parse searcher output.
272 (message "Processing %s output... " mh-indexer) 266 (message "Processing %s output... " mh-searcher)
273 (goto-char (point-min)) 267 (goto-char (point-min))
274 (loop for next-result = (funcall mh-index-next-result-function) 268 (loop for next-result = (funcall mh-search-next-result-function)
275 while next-result 269 while next-result
276 do (unless (eq next-result 'error) 270 do (unless (eq next-result 'error)
277 (unless (gethash (car next-result) folder-results-map) 271 (unless (gethash (car next-result) folder-results-map)
278 (setf (gethash (car next-result) folder-results-map) 272 (setf (gethash (car next-result) folder-results-map)
279 (make-hash-table :test #'equal))) 273 (make-hash-table :test #'equal)))
312 (mh-speed-flists t mh-current-folder)) 306 (mh-speed-flists t mh-current-folder))
313 307
314 ;; Maintain history. 308 ;; Maintain history.
315 (when (or (and redo-search-flag previous-search) window-config) 309 (when (or (and redo-search-flag previous-search) window-config)
316 (setq mh-previous-window-config old-window-config)) 310 (setq mh-previous-window-config old-window-config))
317 (setq mh-index-previous-search (list folder mh-indexer search-regexp)) 311 (setq mh-index-previous-search (list folder mh-searcher search-regexp))
318 312
319 ;; Write out data to disk. 313 ;; Write out data to disk.
320 (unless mh-flists-called-flag (mh-index-write-data)) 314 (unless mh-flists-called-flag (mh-index-write-data))
321 315
322 (message "%s found %s matches in %s folders" 316 (message "%s found %s matches in %s folders"
323 (upcase-initials (symbol-name mh-indexer)) 317 (upcase-initials (symbol-name mh-searcher))
324 (loop for msg-hash being hash-values of mh-index-data 318 (loop for msg-hash being hash-values of mh-index-data
325 sum (hash-table-count msg-hash)) 319 sum (hash-table-count msg-hash))
326 (loop for msg-hash being hash-values of mh-index-data 320 (loop for msg-hash being hash-values of mh-index-data
327 count (> (hash-table-count msg-hash) 0)))))) 321 count (> (hash-table-count msg-hash) 0))))))
328 322
365 (forward-line)) 359 (forward-line))
366 (add-text-properties (point) (1+ (point)) '(front-sticky t)) 360 (add-text-properties (point) (1+ (point)) '(front-sticky t))
367 (add-text-properties (point) (1- (line-end-position)) '(read-only t)) 361 (add-text-properties (point) (1- (line-end-position)) '(read-only t))
368 (goto-char (point-max))) 362 (goto-char (point-max)))
369 363
364 ;;;###mh-autoload
370 (defvar mh-search-mode-map (make-sparse-keymap) 365 (defvar mh-search-mode-map (make-sparse-keymap)
371 "Keymap for searching folder.") 366 "Keymap for searching folder.")
372 367
368 ;;;###mh-autoload
373 ;; If this changes, modify mh-search-mode-help-messages accordingly, below. 369 ;; If this changes, modify mh-search-mode-help-messages accordingly, below.
374 (gnus-define-keys mh-search-mode-map 370 (gnus-define-keys mh-search-mode-map
375 "\C-c?" mh-help 371 "\C-c?" mh-help
376 "\C-c\C-c" mh-index-do-search 372 "\C-c\C-c" mh-index-do-search
377 "\C-c\C-p" mh-pick-do-search 373 "\C-c\C-p" mh-pick-do-search
418 (put 'mh-search-mode 'mode-class 'special) 414 (put 'mh-search-mode 'mode-class 'special)
419 415
420 (define-derived-mode mh-search-mode fundamental-mode "MH-Search" 416 (define-derived-mode mh-search-mode fundamental-mode "MH-Search"
421 "Mode for creating search templates in MH-E.\\<mh-search-mode-map> 417 "Mode for creating search templates in MH-E.\\<mh-search-mode-map>
422 418
423 After each field name, enter the pattern to search for. If a field's 419 Edit this template by entering your search criteria in an
424 value does not matter for the search, leave it empty. To search the 420 appropriate header field that is already there, or create a new
425 entire message, supply the pattern in the \"body\" of the template. 421 field yourself. If the string you're looking for could be
426 Each non-empty field must be matched for a message to be selected. To 422 anywhere in a message, then place the string underneath the row
427 effect a logical \"or\", use \\[mh-search-folder] multiple times. When 423 of dashes.
428 you have finished, type \\[mh-pick-do-search] to do the search. 424
425 To perform the search, type \\[mh-index-do-search].
426
427 Sometimes you're searching for text that is either not indexed,
428 or hasn't been indexed yet. In this case you can override the
429 default method with the pick method by running the command
430 \\[mh-pick-do-search].
429 431
430 The hook `mh-search-mode-hook' is called upon entry to this mode. 432 The hook `mh-search-mode-hook' is called upon entry to this mode.
431 433
432 \\{mh-search-mode-map}" 434 \\{mh-search-mode-map}"
433 435
434 (make-local-variable 'mh-help-messages) 436 (make-local-variable 'mh-help-messages)
435 (easy-menu-add mh-pick-menu) 437 (easy-menu-add mh-pick-menu)
436 (setq mh-help-messages mh-search-mode-help-messages)) 438 (setq mh-help-messages mh-search-mode-help-messages))
437 439
438 ;;;###mh-autoload 440 ;;;###mh-autoload
439 (defun mh-index-do-search (&optional indexer) 441 (defun mh-index-do-search (&optional searcher)
440 "Find messages that match the qualifications in the current pattern buffer. 442 "Find messages using `mh-search-program'.
441 If optional argument INDEXER is present, use it instead of 443 If optional argument SEARCHER is present, use it instead of
442 `mh-index-program'." 444 `mh-search-program'."
443 (interactive) 445 (interactive)
444 (unless (mh-index-choose indexer) (error "No indexing program found")) 446 (unless (mh-search-choose searcher) (error "No search program found"))
445 (let* ((regexp-list (mh-pick-parse-search-buffer)) 447 (let* ((regexp-list (mh-pick-parse-search-buffer))
446 (pattern (funcall mh-index-regexp-builder regexp-list))) 448 (pattern (funcall mh-search-regexp-builder regexp-list)))
447 (if pattern 449 (if pattern
448 (mh-search nil mh-current-folder pattern mh-previous-window-config) 450 (mh-search mh-current-folder pattern nil mh-previous-window-config)
449 (error "No search terms")))) 451 (error "No search terms"))))
450 452
451 ;;;###mh-autoload 453 ;;;###mh-autoload
452 (defun mh-pick-do-search () 454 (defun mh-pick-do-search ()
453 "Find messages that match the qualifications in the current pattern buffer. 455 "Find messages using \"pick\".
454 456
455 Uses the pick method described in `mh-pick-execute-search'." 457 Uses the pick method described in `mh-pick-execute-search'."
456 (interactive) 458 (interactive)
457 (mh-index-do-search 'pick)) 459 (mh-index-do-search 'pick))
458 460
640 (mh-read-seq-default "Search" nil))) 642 (mh-read-seq-default "Search" nil)))
641 (unless sequence (setq sequence mh-unseen-seq)) 643 (unless sequence (setq sequence mh-unseen-seq))
642 (let* ((mh-flists-search-folders folders) 644 (let* ((mh-flists-search-folders folders)
643 (mh-flists-sequence sequence) 645 (mh-flists-sequence sequence)
644 (mh-flists-called-flag t) 646 (mh-flists-called-flag t)
645 (mh-indexer 'flists) 647 (mh-searcher 'flists)
646 (mh-index-execute-search-function 'mh-flists-execute) 648 (mh-search-function 'mh-flists-execute)
647 (mh-index-next-result-function 'mh-mairix-next-result) 649 (mh-search-next-result-function 'mh-mairix-next-result)
648 (mh-mairix-folder mh-user-path) 650 (mh-mairix-folder mh-user-path)
649 (mh-index-regexp-builder nil) 651 (mh-search-regexp-builder nil)
650 (new-folder (format "%s/%s/%s" mh-index-folder 652 (new-folder (format "%s/%s/%s" mh-index-folder
651 mh-flists-results-folder sequence)) 653 mh-flists-results-folder sequence))
652 (window-config (if (equal new-folder mh-current-folder) 654 (window-config (if (equal new-folder mh-current-folder)
653 mh-previous-window-config 655 mh-previous-window-config
654 (current-window-configuration))) 656 (current-window-configuration)))
656 message) 658 message)
657 (cond ((buffer-live-p (get-buffer new-folder)) 659 (cond ((buffer-live-p (get-buffer new-folder))
658 ;; The destination folder is being visited. Trick `mh-search' 660 ;; The destination folder is being visited. Trick `mh-search'
659 ;; into thinking that the folder resulted from a previous search. 661 ;; into thinking that the folder resulted from a previous search.
660 (set-buffer new-folder) 662 (set-buffer new-folder)
661 (setq mh-index-previous-search (list folders mh-indexer sequence)) 663 (setq mh-index-previous-search (list folders mh-searcher sequence))
662 (setq redo-flag t)) 664 (setq redo-flag t))
663 ((mh-folder-exists-p new-folder) 665 ((mh-folder-exists-p new-folder)
664 ;; Folder exists but we don't have it open. That means they are 666 ;; Folder exists but we don't have it open. That means they are
665 ;; stale results from a old flists search. Clear it out. 667 ;; stale results from a old flists search. Clear it out.
666 (mh-exec-cmd-quiet nil "rmf" new-folder))) 668 (mh-exec-cmd-quiet nil "rmf" new-folder)))
667 (setq message (mh-search redo-flag "+" mh-flists-results-folder 669 (setq message (mh-search "+" mh-flists-results-folder
668 window-config) 670 redo-flag window-config)
669 mh-index-sequence-search-flag t 671 mh-index-sequence-search-flag t
670 mh-index-previous-search (list folders mh-indexer sequence)) 672 mh-index-previous-search (list folders mh-searcher sequence))
671 (mh-index-write-data) 673 (mh-index-write-data)
672 (when (stringp message) (message "%s" message)))) 674 (when (stringp message) (message "%s" message))))
673 675
674 (defvar mh-flists-search-folders) 676 (defvar mh-flists-search-folders)
675 677
829 (mh-visit-folder 831 (mh-visit-folder
830 folder (loop for x being the hash-keys of (gethash folder mh-index-data) 832 folder (loop for x being the hash-keys of (gethash folder mh-index-data)
831 when (mh-msg-exists-p x folder) collect x))))) 833 when (mh-msg-exists-p x folder) collect x)))))
832 834
833 ;;;###mh-autoload 835 ;;;###mh-autoload
834 (defun mh-index-p () 836 (defun mh-search-p ()
835 "Non-nil means that this folder was generated by an index search." 837 "Non-nil means that this folder was generated by searching."
836 mh-index-data) 838 mh-index-data)
837 839
838 ;;;###mh-autoload 840 ;;;###mh-autoload
839 (defun mh-index-execute-commands () 841 (defun mh-index-execute-commands ()
840 "Delete/refile the actual messages. 842 "Delete/refile the actual messages.
879 881
880 882
881 883
882 ;;; Indexing functions 884 ;;; Indexing functions
883 885
884 ;; Support different indexing programs 886 ;; Support different search programs
885 (defvar mh-indexer-choices 887 (defvar mh-search-choices
886 '((swish++ 888 '((swish++
887 mh-swish++-binary mh-swish++-execute-search mh-swish++-next-result 889 mh-swish++-binary mh-swish++-execute-search mh-swish++-next-result
888 mh-swish++-regexp-builder) 890 mh-swish++-regexp-builder)
889 (swish 891 (swish
890 mh-swish-binary mh-swish-execute-search mh-swish-next-result nil) 892 mh-swish-binary mh-swish-execute-search mh-swish-next-result nil)
896 (pick 898 (pick
897 mh-pick-binary mh-pick-execute-search mh-pick-next-result 899 mh-pick-binary mh-pick-execute-search mh-pick-next-result
898 mh-pick-regexp-builder) 900 mh-pick-regexp-builder)
899 (grep 901 (grep
900 mh-grep-binary mh-grep-execute-search mh-grep-next-result nil)) 902 mh-grep-binary mh-grep-execute-search mh-grep-next-result nil))
901 "List of possible indexer choices.") 903 "List of possible searcher choices.")
902 904
903 (defun mh-index-choose (&optional indexer) 905 (defun mh-search-choose (&optional searcher)
904 "Choose an indexing function. 906 "Choose a searching function.
905 The side-effects of this function are that the variables 907 The side-effects of this function are that the variables
906 `mh-indexer', `mh-index-execute-search-function', and 908 `mh-searcher', `mh-search-function', and
907 `mh-index-next-result-function' are set according to the first 909 `mh-search-next-result-function' are set according to the first
908 indexer in `mh-indexer-choices' present on the system. 910 searcher in `mh-search-choices' present on the system. If
909 If optional argument INDEXER is present, use it instead of 911 optional argument SEARCHER is present, use it instead of
910 `mh-index-program'." 912 `mh-search-program'."
911 (block nil 913 (block nil
912 (let ((program-alist (cond (indexer 914 (let ((program-alist (cond (searcher
913 (list (assoc indexer mh-indexer-choices))) 915 (list (assoc searcher mh-search-choices)))
914 (mh-index-program 916 (mh-search-program
915 (list 917 (list
916 (assoc mh-index-program mh-indexer-choices))) 918 (assoc mh-search-program mh-search-choices)))
917 (t mh-indexer-choices)))) 919 (t mh-search-choices))))
918 (while program-alist 920 (while program-alist
919 (let* ((current (pop program-alist)) 921 (let* ((current (pop program-alist))
920 (executable (symbol-value (cadr current)))) 922 (executable (symbol-value (cadr current))))
921 (when executable 923 (when executable
922 (setq mh-indexer (car current)) 924 (setq mh-searcher (car current))
923 (setq mh-index-execute-search-function (nth 2 current)) 925 (setq mh-search-function (nth 2 current))
924 (setq mh-index-next-result-function (nth 3 current)) 926 (setq mh-search-next-result-function (nth 3 current))
925 (setq mh-index-regexp-builder (nth 4 current)) 927 (setq mh-search-regexp-builder (nth 4 current))
926 (return mh-indexer)))) 928 (return mh-searcher))))
927 nil))) 929 nil)))
928 930
929 ;;; Swish++ interface 931 ;;; Swish++ interface
930 932
931 (defvar mh-swish++-binary (or (executable-find "search++") 933 (defvar mh-swish++-binary (or (executable-find "search++")
933 (defvar mh-swish++-directory ".swish++") 935 (defvar mh-swish++-directory ".swish++")
934 (defvar mh-swish-folder nil) 936 (defvar mh-swish-folder nil)
935 937
936 ;;;###mh-autoload 938 ;;;###mh-autoload
937 (defun mh-swish++-execute-search (folder-path search-regexp) 939 (defun mh-swish++-execute-search (folder-path search-regexp)
938 "Execute swish++ and read the results. 940 "Execute swish++.
939 941
940 In the examples below, replace \"/home/user/Mail\" with the path to 942 In the examples below, replace \"/home/user/Mail\" with the path to
941 your MH directory. 943 your MH directory.
942 944
943 First create the directory \"/home/user/Mail/.swish++\". Then create 945 First create the directory \"/home/user/Mail/.swish++\". Then create
1013 (defvar mh-swish-binary (executable-find "swish-e")) 1015 (defvar mh-swish-binary (executable-find "swish-e"))
1014 (defvar mh-swish-directory ".swish") 1016 (defvar mh-swish-directory ".swish")
1015 1017
1016 ;;;###mh-autoload 1018 ;;;###mh-autoload
1017 (defun mh-swish-execute-search (folder-path search-regexp) 1019 (defun mh-swish-execute-search (folder-path search-regexp)
1018 "Execute swish-e and read the results. 1020 "Execute swish-e.
1019 1021
1020 In the examples below, replace \"/home/user/Mail\" with the path 1022 In the examples below, replace \"/home/user/Mail\" with the path
1021 to your MH directory. 1023 to your MH directory.
1022 1024
1023 First create the directory \"/home/user/Mail/.swish\". Then 1025 First create the directory \"/home/user/Mail/.swish\". Then
1114 (defvar mh-mairix-directory ".mairix") 1116 (defvar mh-mairix-directory ".mairix")
1115 (defvar mh-mairix-folder nil) 1117 (defvar mh-mairix-folder nil)
1116 1118
1117 ;;;###mh-autoload 1119 ;;;###mh-autoload
1118 (defun mh-mairix-execute-search (folder-path search-regexp-list) 1120 (defun mh-mairix-execute-search (folder-path search-regexp-list)
1119 "Execute mairix and read the results. 1121 "Execute mairix.
1120 1122
1121 In the examples below, replace \"/home/user/Mail\" with the path 1123 In the examples below, replace \"/home/user/Mail\" with the path
1122 to your MH directory. 1124 to your MH directory.
1123 1125
1124 First create the directory \"/home/user/Mail/.mairix\". Then 1126 First create the directory \"/home/user/Mail/.mairix\". Then
1248 (defvar mh-namazu-directory ".namazu") 1250 (defvar mh-namazu-directory ".namazu")
1249 (defvar mh-namazu-folder nil) 1251 (defvar mh-namazu-folder nil)
1250 1252
1251 ;;;###mh-autoload 1253 ;;;###mh-autoload
1252 (defun mh-namazu-execute-search (folder-path search-regexp) 1254 (defun mh-namazu-execute-search (folder-path search-regexp)
1253 "Execute namazu and read the results. 1255 "Execute namazu.
1254 1256
1255 In the examples below, replace \"/home/user/Mail\" with the path to 1257 In the examples below, replace \"/home/user/Mail\" with the path to
1256 your MH directory. 1258 your MH directory.
1257 1259
1258 First create the directory \"/home/user/Mail/.namazu\". Then create 1260 First create the directory \"/home/user/Mail/.namazu\". Then create
1326 1328
1327 ;;;###mh-autoload 1329 ;;;###mh-autoload
1328 (defun mh-pick-execute-search (folder-path search-regexp) 1330 (defun mh-pick-execute-search (folder-path search-regexp)
1329 "Execute pick. 1331 "Execute pick.
1330 1332
1331 There are no semantics associated with the search criteria--they 1333 Read \"pick(1)\" or the section Finding Messages with pick in the
1332 are simply treated as strings. Case is ignored when all lowercase 1334 MH book to find out more about how to enter the criteria (see URL
1333 is used, and regular expressions (a la \"ed\") are available. 1335 `http://www.ics.uci.edu/~mh/book/mh/finpic.htm').
1334 1336
1335 In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP 1337 In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP
1336 is used to search." 1338 is used to search."
1337 (set-buffer (get-buffer-create mh-temp-index-buffer)) 1339 (set-buffer (get-buffer-create mh-temp-index-buffer))
1338 (erase-buffer) 1340 (erase-buffer)
1412 1414
1413 (defvar mh-grep-binary (executable-find "grep")) 1415 (defvar mh-grep-binary (executable-find "grep"))
1414 1416
1415 ;;;###mh-autoload 1417 ;;;###mh-autoload
1416 (defun mh-grep-execute-search (folder-path search-regexp) 1418 (defun mh-grep-execute-search (folder-path search-regexp)
1417 "Execute grep and read the results. 1419 "Execute grep.
1420
1421 Unlike the other search methods, this method does not use the
1422 MH-Search buffer. Instead, you simply enter a regular expression
1423 in the minibuffer. For help in constructing regular expressions,
1424 see your man page for \"grep\".
1418 1425
1419 In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP 1426 In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP
1420 is used to search." 1427 is used to search."
1421 (set-buffer (get-buffer-create mh-temp-index-buffer)) 1428 (set-buffer (get-buffer-create mh-temp-index-buffer))
1422 (erase-buffer) 1429 (erase-buffer)
1475 (when (car string) (insert (car string))) 1482 (when (car string) (insert (car string)))
1476 (dolist (s (cdr string)) 1483 (dolist (s (cdr string))
1477 (insert "_" s))) 1484 (insert "_" s)))
1478 (setq string (mh-replace-string "-lbrace" " ")) 1485 (setq string (mh-replace-string "-lbrace" " "))
1479 (setq string (mh-replace-string "-rbrace" " ")) 1486 (setq string (mh-replace-string "-rbrace" " "))
1487 (setq string (mh-replace-string "-search" " "))
1480 (subst-char-in-region (point-min) (point-max) ?( ? t) 1488 (subst-char-in-region (point-min) (point-max) ?( ? t)
1481 (subst-char-in-region (point-min) (point-max) ?) ? t) 1489 (subst-char-in-region (point-min) (point-max) ?) ? t)
1482 (subst-char-in-region (point-min) (point-max) ?- ? t) 1490 (subst-char-in-region (point-min) (point-max) ?- ? t)
1483 (goto-char (point-min)) 1491 (goto-char (point-min))
1484 (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_))) 1492 (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_)))
1490 (subst-char-in-region (point-min) (point-max) ?\t ?_ t) 1498 (subst-char-in-region (point-min) (point-max) ?\t ?_ t)
1491 (subst-char-in-region (point-min) (point-max) ?\n ?_ t) 1499 (subst-char-in-region (point-min) (point-max) ?\n ?_ t)
1492 (subst-char-in-region (point-min) (point-max) ?\r ?_ t) 1500 (subst-char-in-region (point-min) (point-max) ?\r ?_ t)
1493 (subst-char-in-region (point-min) (point-max) ?/ ?$ t) 1501 (subst-char-in-region (point-min) (point-max) ?/ ?$ t)
1494 (let ((out (truncate-string-to-width (buffer-string) 20))) 1502 (let ((out (truncate-string-to-width (buffer-string) 20)))
1495 (cond ((eq mh-indexer 'flists) 1503 (cond ((eq mh-searcher 'flists)
1496 (format "%s/%s" mh-flists-results-folder mh-flists-sequence)) 1504 (format "%s/%s" mh-flists-results-folder mh-flists-sequence))
1497 ((equal out mh-flists-results-folder) (concat out "1")) 1505 ((equal out mh-flists-results-folder) (concat out "1"))
1498 (t out))))) 1506 (t out)))))
1499 1507
1500 (defun mh-folder-exists-p (folder) 1508 (defun mh-folder-exists-p (folder)