Annotation of GNUtools/emacs/lisp/rmailsum.el, revision 1.1.1.1

1.1       root        1: ;; "RMAIL" mail reader for Emacs.
                      2: ;; Copyright (C) 1985 Free Software Foundation, Inc.
                      3: 
                      4: ;; This file is part of GNU Emacs.
                      5: 
                      6: ;; GNU Emacs is free software; you can redistribute it and/or modify
                      7: ;; it under the terms of the GNU General Public License as published by
                      8: ;; the Free Software Foundation; either version 1, or (at your option)
                      9: ;; any later version.
                     10: 
                     11: ;; GNU Emacs is distributed in the hope that it will be useful,
                     12: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: ;; GNU General Public License for more details.
                     15: 
                     16: ;; You should have received a copy of the GNU General Public License
                     17: ;; along with GNU Emacs; see the file COPYING.  If not, write to
                     18: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     19: 
                     20: 
                     21: ;; summary things
                     22: 
                     23: (defun rmail-summary ()
                     24:   "Display a summary of all messages, one line per message."
                     25:   (interactive)
                     26:   (rmail-new-summary "All" nil))
                     27: 
                     28: (defun rmail-summary-by-labels (labels)
                     29:   "Display a summary of all messages with one or more LABELS.
                     30: LABELS should be a string containing the desired labels, separated by commas."
                     31:   (interactive "sLabels to summarize by: ")
                     32:   (if (string= labels "")
                     33:       (setq labels (or rmail-last-multi-labels
                     34:                       (error "No label specified"))))
                     35:   (setq rmail-last-multi-labels labels)
                     36:   (rmail-new-summary (concat "labels " labels)
                     37:                     'rmail-message-labels-p
                     38:                     (concat ", \\(" (mail-comma-list-regexp labels) "\\),")))
                     39: 
                     40: (defun rmail-summary-by-recipients (recipients &optional primary-only)
                     41:   "Display a summary of all messages with the given RECIPIENTS.
                     42: Normally checks the To, From and Cc fields of headers;
                     43: but if PRIMARY-ONLY is non-nil (prefix arg given),
                     44:  only look in the To and From fields.
                     45: RECIPIENTS is a string of names separated by commas."
                     46:   (interactive "sRecipients to summarize by: \nP")
                     47:   (rmail-new-summary
                     48:    (concat "recipients " recipients)
                     49:    'rmail-message-recipients-p
                     50:    (mail-comma-list-regexp recipients) primary-only))
                     51: 
                     52: (defun rmail-message-recipients-p (msg recipients &optional primary-only)
                     53:   (save-restriction
                     54:     (goto-char (rmail-msgbeg msg))
                     55:     (search-forward "\n*** EOOH ***\n")
                     56:     (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
                     57:     (or (string-match recipients (or (mail-fetch-field "To") ""))
                     58:        (string-match recipients (or (mail-fetch-field "From") ""))
                     59:        (if (not primary-only)
                     60:            (string-match recipients (or (mail-fetch-field "Cc") ""))))))
                     61: 
                     62: (defun rmail-new-summary (description function &rest args)
                     63:   "Create a summary of selected messages.
                     64: DESCRIPTION makes part of the mode line of the summary buffer.
                     65: For each message, FUNCTION is applied to the message number and ARGS...
                     66: and if the result is non-nil, that message is included.
                     67: nil for FUNCTION means all messages."
                     68:   (message "Computing summary lines...")
                     69:   (or (and rmail-summary-buffer
                     70:           (buffer-name rmail-summary-buffer))
                     71:       (setq rmail-summary-buffer
                     72:            (generate-new-buffer (concat (buffer-name) "-summary"))))
                     73:   (let ((summary-msgs ())
                     74:        (new-summary-line-count 0))
                     75:     (let ((msgnum 1)
                     76:          (buffer-read-only nil))
                     77:       (save-restriction
                     78:        (save-excursion
                     79:          (widen)
                     80:          (goto-char (point-min))
                     81:          (while (>= rmail-total-messages msgnum)
                     82:            (if (or (null function)
                     83:                    (apply function (cons msgnum args)))
                     84:                (setq summary-msgs
                     85:                      (cons (rmail-make-summary-line msgnum)
                     86:                            summary-msgs)))
                     87:            (setq msgnum (1+ msgnum))))))
                     88:     (let ((sbuf rmail-summary-buffer)
                     89:          (rbuf (current-buffer))
                     90:          (total rmail-total-messages)
                     91:          (mesg rmail-current-message))
                     92:       (pop-to-buffer sbuf)
                     93:       (let ((buffer-read-only nil))
                     94:        (erase-buffer)
                     95:        (cond (summary-msgs
                     96:               (princ (nreverse summary-msgs) sbuf)
                     97:               (delete-char -1)
                     98:               (subst-char-in-region 1 2 ?\( ?\ ))))
                     99:       (setq buffer-read-only t)
                    100:       (goto-char (point-min))
                    101:       (rmail-summary-mode)
                    102:       (make-local-variable 'minor-mode-alist)
                    103:       (setq minor-mode-alist (list ": " description))
                    104:       (setq rmail-buffer rbuf
                    105:            rmail-total-messages total)
                    106:       (rmail-summary-goto-msg mesg t)))
                    107:   (message "Computing summary lines...done"))
                    108: 
                    109: (defun rmail-make-summary-line (msg)
                    110:   (let ((line (or (aref rmail-summary-vector (1- msg))
                    111:                  (progn
                    112:                    (setq new-summary-line-count
                    113:                          (1+ new-summary-line-count))
                    114:                    (if (zerop (% new-summary-line-count 10))
                    115:                        (message "Computing summary lines...%d"
                    116:                                 new-summary-line-count))
                    117:                    (rmail-make-summary-line-1 msg)))))
                    118:     ;; Fix up the part of the summary that says "deleted" or "unseen".
                    119:     (aset line 4
                    120:          (if (rmail-message-deleted-p msg) ?\D
                    121:            (if (= ?0 (char-after (+ 3 (rmail-msgbeg msg))))
                    122:                ?\- ?\ )))
                    123:     line))
                    124: 
                    125: (defun rmail-make-summary-line-1 (msg)
                    126:   (goto-char (rmail-msgbeg msg))
                    127:   (let* ((lim (save-excursion (forward-line 2) (point)))
                    128:         pos
                    129:         (labels
                    130:          (progn
                    131:            (forward-char 3)
                    132:            (concat
                    133: ;           (if (save-excursion (re-search-forward ",answered," lim t))
                    134: ;               "*" "")
                    135: ;           (if (save-excursion (re-search-forward ",filed," lim t))
                    136: ;               "!" "")
                    137:             (if (progn (search-forward ",,") (eolp))
                    138:                 ""
                    139:               (concat "{"
                    140:                       (buffer-substring (point)
                    141:                                         (progn (end-of-line) (point)))
                    142:                       "} ")))))
                    143:         (line
                    144:          (progn
                    145:            (forward-line 1)
                    146:            (if (looking-at "Summary-line: ")
                    147:                (progn
                    148:                  (goto-char (match-end 0))
                    149:                  (setq line
                    150:                        (buffer-substring (point)
                    151:                                          (progn (forward-line 1) (point)))))))))
                    152:     ;; Obsolete status lines lacking a # should be flushed.
                    153:     (and line
                    154:         (not (string-match "#" line))
                    155:         (progn
                    156:           (delete-region (point)
                    157:                          (progn (forward-line -1) (point)))
                    158:           (setq line nil)))
                    159:     ;; If we didn't get a valid status line from the message,
                    160:     ;; make a new one and put it in the message.
                    161:     (or line
                    162:        (let* ((case-fold-search t)
                    163:               (next (rmail-msgend msg))
                    164:               (beg (if (progn (goto-char (rmail-msgbeg msg))
                    165:                               (search-forward "\n*** EOOH ***\n" next t))
                    166:                        (point)
                    167:                      (forward-line 1)
                    168:                      (point)))
                    169:               (end (progn (search-forward "\n\n" nil t) (point))))
                    170:          (save-restriction
                    171:            (narrow-to-region beg end)
                    172:            (goto-char beg)
                    173:            (setq line (rmail-make-basic-summary-line)))
                    174:          (goto-char (rmail-msgbeg msg))
                    175:          (forward-line 2)
                    176:          (insert "Summary-line: " line)))
                    177:     (setq pos (string-match "#" line))
                    178:     (aset rmail-summary-vector (1- msg)
                    179:          (concat (format "%4d  " msg)
                    180:                  (substring line 0 pos)
                    181:                  labels
                    182:                  (substring line (1+ pos))))))
                    183: 
                    184: (defun rmail-make-basic-summary-line ()
                    185:   (goto-char (point-min))
                    186:   (concat (save-excursion
                    187:            (if (not (re-search-forward "^Date:" nil t))
                    188:                "      "
                    189:              (cond ((re-search-forward "\\([^0-9:]\\)\\([0-3]?[0-9]\\)\\([- \t_]+\\)\\([adfjmnos][aceopu][bcglnprtvy]\\)"
                    190:                      (save-excursion (end-of-line) (point)) t)
                    191:                     (format "%2d-%3s"
                    192:                             (string-to-int (buffer-substring
                    193:                                             (match-beginning 2)
                    194:                                             (match-end 2)))
                    195:                             (buffer-substring
                    196:                              (match-beginning 4) (match-end 4))))
                    197:                    ((re-search-forward "\\([^a-z]\\)\\([adfjmnos][acepou][bcglnprtvy]\\)\\([-a-z \t_]*\\)\\([0-9][0-9]?\\)"
                    198:                      (save-excursion (end-of-line) (point)) t)
                    199:                     (format "%2d-%3s"
                    200:                             (string-to-int (buffer-substring
                    201:                                             (match-beginning 4)
                    202:                                             (match-end 4)))
                    203:                             (buffer-substring
                    204:                              (match-beginning 2) (match-end 2))))
                    205:                    (t "??????"))))
                    206:          "  "
                    207:          (save-excursion
                    208:            (if (not (re-search-forward "^From:[ \t]*" nil t))
                    209:                "                         "
                    210:              (let* ((from (mail-strip-quoted-names
                    211:                            (buffer-substring
                    212:                             (1- (point))
                    213:                             (progn (end-of-line)
                    214:                                    (skip-chars-backward " \t")
                    215:                                    (point)))))
                    216:                     len mch lo)
                    217:                (if (string-match (concat "^"
                    218:                                          (regexp-quote (user-login-name))
                    219:                                          "\\($\\|@\\)")
                    220:                                  from)
                    221:                    (save-excursion
                    222:                      (goto-char (point-min))
                    223:                      (if (not (re-search-forward "^To:[ \t]*" nil t))
                    224:                          nil
                    225:                        (setq from
                    226:                              (concat "to: "
                    227:                                      (mail-strip-quoted-names
                    228:                                       (buffer-substring
                    229:                                        (point)
                    230:                                        (progn (end-of-line)
                    231:                                               (skip-chars-backward " \t")
                    232:                                               (point)))))))))
                    233:                (setq len (length from))
                    234:                (setq mch (string-match "[@%]" from))
                    235:                (format "%25s"
                    236:                        (if (or (not mch) (<= len 25))
                    237:                            (substring from (max 0 (- len 25)))
                    238:                          (substring from
                    239:                                     (setq lo (cond ((< (- mch 9) 0) 0)
                    240:                                                    ((< len (+ mch 16))
                    241:                                                     (- len 25))
                    242:                                                    (t (- mch 9))))
                    243:                                     (min len (+ lo 25))))))))
                    244:          "  #"
                    245:          (if (re-search-forward "^Subject:" nil t)
                    246:              (progn (skip-chars-forward " \t")
                    247:                     (buffer-substring (point)
                    248:                                       (progn (end-of-line)
                    249:                                              (point))))
                    250:            (re-search-forward "[\n][\n]+" nil t)
                    251:            (buffer-substring (point) (progn (end-of-line) (point))))
                    252:          "\n"))
                    253: 
                    254: (defun rmail-summary-next-all (&optional number)
                    255:   (interactive "p")
                    256:   (forward-line (if number number 1))
                    257:   (rmail-summary-goto-msg))
                    258: 
                    259: (defun rmail-summary-previous-all (&optional number)
                    260:   (interactive "p")
                    261:   (forward-line (- (if number number 1)))
                    262:   (rmail-summary-goto-msg))
                    263: 
                    264: (defun rmail-summary-next-msg (&optional number)
                    265:   (interactive "p")
                    266:   (forward-line 0)
                    267:   (and (> number 0) (forward-line 1))
                    268:   (let ((count (if (< number 0) (- number) number))
                    269:        (search (if (> number 0) 're-search-forward 're-search-backward))
                    270:        end)
                    271:     (while (and (> count 0) (funcall search "^.....[^D]" nil t))
                    272:       (setq count (1- count)))
                    273:     (rmail-summary-goto-msg)))
                    274: 
                    275: (defun rmail-summary-previous-msg (&optional number)
                    276:   (interactive "p")
                    277:   (rmail-summary-next-msg (- (if number number 1))))
                    278: 
                    279: (defun rmail-summary-delete-forward ()
                    280:   (interactive)
                    281:   (let (end)
                    282:     (rmail-summary-goto-msg)
                    283:     (pop-to-buffer rmail-buffer)
                    284:     (rmail-delete-message)
                    285:     (pop-to-buffer rmail-summary-buffer)
                    286:     (let ((buffer-read-only nil))
                    287:       (skip-chars-forward " ")
                    288:       (skip-chars-forward "[0-9]")
                    289:       (delete-char 1)
                    290:       (insert "D"))
                    291:     (rmail-summary-next-msg 1)))
                    292: 
                    293: (defun rmail-summary-undelete ()
                    294:   (interactive)
                    295:   (let ((buffer-read-only nil))
                    296:     (end-of-line)
                    297:     (cond ((re-search-backward "\\(^ *[0-9]*\\)\\(D\\)" nil t)
                    298:           (replace-match "\\1 ")
                    299:           (rmail-summary-goto-msg)
                    300:           (pop-to-buffer rmail-buffer)
                    301:           (and (rmail-message-deleted-p rmail-current-message)
                    302:                (rmail-undelete-previous-message))
                    303:           (pop-to-buffer rmail-summary-buffer))
                    304:          (t
                    305:           (rmail-summary-goto-msg)))))
                    306: 
                    307: ;; Rmail Summary mode is suitable only for specially formatted data.
                    308: (put 'rmail-summary-mode 'mode-class 'special)
                    309: 
                    310: (defun rmail-summary-mode ()
                    311:   "Major mode in effect in Rmail summary buffer.
                    312: A subset of the Rmail mode commands are supported in this mode. 
                    313: As commands are issued in the summary buffer the corresponding
                    314: mail message is displayed in the rmail buffer.
                    315: 
                    316: n       Move to next undeleted message, or arg messages.
                    317: p       Move to previous undeleted message, or arg messages.
                    318: C-n    Move to next, or forward arg messages.
                    319: C-p    Move to previous, or previous arg messages.
                    320: j       Jump to the message at the cursor location.
                    321: d       Delete the message at the cursor location and move to next message.
                    322: u      Undelete this or previous deleted message.
                    323: q      Quit Rmail.
                    324: x      Exit and kill the summary window.
                    325: space   Scroll message in other window forward.
                    326: delete  Scroll message backward.
                    327: 
                    328: Entering this mode calls value of hook variable rmail-summary-mode-hook."
                    329:   (interactive)
                    330:   (kill-all-local-variables)
                    331:   (make-local-variable 'rmail-buffer)
                    332:   (make-local-variable 'rmail-total-messages)
                    333:   (setq major-mode 'rmail-summary-mode)
                    334:   (setq mode-name "RMAIL Summary")
                    335:   (use-local-map rmail-summary-mode-map)
                    336:   (setq truncate-lines t)
                    337:   (setq buffer-read-only t)
                    338:   (set-syntax-table text-mode-syntax-table)
                    339:   (run-hooks 'rmail-summary-mode-hook))
                    340: 
                    341: (defun rmail-summary-goto-msg (&optional n nowarn)
                    342:   (interactive "P")
                    343:   (if (consp n) (setq n (prefix-numeric-value n)))
                    344:   (if (eobp) (forward-line -1))
                    345:   (beginning-of-line)
                    346:   (let ((buf rmail-buffer)
                    347:        (cur (point))
                    348:        (curmsg (string-to-int
                    349:                 (buffer-substring (point)
                    350:                                   (min (point-max) (+ 5 (point)))))))
                    351:     (if (not n)
                    352:        (setq n curmsg)
                    353:       (if (< n 1)
                    354:          (progn (message "No preceding message")
                    355:                 (setq n 1)))
                    356:       (if (> n rmail-total-messages)
                    357:          (progn (message "No following message")
                    358:                 (goto-char (point-max))
                    359:                 (rmail-summary-goto-msg)))
                    360:       (goto-char (point-min))
                    361:       (if (not (re-search-forward (concat "^ *" (int-to-string n)) nil t))
                    362:          (progn (or nowarn (message "Message %d not found" n))
                    363:                 (setq n curmsg)
                    364:                 (goto-char cur))))
                    365:     (beginning-of-line)
                    366:     (skip-chars-forward " ")
                    367:     (skip-chars-forward "0-9")
                    368:     (save-excursion (if (= (following-char) ?-)
                    369:                        (let ((buffer-read-only nil))
                    370:                          (delete-char 1)
                    371:                          (insert " "))))
                    372:     (beginning-of-line)
                    373:     (pop-to-buffer buf)
                    374:     (rmail-show-message n)
                    375:     (pop-to-buffer rmail-summary-buffer)))
                    376: 
                    377: (defvar rmail-summary-mode-map nil)
                    378: 
                    379: (if rmail-summary-mode-map
                    380:     nil
                    381:   (setq rmail-summary-mode-map (make-keymap))
                    382:   (suppress-keymap rmail-summary-mode-map)
                    383:   (define-key rmail-summary-mode-map "j" 'rmail-summary-goto-msg)
                    384:   (define-key rmail-summary-mode-map "n" 'rmail-summary-next-msg)
                    385:   (define-key rmail-summary-mode-map "p" 'rmail-summary-previous-msg)
                    386:   (define-key rmail-summary-mode-map "\C-n" 'rmail-summary-next-all)
                    387:   (define-key rmail-summary-mode-map "\C-p" 'rmail-summary-previous-all)
                    388:   (define-key rmail-summary-mode-map " " 'rmail-summary-scroll-msg-up)
                    389:   (define-key rmail-summary-mode-map "q" 'rmail-summary-quit)
                    390:   (define-key rmail-summary-mode-map "u" 'rmail-summary-undelete)
                    391:   (define-key rmail-summary-mode-map "x" 'rmail-summary-exit)
                    392:   (define-key rmail-summary-mode-map "\177" 'rmail-summary-scroll-msg-down)
                    393:   (define-key rmail-summary-mode-map "d" 'rmail-summary-delete-forward))
                    394: 
                    395: (defun rmail-summary-scroll-msg-up (&optional dist)
                    396:   "Scroll other window forward."
                    397:   (interactive "P")
                    398:   (let ((window (selected-window))
                    399:        (new-window (display-buffer rmail-buffer)))
                    400:     (unwind-protect
                    401:        (progn
                    402:          (select-window new-window)
                    403:          (scroll-up dist))
                    404:       (select-window window))))
                    405: 
                    406: (defun rmail-summary-scroll-msg-down (&optional dist)
                    407:   "Scroll other window backward."
                    408:   (interactive "P")
                    409:   (let ((window (selected-window))
                    410:        (new-window (display-buffer rmail-buffer)))
                    411:     (unwind-protect
                    412:        (progn
                    413:          (select-window new-window)
                    414:          (scroll-down dist))
                    415:       (select-window window))))
                    416: 
                    417: (defun rmail-summary-quit ()
                    418:   "Quit out of rmail and rmail summary."
                    419:   (interactive)
                    420:   (rmail-summary-exit)
                    421:   (rmail-quit))
                    422: 
                    423: (defun rmail-summary-exit ()
                    424:   "Exit rmail summary, remaining within rmail."
                    425:   (interactive)
                    426:   (bury-buffer (current-buffer))
                    427:   (if (get-buffer-window rmail-buffer)
                    428:       ;; Select the window with rmail in it, then delete this window.
                    429:       (select-window (prog1
                    430:                         (get-buffer-window rmail-buffer)
                    431:                       (delete-window (selected-window))))
                    432:     ;; Switch to the rmail buffer in this window.
                    433:     (switch-to-buffer rmail-buffer)))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.