;; Copyright (C) 1985, 1986, 1987, 1988,
;; 1990, 1992, 1993, 1994, 1995, 1997, 1999,
-;; 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Maintainer: Bill Wohler <wohler@newt.com>
;; MH-E is an Emacs interface to the MH mail system.
-;; MH-E is supported in GNU Emacs 20 and 21, with MH 6.8.4 and nmh 1.0.4.
+;; MH-E is supported in GNU Emacs 21 and 22 as well as XEmacs 21
+;; (except for versions 21.5.9-21.5.16), with MH 6.8.4 on, nmh 1.0.4
+;; on, and GNU mailutils 0.4 on.
;; Mailing Lists:
;; mh-e-users@lists.sourceforge.net
(eval-when-compile (require 'mh-acros))
(mh-require-cl)
-(require 'mh-utils)
-(require 'mh-init)
-(require 'mh-inc)
-(require 'mh-seq)
-(require 'gnus-util)
-(require 'easymenu)
-;; Shush the byte-compiler
-(defvar font-lock-auto-fontify)
-(defvar font-lock-defaults)
+(require 'easymenu)
+(require 'gnus-util)
+(require 'mh-buffers)
+(require 'mh-seq)
+(require 'mh-utils)
(defconst mh-version "7.85+cvs" "Version number of MH-E.")
additional hints for fontification have been added to the fifth
column (remember that in Emacs, the first column is 0).
-The values of the fifth column, in priority order, are: `-' if
+The values of the fifth column, in priority order, are: \"-\" if
the message has been replied to, t if an address on the To: line
-matches one of the mailboxes of the current user, `c' if the Cc:
-line matches, `b' if the Bcc: line matches, and `n' if a
+matches one of the mailboxes of the current user, \"c\" if the Cc:
+line matches, \"b\" if the Bcc: line matches, and \"n\" if a
non-empty Newsgroups: header is present.")
(defvar mh-scan-format-nmh
hints for fontification have been added to the fifth
column (remember that in Emacs, the first column is 0).
-The values of the fifth column, in priority order, are: `-' if
+The values of the fifth column, in priority order, are: \"-\" if
the message has been replied to, t if an address on the To: field
-matches one of the mailboxes of the current user, `c' if the Cc:
-field matches, `b' if the Bcc: field matches, and `n' if a
+matches one of the mailboxes of the current user, \"c\" if the Cc:
+field matches, \"b\" if the Bcc: field matches, and \"n\" if a
non-empty Newsgroups: field is present.")
(defvar mh-note-deleted ?D
\"^\\\\( *[0-9]+\\\\)[^D^0-9]\".
This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. This regular
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-msg-number'. This regular
expression should be correct as it is needed by non-fontification
functions.")
\"^\\\\( *[0-9]+\\\\)D\".
This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. This regular
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-deleted'. This regular
expression should be correct as it is needed by non-fontification
functions. See also `mh-note-deleted'.")
\"^\\\\( *[0-9]+\\\\)\\\\^\".
This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. This regular
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-refiled'. This regular
expression should be correct as it is needed by non-fontification
functions. See also `mh-note-refiled'.")
This expression includes the leading space and current message
marker \"+\" within the parenthesis since it looks better to
-highlight these items as well. This regular expression should be
-correct as it is needed by non-fontification functions. See also
-`mh-note-cur'.")
+highlight these items as well. The highlighting is done with the
+face `mh-folder-cur-msg-number'. This regular expression should
+be correct as it is needed by non-fontification functions. See
+also `mh-note-cur'.")
(defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)"
"This regular expression matches a valid date.
expects this expression to contain only one parenthesized
expression which matches the date field as in the default of
\"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}. If this regular expression
-is not correct, the date will not be highlighted. See also
-`mh-scan-format-regexp'.")
+is not correct, the date will not be highlighted with the face
+`mh-folder-date'.")
(defvar mh-scan-rcpt-regexp "\\(To:\\)\\(..............\\)"
"This regular expression specifies the recipient in messages you sent.
Note that the default setting of `mh-folder-font-lock-keywords'
expects this expression to contain two parenthesized expressions.
-The first is expected to match the `To:' that the default scan
+The first is expected to match the \"To:\" that the default scan
format file generates. The second is expected to match the
recipient's name as in the default of
\"\\\\(To:\\\\)\\\\(..............\\\\)\". If this regular
-expression is not correct, the recipient will not be
-highlighted.")
+expression is not correct, the \"To:\" string will not be
+highlighted with the face `mh-folder-to' and the recipient will
+not be highlighted with the face `mh-folder-address'")
(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
"This regular expression matches the message body fragment.
expects this expression to contain at least one parenthesized
expression which matches the body text as in the default of
\"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\". If this regular expression is
-not correct, the body fragment will not be highlighted.")
+not correct, the body fragment will not be highlighted with the
+face `mh-folder-body'.")
(defvar mh-scan-subject-regexp
"^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least three parenthesized expressions.
-The first is expected to match the `Re:' string, if any. The
-second matches an optional bracketed number after `Re:', such as
-in `Re[2]:' (and is thus a sub-expression of the first
-expression) and the third is expected to match the subject line
-itself as in the default of \(broken on multiple lines for
-readability):
+The first is expected to match the \"Re:\" string, if any, and is
+highlighted with the face `mh-folder-followup'. The second
+matches an optional bracketed number after \"Re:\", such as in
+\"Re[2]:\" (and is thus a sub-expression of the first expression)
+and the third is expected to match the subject line itself which
+is highlighted with the face `mh-folder-subject'. For example,
+the default (broken on multiple lines for readability) is
^ *[0-9]+........[ ]*...................
\\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)*
This regular expression should be correct as it is needed by
non-fontification functions.")
-(defvar mh-scan-format-regexp
- (concat "\\([bct]\\)" mh-scan-date-regexp " *\\(..................\\)")
- "This regular expression matches the output of scan.
+(defvar mh-scan-sent-to-me-sender-regexp
+ "^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)"
+ "This regular expression matches messages sent to us.
Note that the default setting of `mh-folder-font-lock-keywords'
-expects this expression to contain at least three parenthesized
+expects this expression to contain at least two parenthesized
expressions. The first should match the fontification hint (see
-`mh-scan-format-nmh'), the second is found in
-`mh-scan-date-regexp', and the third should match the user name
+`mh-scan-format-nmh') and the second should match the user name
as in the default of
- \"(concat \"\\\\([bct]\\\\)\" mh-scan-date-regexp
- \"*\\\\(..................\\\\)\")\".
+ ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\)
-If this regular expression is not correct, the notation hints and
-the sender will not be highlighted.")
+If this regular expression is not correct, the notation hints
+will not be highlighted with the face
+`mh-mh-folder-sent-to-me-hint' and the sender will not be
+highlighted with the face `mh-folder-sent-to-me-sender'.")
\f
(list
;; Folders when displaying index buffer
(list "^\\+.*"
- '(0 mh-index-folder-face))
+ '(0 'mh-index-folder))
;; Marked for deletion
(list (concat mh-scan-deleted-msg-regexp ".*")
- '(0 mh-folder-deleted-face))
+ '(0 'mh-folder-deleted))
;; Marked for refile
(list (concat mh-scan-refiled-msg-regexp ".*")
- '(0 mh-folder-refiled-face))
- ;;after subj
- (list mh-scan-body-regexp '(1 mh-folder-body-face nil t))
+ '(0 'mh-folder-refiled))
+ ;; After subject
+ (list mh-scan-body-regexp
+ '(1 'mh-folder-body nil t))
+ ;; Subject
'(mh-folder-font-lock-subject
- (1 mh-folder-followup-face append t)
- (2 mh-folder-subject-face append t))
- ;;current msg
+ (1 'mh-folder-followup append t)
+ (2 'mh-folder-subject append t))
+ ;; Current message number
(list mh-scan-cur-msg-number-regexp
- '(1 mh-folder-cur-msg-number-face))
+ '(1 'mh-folder-cur-msg-number))
+ ;; Message number
(list mh-scan-good-msg-regexp
- '(1 mh-folder-msg-number-face)) ;; Msg number
- (list mh-scan-date-regexp '(1 mh-folder-date-face)) ;; Date
+ '(1 'mh-folder-msg-number))
+ ;; Date
+ (list mh-scan-date-regexp
+ '(1 'mh-folder-date))
+ ;; Messages from me (To:)
(list mh-scan-rcpt-regexp
- '(1 mh-folder-to-face) ;; To:
- '(2 mh-folder-address-face)) ;; address
- ;; scan font-lock name
- (list mh-scan-format-regexp
- '(1 mh-folder-date-face)
- '(3 mh-folder-scan-format-face)))
+ '(1 'mh-folder-to)
+ '(2 'mh-folder-address))
+ ;; Messages to me
+ (list mh-scan-sent-to-me-sender-regexp
+ '(1 'mh-folder-sent-to-me-hint)
+ '(2 'mh-folder-sent-to-me-sender)))
"Keywords (regular expressions) used to fontify the MH-Folder buffer.")
(defvar mh-scan-cmd-note-width 1
"Number of columns consumed by the cmd-note field in `mh-scan-format'.
-This column will have one of the values: ` ', `D', `^', `+' and
-where ` ' is the default value,
+This column will have one of the values: \" \", \"D\", \"^\", \"+\" and
+where \" \" is the default value,
- `D' is the `mh-note-deleted' character,
- `^' is the `mh-note-refiled' character, and
- `+' is the `mh-note-cur' character.")
+ \"D\" is the `mh-note-deleted' character,
+ \"^\" is the `mh-note-refiled' character, and
+ \"+\" is the `mh-note-cur' character.")
(defvar mh-scan-destination-width 1
"Number of columns consumed by the destination field in `mh-scan-format'.
-This column will have one of ' ', '%', '-', 't', 'c', 'b', or `n'
+This column will have one of \" \", \"%\", \"-\", \"t\", \"c\", \"b\", or \"n\"
in it.
- ' ' blank space is the default character.
- '%' indicates that the message in in a named MH sequence.
- '-' indicates that the message has been annotated with a replied field.
- 't' indicates that the message contains mymbox in the To: field.
- 'c' indicates that the message contains mymbox in the Cc: field.
- 'b' indicates that the message contains mymbox in the Bcc: field.
- 'n' indicates that the message contains a Newsgroups: field.")
+ \" \" blank space is the default character.
+ \"%\" indicates that the message in in a named MH sequence.
+ \"-\" indicates that the message has been annotated with a replied field.
+ \"t\" indicates that the message contains mymbox in the To: field.
+ \"c\" indicates that the message contains mymbox in the Cc: field.
+ \"b\" indicates that the message contains mymbox in the Bcc: field.
+ \"n\" indicates that the message contains a Newsgroups: field.")
(defvar mh-scan-date-width 5
"Number of columns consumed by the date field in `mh-scan-format'.
(defvar mh-scan-date-flag-width 1
"Number of columns consumed to flag (in)valid dates in `mh-scan-format'.
-This column will have ` ' for valid and `*' for invalid or
+This column will have \" \" for valid and \"*\" for invalid or
missing dates.")
(defvar mh-scan-from-mbox-width 17
"Lists which folders were affected by deletes and refiles.
This list will always include the current folder
`mh-current-folder'. This variable can be used by
-`mh-before-commands-processed-hook'.")
+`mh-after-commands-processed-hook'.")
(defvar mh-next-direction 'forward
"Direction to move to next message.")
(mh-recenter 0))
(setq mh-showing-with-headers t)))
-(defun mh-inc-folder (&optional maildrop-name folder)
+(defun mh-inc-folder (&optional file folder)
"Incorporate new mail into a folder.
You can incorporate mail from any file into the current folder by
specifying a prefix argument; you'll be prompted for the name of
-the file to use as well as the destination folder
+the FILE to use as well as the destination FOLDER
The hook `mh-inc-folder-hook' is run after incorporating new
-mail. Do not call this function from outside MH-E; use
-\\[mh-rmail] instead.
+mail.
-In a program optional argument MAILDROP-NAME specifies an
-alternate maildrop from the default. The optional argument FOLDER
-specifies where to incorporate mail instead of the default named
-by `mh-inbox'."
+Do not call this function from outside MH-E; use \\[mh-rmail]
+instead."
(interactive (list (if current-prefix-arg
(expand-file-name
(read-file-name "inc mail from file: "
((not (eq (current-buffer) (get-buffer folder)))
(switch-to-buffer folder)
(setq mh-previous-window-config config))))
- (mh-get-new-mail maildrop-name)
+ (mh-get-new-mail file)
(when (and threading-needed-flag
(save-excursion
(goto-char (point-min))
a) The folder name associated with the first address found in
the list `mh-default-folder-list' is used. Each element in
- this list contains a `Check Recipient' item. If this item is
+ this list contains a \"Check Recipient\" item. If this item is
turned on, then the address is checked against the recipient
instead of the sender. This is useful for mailing lists.
(defun mh-refile-or-write-again (range &optional interactive-flag)
"Repeat last output command.
-If you are refiling several messages into the same folder, you can use
-this command to repeat the last refile or write. You can use a range.
+If you are refiling several messages into the same folder, you
+can use this command to repeat the last
+refile (\\[mh-refile-msg]) or write (\\[mh-write-msg-to-file]).
+You can use a range.
Check the documentation of `mh-interactive-range' to see how RANGE is
read in interactive use.
(error "No previous refile or write"))
(cond ((eq (car mh-last-destination) 'refile)
(mh-refile-msg range (cdr mh-last-destination))
- (message "%s" (format "Destination folder: %s"
- (cdr mh-last-destination))))
+ (message "Destination folder: %s" (cdr mh-last-destination)))
(t
(mh-iterate-on-range msg range
(apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
many unread messages to skip."
(interactive "p")
(unless (> count 0)
- (error "The function mh-previous-unread-msg expects positive argument"))
+ (error "The function `mh-previous-unread-msg' expects positive argument"))
(setq count (1- count))
(let ((unread-sequence (cdr (assoc mh-unseen-seq mh-seq-list)))
(cur-msg (mh-get-msg-num nil)))
(when (consp part-index) (setq part-index (car part-index)))
(mh-folder-mime-action part-index #'mh-mime-save-part nil))
-(defvar mh-thread-scan-line-map-stack)
-
(defun mh-reset-threads-and-narrowing ()
"Reset all variables pertaining to threads and narrowing.
Also removes all content from the folder buffer."
mh-interpret-number-as-range-flag)
nil)))
(setq mh-next-direction 'forward)
- (let ((threaded-flag (memq 'unthread mh-view-ops)))
+ (let ((threaded-flag (memq 'unthread mh-view-ops))
+ (msg-num (mh-get-msg-num nil)))
(mh-scan-folder mh-current-folder (or range "all") dont-exec-pending)
+ ;; If there isn't a cur sequence, mh-scan-folder goes to the first message.
+ ;; Try to stay where we were.
+ (if (null (car (mh-seq-to-msgs 'cur)))
+ (mh-goto-msg msg-num t t))
(cond (threaded-flag (mh-toggle-threads))
(mh-index-data (mh-index-insert-folder-headers)))))
(append-to-file (point) (point-max) output-file))))
(defun mh-toggle-showing ()
- "Toggle the scanning mode/showing mode of displaying messages."
+ "Toggle between MH-Folder and MH-Folder Show modes.
+
+This command switches between MH-Folder mode and MH-Folder Show
+mode. MH-Folder mode turns off the associated show buffer so that
+you can perform operations on the messages quickly without
+reading them. This is an excellent way to prune out your junk
+mail or to refile a group of messages to another folder for later
+examination."
(interactive)
(if mh-showing-mode
(mh-set-scan-mode)
(if (not (mh-outstanding-commands-p))
(mh-set-folder-modified-p nil)))
-
(defun mh-folder-line-matches-show-buffer-p ()
"Return t if the message under point in folder-mode is in the show buffer.
Return nil in any other circumstance (no message under point, no
(values (format "+%s" folder) (car unseen) (car total))))))))
(defun mh-folder-size-folder (folder)
- "Find size of FOLDER using `folder'."
+ "Find size of FOLDER using \"folder\"."
(with-temp-buffer
(let ((u (length (cdr (assoc mh-unseen-seq
(mh-read-folder-sequences folder nil))))))
(values 0 u folder)))))
(defun mh-folder-size-flist (folder)
- "Find size of FOLDER using `flist'."
+ "Find size of FOLDER using \"flist\"."
(with-temp-buffer
(call-process (expand-file-name "flist" mh-progs) nil t nil "-showzero"
"-norecurse" folder "-sequence" (symbol-name mh-unseen-seq))
(setq mh-previous-window-config config)))
nil)
-
(defun mh-update-sequences ()
"Flush MH-E's state out to MH.
(beginning-of-line)
(setq message (mh-get-msg-num t)))
(if (looking-at mh-scan-refiled-msg-regexp)
- (error "Message %d is refiled. Undo refile before deleting" message))
+ (error "Message %d is refiled; undo refile before deleting" message))
(if (looking-at mh-scan-deleted-msg-regexp)
nil
(mh-set-folder-modified-p t)
(beginning-of-line)
(setq message (mh-get-msg-num t)))
(cond ((looking-at mh-scan-deleted-msg-regexp)
- (error "Message %d is deleted. Undo delete before moving" message))
+ (error "Message %d is deleted; undo delete before moving" message))
((looking-at mh-scan-refiled-msg-regexp)
(if (y-or-n-p
- (format "Message %d already refiled. Copy to %s as well? "
+ (format "Message %d already refiled; copy to %s as well? "
message folder))
(mh-exec-cmd "refile" (mh-get-msg-num t) "-link"
"-src" mh-current-folder
many unread messages to skip."
(interactive "p")
(unless (> count 0)
- (error "The function mh-next-unread-msg expects positive argument"))
+ (error "The function `mh-next-unread-msg' expects positive argument"))
(setq count (1- count))
(let ((unread-sequence (reverse (cdr (assoc mh-unseen-seq mh-seq-list))))
(cur-msg (mh-get-msg-num nil)))
["List Folders" mh-list-folders t]
["Visit a Folder..." mh-visit-folder t]
["View New Messages" mh-index-new-messages t]
- ["Search a Folder..." mh-search-folder t]
- ["Indexed Search..." mh-index-search t]
+ ["Search..." mh-search t]
"--"
["Quit MH-E" mh-quit t]))
onward while the latter is used in previous versions and XEmacs."
(if (boundp 'write-file-functions)
''write-file-functions ;Emacs 21.4
- ''local-write-file-hooks)) ;<Emacs 21.4, XEmacs
-
-;; Avoid compiler warnings in non-bleeding edge versions of Emacs.
-(eval-when-compile
- (defvar tool-bar-mode)
- (defvar tool-bar-map)
- (defvar desktop-save-buffer)) ;Emacs 21.4
+ ''local-write-file-hooks)) ;XEmacs
;; Register mh-folder-mode as supporting which-function-mode...
(load "which-func" t t)
(not (member 'mh-folder-mode which-func-modes)))
(push 'mh-folder-mode which-func-modes))
+;; Shush compiler.
+(eval-when-compile
+ (defvar desktop-save-buffer)
+ (defvar font-lock-auto-fontify))
+
(defvar mh-folder-buttons-init-flag nil)
;; Autoload cookie needed by desktop.el
Indicates all messages in the range <num1> to <num2>, inclusive.
The range must be nonempty.
-`<num>:N'
-`<num>:+N'
-`<num>:-N'
+<num>:N
+<num>:+N
+<num>:-N
Up to N messages beginning with (or ending with) message num. Num
may be any of the predefined symbols: first, prev, cur, next or
last.
-`first:N'
-`prev:N'
-`next:N'
-`last:N'
+first:N
+prev:N
+next:N
+last:N
The first, previous, next or last messages, if they exist.
-`all'
+all
All of the messages.
For example, a range that shows all of these things is `1 2 3
'mh-folder-view-stack () ; Stack of previous views of the
; folder.
'mh-index-data nil ; If the folder was created by a call
- ; to mh-index-search this contains info
+ ; to mh-search, this contains info
; about the search results.
- 'mh-index-previous-search nil ; Previous folder and search-regexp
+ 'mh-index-previous-search nil ; folder, indexer, search-regexp
'mh-index-msg-checksum-map nil ; msg -> checksum map
'mh-index-checksum-origin-map nil ; checksum -> ( orig-folder, orig-msg )
'mh-index-sequence-search-flag nil ; folder resulted from sequence search
(defun mh-colors-available-p ()
"Check if colors are available in the Emacs being used."
(or mh-xemacs-flag
- (let ((color-cells
- (or (ignore-errors (mh-funcall-if-exists display-color-cells))
- (ignore-errors (mh-funcall-if-exists
- x-display-color-cells)))))
+ (let ((color-cells (display-color-cells)))
(and (numberp color-cells) (>= color-cells 8)))))
(defun mh-colors-in-use-p ()
comes after that."
(if (eq mh-scan-format-file t)
(max (1+ width) 2)
- (error "%s %s" "Can't call mh-msg-num-width-to-column"
- "when mh-scan-format-file is not t")))
+ (error "%s %s" "Can't call `mh-msg-num-width-to-column' when"
+ "`mh-scan-format-file' is not set to \"Use MH-E scan Format\"")))
(defun mh-set-cmd-note (column)
"Set `mh-cmd-note' to COLUMN.
(mh-remove-sequence-notation msg nil t))
(clrhash mh-sequence-notation-history)))
-
(defun mh-goto-cur-msg (&optional minimal-changes-flag)
"Position the cursor at the current message.
When optional argument MINIMAL-CHANGES-FLAG is non-nil, the
(defalias 'mh-alt-send 'mh-send)
(defalias 'mh-alt-visit-folder 'mh-visit-folder)
-;; Save the `b' binding for a future `back'. Maybe?
+;; Save the "b" binding for a future `back'. Maybe?
(gnus-define-keys mh-folder-mode-map
" " mh-page-msg
"!" mh-refile-or-write-again
"S" mh-sort-folder
"c" mh-catchup
"f" mh-alt-visit-folder
- "i" mh-index-search
"k" mh-kill-folder
"l" mh-list-folders
"n" mh-index-new-messages
"p" mh-pack-folder
"q" mh-index-sequenced-messages
"r" mh-rescan-folder
- "s" mh-search-folder
+ "s" mh-search
"u" mh-undo-folder
"v" mh-visit-folder)
;;
;; When adding a new prefix, ensure that the help message contains "what" the
;; prefix is for. For example, if the word "folder" were not present in the
-;; `F' entry, it would not be clear what these commands operated upon.
+;; "F" entry, it would not be clear what these commands operated upon.
(defvar mh-help-messages
'((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n"
"[d]elete, [o]refile, e[x]ecute,\n"