Mercurial > emacs
diff lisp/mh-e/mh-pick.el @ 49578:b35587af8747
Upgraded to MH-E version 7.2.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
author | Bill Wohler <wohler@newt.com> |
---|---|
date | Mon, 03 Feb 2003 20:55:30 +0000 |
parents | 06b77df47802 |
children | 7dd3d5eae9c7 |
line wrap: on
line diff
--- a/lisp/mh-e/mh-pick.el Mon Feb 03 16:39:05 2003 +0000 +++ b/lisp/mh-e/mh-pick.el Mon Feb 03 20:55:30 2003 +0000 @@ -30,7 +30,7 @@ ;;; Change Log: -;; $Id: mh-pick.el,v 1.10 2003/01/08 23:21:16 wohler Exp $ +;; $Id: mh-pick.el,v 1.30 2003/01/27 04:16:47 wohler Exp $ ;;; Code: @@ -44,28 +44,34 @@ "Keymap for searching folder.") (defvar mh-searching-folder nil) ;Folder this pick is searching. +(defvar mh-searching-function nil) ;;;###mh-autoload -(defun mh-search-folder (folder) +(defun mh-search-folder (folder window-config) "Search FOLDER for messages matching a pattern. This function uses the MH command `pick' to do the work. -Add the messages found to the sequence named `search'." - (interactive (list (mh-prompt-for-folder "Search" - mh-current-folder - t))) - (switch-to-buffer-other-window "pick-pattern") - (if (or (zerop (buffer-size)) - (not (y-or-n-p "Reuse pattern? "))) - (mh-make-pick-template) - (message "")) - (setq mh-searching-folder folder) - (message "%s" (substitute-command-keys - (concat "Type \\[mh-do-pick-search] to search messages, " - "\\[mh-help] for help.")))) +Add the messages found to the sequence named `search'. +Argument WINDOW-CONFIG is the current window configuration and is used when +the search folder is dismissed." + (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil t) + (current-window-configuration))) + (let ((pick-folder (if (equal folder "+") mh-current-folder folder))) + (switch-to-buffer-other-window "search-pattern") + (if (or (zerop (buffer-size)) + (not (y-or-n-p "Reuse pattern? "))) + (mh-make-pick-template) + (message "")) + (setq mh-searching-function 'mh-pick-do-search + mh-searching-folder pick-folder + mh-current-folder folder + mh-previous-window-config window-config) + (message "%s" (substitute-command-keys + (concat "Type \\[mh-do-search] to search messages, " + "\\[mh-help] for help."))))) (defun mh-make-pick-template () "Initialize the current buffer with a template for a pick pattern." - (erase-buffer) + (let ((inhibit-read-only t)) (erase-buffer)) (insert "From: \n" "To: \n" "Cc: \n" @@ -74,20 +80,29 @@ "---------\n") (mh-pick-mode) (goto-char (point-min)) - (end-of-line)) + (dotimes (i 5) + (add-text-properties (point) (1+ (point)) '(front-sticky t)) + (add-text-properties (- (line-end-position) 2) (1- (line-end-position)) + '(rear-nonsticky t)) + (add-text-properties (point) (1- (line-end-position)) '(read-only t)) + (forward-line)) + (add-text-properties (point) (1+ (point)) '(front-sticky t)) + (add-text-properties (point) (1- (line-end-position)) '(read-only t)) + (goto-char (point-max))) ;;; Menu extracted from mh-menubar.el V1.1 (31 July 2001) (easy-menu-define mh-pick-menu mh-pick-mode-map "Menu for MH-E pick-mode" '("Pick" - ["Execute the Search" mh-do-pick-search t])) + ["Execute the Search" mh-pick-do-search t])) ;;; Help Messages ;;; Group messages logically, more or less. (defvar mh-pick-mode-help-messages '((nil - "Search messages: \\[mh-do-pick-search]\n" + "Search messages using pick: \\[mh-pick-do-search]\n" + "Search messages using index: \\[mh-index-do-search]\n" "Move to a field by typing C-c C-f C-<field>\n" "where <field> is the first letter of the desired field.")) "Key binding cheat sheet. @@ -111,7 +126,7 @@ entire message, supply the pattern in the \"body\" of the template. Each non-empty field must be matched for a message to be selected. To effect a logical \"or\", use \\[mh-search-folder] multiple times. -When you have finished, type \\[mh-do-pick-search] to do the search. +When you have finished, type \\[mh-pick-do-search] to do the search. The value of `mh-pick-mode-hook' is a list of functions to be called, with no arguments, upon entry to this mode. @@ -119,8 +134,9 @@ \\{mh-pick-mode-map}" (make-local-variable 'mh-searching-folder) + (make-local-variable 'mh-searching-function) + (make-local-variable 'mh-help-messages) (easy-menu-add mh-pick-menu) - (make-local-variable 'mh-help-messages) (setq mh-help-messages mh-pick-mode-help-messages) (run-hooks 'mh-pick-mode-hook)) @@ -128,41 +144,58 @@ (defun mh-do-pick-search () "Find messages that match the qualifications in the current pattern buffer. Messages are searched for in the folder named in `mh-searching-folder'. +Add the messages found to the sequence named `search'. + +This is a deprecated function and `mh-pick-do-search' should be used instead." + (interactive) + (mh-pick-do-search)) + +;;;###mh-autoload +(defun mh-pick-do-search () + "Find messages that match the qualifications in the current pattern buffer. +Messages are searched for in the folder named in `mh-searching-folder'. Add the messages found to the sequence named `search'." (interactive) - (let ((pattern-buffer (buffer-name)) - (searching-buffer mh-searching-folder) - range - msgs - (pattern nil) - (new-buffer nil)) + (let ((pattern-list (mh-pick-parse-search-buffer)) + (folder mh-searching-folder) + (new-buffer-flag nil) + (window-config mh-previous-window-config) + range pick-args msgs) + (unless pattern-list + (error "No search pattern specified")) (save-excursion - (cond ((get-buffer searching-buffer) - (set-buffer searching-buffer) - (setq range (list (format "%d-%d" - mh-first-msg-num mh-last-msg-num)))) + (cond ((get-buffer folder) + (set-buffer folder) + (setq range (if (and mh-first-msg-num mh-last-msg-num) + (format "%d-%d" mh-first-msg-num mh-last-msg-num) + "all"))) (t - (mh-make-folder searching-buffer) - (setq range '("all")) - (setq new-buffer t)))) - (message "Searching...") - (goto-char (point-min)) - (while (and range - (setq pattern (mh-next-pick-field pattern-buffer))) - (setq msgs (mh-seq-from-command searching-buffer - 'search - (mh-list-to-string - (list "pick" pattern searching-buffer - "-list" - (mh-coalesce-msg-list range))))) - (setq range msgs)) ;restrict the pick range for next pass + (mh-make-folder folder) + (setq range "all") + (setq new-buffer-flag t)))) + (setq pick-args (mh-pick-regexp-builder pattern-list)) + (when pick-args + (setq msgs (mh-seq-from-command folder 'search + `("pick" ,folder ,range ,@pick-args)))) (message "Searching...done") - (if new-buffer - (mh-scan-folder searching-buffer msgs) - (switch-to-buffer searching-buffer)) + (if (not new-buffer-flag) + (switch-to-buffer folder) + (mh-scan-folder folder msgs) + (setq mh-previous-window-config window-config)) (mh-add-msgs-to-seq msgs 'search) (delete-other-windows))) +;;;###mh-autoload +(defun mh-do-search () + "Use the default searching function. +If \\[mh-search-folder] was used to create the search pattern then pick is used +to search the folder. Otherwise if \\[mh-index-search] was used then the +indexing program specified in `mh-index-program' is used." + (interactive) + (if (symbolp mh-searching-function) + (funcall mh-searching-function) + (error "No searching function defined"))) + (defun mh-seq-from-command (folder seq command) "In FOLDER, make a sequence named SEQ by executing COMMAND. COMMAND is a list. The first element is a program name @@ -181,31 +214,66 @@ (setq msgs (nreverse msgs)) ;put in ascending order msgs))) -(defun mh-next-pick-field (buffer) - "Return the next piece of a pick argument extracted from BUFFER. -Return a list like (\"--fieldname\" \"pattern\") or (\"-search\" \"bodypat\") -or nil if no pieces remain." - (set-buffer buffer) - (let ((case-fold-search t)) - (cond ((eobp) - nil) - ((re-search-forward "^\\([a-z][^: \t\n]*\\):[ \t]*\\([a-z0-9].*\\)$" - nil t) - (let* ((component - (format "--%s" - (downcase (buffer-substring (match-beginning 1) - (match-end 1))))) - (pat (buffer-substring (match-beginning 2) (match-end 2)))) - (forward-line 1) - (list component pat))) - ((re-search-forward "^-*$" nil t) - (forward-char 1) - (let ((body (buffer-substring (point) (point-max)))) - (if (and (> (length body) 0) (not (equal body "\n"))) - (list "-search" body) - nil))) - (t - nil)))) +(defun mh-pick-parse-search-buffer () + "Parse the search buffer contents. +The function returns a alist. The car of each element is either the header name +to search in or nil to search the whole message. The cdr of the element is the +pattern to search." + (save-excursion + (let ((pattern-list ()) + (in-body-flag nil) + start begin) + (goto-char (point-min)) + (while (not (eobp)) + (if (search-forward "--------" (line-end-position) t) + (setq in-body-flag t) + (beginning-of-line) + (setq begin (point)) + (setq start (if in-body-flag + (point) + (search-forward ":" (line-end-position) t) + (point))) + (push (cons (and (not in-body-flag) + (intern (downcase + (buffer-substring-no-properties + begin (1- start))))) + (mh-index-parse-search-regexp + (buffer-substring-no-properties + start (line-end-position)))) + pattern-list)) + (forward-line)) + pattern-list))) + + + +;; Functions specific to how pick works... +(defun mh-pick-construct-regexp (expr component) + "Construct pick compatible expression corresponding to EXPR. +COMPONENT is the component to search." + (cond ((atom expr) (list component expr)) + ((eq (car expr) 'and) + `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-and" + ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) + ((eq (car expr) 'or) + `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-or" + ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) + ((eq (car expr) 'not) + `("-lbrace" "-not" ,@(mh-pick-construct-regexp (cadr expr) component) + "-rbrace")) + (t (error "Unknown operator '%s' seen" (car expr))))) + +(defun mh-pick-regexp-builder (pattern-list) + "Generate pick search expression from PATTERN-LIST." + (let ((result ())) + (dolist (pattern pattern-list) + (when (cdr pattern) + (setq result `(,@result "-and" "-lbrace" + ,@(mh-pick-construct-regexp + (cdr pattern) (if (car pattern) + (format "-%s" (car pattern)) + "-search")) + "-rbrace")))) + (cdr result))) @@ -213,7 +281,9 @@ ;;; If this changes, modify mh-pick-mode-help-messages accordingly, above. (gnus-define-keys mh-pick-mode-map "\C-c?" mh-help - "\C-c\C-c" mh-do-pick-search + "\C-c\C-i" mh-index-do-search + "\C-c\C-p" mh-pick-do-search + "\C-c\C-c" mh-do-search "\C-c\C-f\C-b" mh-to-field "\C-c\C-f\C-c" mh-to-field "\C-c\C-f\C-d" mh-to-field