summaryrefslogtreecommitdiff
path: root/lisp/mh-e/mh-scan.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/mh-e/mh-scan.el')
-rw-r--r--lisp/mh-e/mh-scan.el490
1 files changed, 490 insertions, 0 deletions
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
new file mode 100644
index 00000000000..b52f2b4eeb8
--- /dev/null
+++ b/lisp/mh-e/mh-scan.el
@@ -0,0 +1,490 @@
+;;; mh-scan.el --- MH-E scan line constants and utilities
+
+;; Copyright (C) 1993, 1995, 1997,
+;; 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file contains constants and a few functions for interpreting
+;; scan lines.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+
+
+
+;;; Scan Formats
+
+;; The following scan formats are passed to the scan program if the setting of
+;; `mh-scan-format-file' is t. They are identical except the later one makes
+;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
+;; want to change the column of the notations, use the `mh-set-cmd-note'
+;; function.
+
+(defvar mh-scan-format-mh
+ (concat
+ "%4(msg)"
+ "%<(cur)+%| %>"
+ "%<{replied}-"
+ "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
+ "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
+ "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
+ "%?(nonnull(comp{newsgroups}))n%>"
+ "%<(zero) %>"
+ "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
+ "%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>"
+ "%<(zero)%17(friendly{from})%> "
+ "%{subject}%<{body}<<%{body}%>")
+ "*Scan format string for MH.
+This string is passed to the scan program via the -format
+argument. This format is identical to the default except that
+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 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
+non-empty Newsgroups: header is present.")
+
+(defvar mh-scan-format-nmh
+ (concat
+ "%4(msg)"
+ "%<(cur)+%| %>"
+ "%<{replied}-"
+ "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
+ "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
+ "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
+ "%?(nonnull(comp{newsgroups}))n%>"
+ "%<(zero) %>"
+ "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
+ "%<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>"
+ "%<(zero)%17(decode(friendly{from}))%> "
+ "%(decode{subject})%<{body}<<%{body}%>")
+ "*Scan format string for nmh.
+This string is passed to the scan program via the -format arg.
+This format is identical to the default except that 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 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
+non-empty Newsgroups: field is present.")
+
+
+
+;;; Regular Expressions
+
+;; Alphabetical.
+
+(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
+ "This regular expression matches the message body fragment.
+
+Note that the default setting of `mh-folder-font-lock-keywords'
+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 with the
+face `mh-folder-body'.")
+
+(defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*"
+ "This regular expression matches the current message.
+
+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 one parenthesized expression which
+matches the message number as in the default of
+
+ \"^\\\\( *[0-9]+\\\\+\\\\).*\".
+
+This expression includes the leading space and current message
+marker \"+\" within the parenthesis since it looks better to
+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.
+
+It must not be anchored to the beginning or the end of the line.
+Note that the default setting of `mh-folder-font-lock-keywords'
+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 with the face
+`mh-folder-date'.")
+
+(defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D"
+ "This regular expression matches deleted messages.
+
+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 one parenthesized expression which
+matches the message number as in the default of
+
+ \"^\\\\( *[0-9]+\\\\)D\".
+
+This expression includes the leading space within the parenthesis
+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'.")
+
+(defvar mh-scan-good-msg-regexp "^\\( *[0-9]+\\)[^D^0-9]"
+ "This regular expression matches \"good\" messages.
+
+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 one parenthesized expression which
+matches the message number as in the default of
+
+ \"^\\\\( *[0-9]+\\\\)[^D^0-9]\".
+
+This expression includes the leading space within the parenthesis
+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.")
+
+(defvar mh-scan-msg-format-regexp "%\\([0-9]*\\)(msg)"
+ "This regular expression finds the message number width in a scan format.
+
+Note that the message number must be placed in a parenthesized
+expression as in the default of \"%\\\\([0-9]*\\\\)(msg)\". This
+variable is only consulted if `mh-scan-format-file' is set to
+\"Use MH-E scan Format\".")
+
+(defvar mh-scan-msg-format-string "%d"
+ "This is a format string for width of the message number in a scan format.
+
+Use \"0%d\" for zero-filled message numbers. This variable is only
+consulted if `mh-scan-format-file' is set to \"Use MH-E scan
+Format\".")
+
+(defvar mh-scan-msg-number-regexp "^ *\\([0-9]+\\)"
+ "This regular expression extracts the message number.
+
+It must match from the beginning of the line. Note that the
+message number must be placed in a parenthesized expression as in
+the default of \"^ *\\\\([0-9]+\\\\)\".")
+
+(defvar mh-scan-msg-overflow-regexp "^[?0-9][0-9]"
+ "This regular expression matches overflowed message numbers.")
+
+(defvar mh-scan-msg-search-regexp "^[^0-9]*%d[^0-9]"
+ "This regular expression matches a particular message.
+
+It is a format string; use \"%d\" to represent the location of the
+message number within the expression as in the default of
+\"^[^0-9]*%d[^0-9]\".")
+
+(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
+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 \"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-refiled-msg-regexp "^\\( *[0-9]+\\)\\^"
+ "This regular expression matches refiled messages.
+
+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 one parenthesized expression which
+matches the message number as in the default of
+
+ \"^\\\\( *[0-9]+\\\\)\\\\^\".
+
+This expression includes the leading space within the parenthesis
+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'.")
+
+(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 two parenthesized
+expressions. The first should match the fontification hint (see
+`mh-scan-format-nmh') and the second should match the user name
+as in the default of
+
+ ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\)
+
+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'.")
+
+(defvar mh-scan-subject-regexp
+ "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
+ "This regular expression matches the subject.
+
+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, 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-*\\\\)*
+ \\\\([^<\\n]*\\\\)
+
+This regular expression should be correct as it is needed by
+non-fontification functions.")
+
+(defvar mh-scan-valid-regexp "^ *[0-9]"
+ "This regular expression describes a valid scan line.
+
+This is used to eliminate error messages that are occasionally
+produced by \"inc\".")
+
+
+
+;;; Widths, Offsets and Columns
+
+(defvar mh-cmd-note 4
+ "Column for notations.
+
+This variable should be set with the function `mh-set-cmd-note'.
+This variable may be updated dynamically if
+`mh-adaptive-cmd-note-flag' is on.
+
+Note that columns in Emacs start with 0.")
+(make-variable-buffer-local 'mh-cmd-note)
+
+(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,
+
+ \"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\"
+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.")
+
+(defvar mh-scan-date-width 5
+ "Number of columns consumed by the date field in `mh-scan-format'.
+This column will typically be of the form mm/dd.")
+
+(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
+missing dates.")
+
+(defvar mh-scan-from-mbox-width 17
+ "Number of columns consumed with the \"From:\" line in `mh-scan-format'.
+This column will have a friendly name or e-mail address of the
+originator, or a \"To: address\" for outgoing e-mail messages.")
+
+(defvar mh-scan-from-mbox-sep-width 2
+ "Number of columns consumed by whitespace after from-mbox in `mh-scan-format'.
+This column will only ever have spaces in it.")
+
+(defvar mh-scan-field-destination-offset
+ (+ mh-scan-cmd-note-width)
+ "The offset from the `mh-cmd-note' for the destination column.")
+
+(defvar mh-scan-field-from-start-offset
+ (+ mh-scan-cmd-note-width
+ mh-scan-destination-width
+ mh-scan-date-width
+ mh-scan-date-flag-width)
+ "The offset from the `mh-cmd-note' to find the start of \"From:\" address.")
+
+(defvar mh-scan-field-from-end-offset
+ (+ mh-scan-field-from-start-offset mh-scan-from-mbox-width)
+ "The offset from the `mh-cmd-note' to find the end of \"From:\" address.")
+
+(defvar mh-scan-field-subject-start-offset
+ (+ mh-scan-cmd-note-width
+ mh-scan-destination-width
+ mh-scan-date-width
+ mh-scan-date-flag-width
+ mh-scan-from-mbox-width
+ mh-scan-from-mbox-sep-width)
+ "The offset from the `mh-cmd-note' to find the start of the subject.")
+
+
+
+;;; Notation
+
+;; Alphabetical.
+
+(defvar mh-note-cur ?+
+ "The current message (in MH, not in MH-E) is marked by this character.
+See also `mh-scan-cur-msg-number-regexp'.")
+
+(defvar mh-note-copied "C"
+ "Messages that have been copied are marked by this character.")
+
+(defvar mh-note-deleted ?D
+ "Messages that have been deleted are marked by this character.
+See also `mh-scan-deleted-msg-regexp'.")
+
+(defvar mh-note-dist ?R
+ "Messages that have been redistributed are marked by this character.")
+
+(defvar mh-note-forw ?F
+ "Messages that have been forwarded are marked by this character.")
+
+(defvar mh-note-printed "P"
+ "Messages that have been printed are marked by this character.")
+
+(defvar mh-note-refiled ?^
+ "Messages that have been refiled are marked by this character.
+See also `mh-scan-refiled-msg-regexp'.")
+
+(defvar mh-note-repl ?-
+ "Messages that have been replied to are marked by this character.")
+
+(defvar mh-note-seq ?%
+ "Messages in a user-defined sequence are marked by this character.
+
+Messages in the \"search\" sequence are marked by this character as
+well.")
+
+
+
+;;; Utilities
+
+;;;###mh-autoload
+(defun mh-scan-msg-number-regexp ()
+ "Return value of variable `mh-scan-msg-number-regexp'."
+ mh-scan-msg-number-regexp)
+
+;;;###mh-autoload
+(defun mh-scan-msg-search-regexp ()
+ "Return value of variable `mh-scan-msg-search-regexp'."
+ mh-scan-msg-search-regexp)
+
+;;;###mh-autoload
+(defun mh-set-cmd-note (column)
+ "Set `mh-cmd-note' to COLUMN.
+Note that columns in Emacs start with 0."
+ (setq mh-cmd-note column))
+
+;;;###mh-autoload
+(defun mh-scan-format ()
+ "Return the output format argument for the scan program."
+ (if (equal mh-scan-format-file t)
+ (list "-format" (if (mh-variant-p 'nmh 'mu-mh)
+ (list (mh-update-scan-format
+ mh-scan-format-nmh mh-cmd-note))
+ (list (mh-update-scan-format
+ mh-scan-format-mh mh-cmd-note))))
+ (if (not (equal mh-scan-format-file nil))
+ (list "-form" mh-scan-format-file))))
+
+(defun mh-update-scan-format (fmt width)
+ "Return a scan format with the (msg) width in the FMT replaced with WIDTH.
+
+The message number width portion of the format is discovered
+using `mh-scan-msg-format-regexp'. Its replacement is controlled
+with `mh-scan-msg-format-string'."
+ (or (and
+ (string-match mh-scan-msg-format-regexp fmt)
+ (let ((begin (match-beginning 1))
+ (end (match-end 1)))
+ (concat (substring fmt 0 begin)
+ (format mh-scan-msg-format-string width)
+ (substring fmt end))))
+ fmt))
+
+;;;###mh-autoload
+(defun mh-msg-num-width (folder)
+ "Return the width of the largest message number in this FOLDER."
+ (or mh-progs (mh-find-path))
+ (let ((tmp-buffer (get-buffer-create mh-temp-buffer))
+ (width 0))
+ (save-excursion
+ (set-buffer tmp-buffer)
+ (erase-buffer)
+ (apply 'call-process
+ (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
+ (list folder "last" "-format" "%(msg)"))
+ (goto-char (point-min))
+ (if (re-search-forward mh-scan-msg-number-regexp nil 0 1)
+ (setq width (length (buffer-substring
+ (match-beginning 1) (match-end 1))))))
+ width))
+
+;;;###mh-autoload
+(defun mh-msg-num-width-to-column (width)
+ "Return the column for notations given message number WIDTH.
+Note that columns in Emacs start with 0.
+
+If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this
+means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are
+in use. This function therefore assumes that the first column is
+empty (to provide room for the cursor), the following WIDTH
+columns contain the message number, and the column for notations
+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 set to \"Use MH-E scan Format\"")))
+
+(provide 'mh-scan)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;;; mh-scan.el ends here