|
|
1.1 ! root 1: ;; "RMAIL" mail reader for Emacs. ! 2: ;; Copyright (C) 1985, 1988 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: ;; Global to all RMAIL buffers. It exists primarily for the sake of ! 22: ;; completion. It is better to use strings with the label functions ! 23: ;; and let them worry about making the label. ! 24: ! 25: (defvar rmail-label-obarray (make-vector 47 0)) ! 26: ! 27: ;; Named list of symbols representing valid message attributes in RMAIL. ! 28: ! 29: (defconst rmail-attributes ! 30: (cons 'rmail-keywords ! 31: (mapcar '(lambda (s) (intern s rmail-label-obarray)) ! 32: '("deleted" "answered" "filed" "forwarded" "unseen" "edited")))) ! 33: ! 34: (defconst rmail-deleted-label (intern "deleted" rmail-label-obarray)) ! 35: ! 36: ;; Named list of symbols representing valid message keywords in RMAIL. ! 37: ! 38: (defvar rmail-keywords nil) ! 39: ! 40: (defun rmail-add-label (string) ! 41: "Add LABEL to labels associated with current RMAIL message. ! 42: Completion is performed over known labels when reading." ! 43: (interactive (list (rmail-read-label "Add label"))) ! 44: (rmail-set-label string t)) ! 45: ! 46: (defun rmail-kill-label (string) ! 47: "Remove LABEL from labels associated with current RMAIL message. ! 48: Completion is performed over known labels when reading." ! 49: (interactive (list (rmail-read-label "Remove label"))) ! 50: (rmail-set-label string nil)) ! 51: ! 52: (defun rmail-read-label (prompt) ! 53: (if (not rmail-keywords) (rmail-parse-file-keywords)) ! 54: (let ((result ! 55: (completing-read (concat prompt ! 56: (if rmail-last-label ! 57: (concat " (default " ! 58: (symbol-name rmail-last-label) ! 59: "): ") ! 60: ": ")) ! 61: rmail-label-obarray ! 62: nil ! 63: nil))) ! 64: (if (string= result "") ! 65: rmail-last-label ! 66: (setq rmail-last-label (rmail-make-label result t))))) ! 67: ! 68: (defun rmail-set-label (l state &optional n) ! 69: (rmail-maybe-set-message-counters) ! 70: (if (not n) (setq n rmail-current-message)) ! 71: (aset rmail-summary-vector (1- n) nil) ! 72: (let* ((attribute (rmail-attribute-p l)) ! 73: (keyword (and (not attribute) ! 74: (or (rmail-keyword-p l) ! 75: (rmail-install-keyword l)))) ! 76: (label (or attribute keyword))) ! 77: (if label ! 78: (let ((omax (- (buffer-size) (point-max))) ! 79: (omin (- (buffer-size) (point-min))) ! 80: (buffer-read-only nil) ! 81: (case-fold-search t)) ! 82: (unwind-protect ! 83: (save-excursion ! 84: (widen) ! 85: (goto-char (rmail-msgbeg n)) ! 86: (forward-line 1) ! 87: (if (not (looking-at "[01],")) ! 88: nil ! 89: (let ((start (1+ (point))) ! 90: (bound)) ! 91: (narrow-to-region (point) (progn (end-of-line) (point))) ! 92: (setq bound (point-max)) ! 93: (search-backward ",," nil t) ! 94: (if attribute ! 95: (setq bound (1+ (point))) ! 96: (setq start (1+ (point)))) ! 97: (goto-char start) ! 98: ; (while (re-search-forward "[ \t]*,[ \t]*" nil t) ! 99: ; (replace-match ",")) ! 100: ; (goto-char start) ! 101: (if (re-search-forward ! 102: (concat ", " (rmail-quote-label-name label) ",") ! 103: bound ! 104: 'move) ! 105: (if (not state) (replace-match ",")) ! 106: (if state (insert " " (symbol-name label) ","))) ! 107: (if (eq label rmail-deleted-label) ! 108: (rmail-set-message-deleted-p n state))))) ! 109: (narrow-to-region (- (buffer-size) omin) (- (buffer-size) omax)) ! 110: (if (= n rmail-current-message) (rmail-display-labels))))))) ! 111: ! 112: ;; Commented functions aren't used by RMAIL but might be nice for user ! 113: ;; packages that do stuff with RMAIL. Note that rmail-message-labels-p ! 114: ;; is in rmailsum now. ! 115: ! 116: ;(defun rmail-message-attribute-p (attribute &optional n) ! 117: ; "Returns t if ATTRIBUTE on NTH or current message." ! 118: ; (rmail-message-labels-p (rmail-make-label attribute t) n)) ! 119: ! 120: ;(defun rmail-message-keyword-p (keyword &optional n) ! 121: ; "Returns t if KEYWORD on NTH or current message." ! 122: ; (rmail-message-labels-p (rmail-make-label keyword t) n t)) ! 123: ! 124: ;(defun rmail-message-label-p (label &optional n) ! 125: ; "Returns symbol if LABEL (attribute or keyword) on NTH or current message." ! 126: ; (rmail-message-labels-p (rmail-make-label label t) n 'all)) ! 127: ! 128: ;; Not used by RMAIL but might be nice for user package. ! 129: ! 130: ;(defun rmail-parse-message-labels (&optional n) ! 131: ; "Returns labels associated with NTH or current RMAIL message. ! 132: ;Results is a list of two lists. The first is the message attributes ! 133: ;and the second is the message keywords. Labels are represented as symbols." ! 134: ; (let ((omin (- (buffer-size) (point-min))) ! 135: ; (omax (- (buffer-size) (point-max))) ! 136: ; (result)) ! 137: ; (unwind-protect ! 138: ; (save-excursion ! 139: ; (let ((beg (rmail-msgbeg (or n rmail-current-message)))) ! 140: ; (widen) ! 141: ; (goto-char beg) ! 142: ; (forward-line 1) ! 143: ; (if (looking-at "[01],") ! 144: ; (save-restriction ! 145: ; (narrow-to-region (point) (save-excursion (end-of-line) (point))) ! 146: ; (rmail-nuke-whitespace) ! 147: ; (goto-char (1+ (point-min))) ! 148: ; (list (mail-parse-comma-list) (mail-parse-comma-list)))))) ! 149: ; (narrow-to-region (- (buffer-size) omin) ! 150: ; (- (buffer-size) omax)) ! 151: ; nil))) ! 152: ! 153: (defun rmail-attribute-p (s) ! 154: (let ((symbol (rmail-make-label s))) ! 155: (if (memq symbol (cdr rmail-attributes)) symbol))) ! 156: ! 157: (defun rmail-keyword-p (s) ! 158: (let ((symbol (rmail-make-label s))) ! 159: (if (memq symbol (cdr (rmail-keywords))) symbol))) ! 160: ! 161: (defun rmail-make-label (s &optional forcep) ! 162: (cond ((symbolp s) s) ! 163: (forcep (intern (downcase s) rmail-label-obarray)) ! 164: (t (intern-soft (downcase s) rmail-label-obarray)))) ! 165: ! 166: (defun rmail-force-make-label (s) ! 167: (intern (downcase s) rmail-label-obarray)) ! 168: ! 169: (defun rmail-quote-label-name (label) ! 170: (regexp-quote (symbol-name (rmail-make-label label t)))) ! 171: ! 172: ;; Motion on messages with keywords. ! 173: ! 174: (defun rmail-previous-labeled-message (n label) ! 175: "Show previous message with LABEL. Defaults to last labels used. ! 176: With prefix argument N moves backward N messages with these labels." ! 177: (interactive "p\nsMove to previous msg with labels: ") ! 178: (rmail-next-labeled-message (- n) label)) ! 179: ! 180: (defun rmail-next-labeled-message (n labels) ! 181: "Show next message with LABEL. Defaults to last labels used. ! 182: With prefix argument N moves forward N messages with these labels." ! 183: (interactive "p\nsMove to next msg with labels: ") ! 184: (if (string= labels "") ! 185: (setq labels rmail-last-multi-labels)) ! 186: (or labels ! 187: (error "No labels to find have been specified previously")) ! 188: (setq rmail-last-multi-labels labels) ! 189: (rmail-maybe-set-message-counters) ! 190: (let ((lastwin rmail-current-message) ! 191: (current rmail-current-message) ! 192: (regexp (concat ", ?\\(" ! 193: (mail-comma-list-regexp labels) ! 194: "\\),"))) ! 195: (save-restriction ! 196: (widen) ! 197: (while (and (> n 0) (< current rmail-total-messages)) ! 198: (setq current (1+ current)) ! 199: (if (rmail-message-labels-p current regexp) ! 200: (setq lastwin current n (1- n)))) ! 201: (while (and (< n 0) (> current 1)) ! 202: (setq current (1- current)) ! 203: (if (rmail-message-labels-p current regexp) ! 204: (setq lastwin current n (1+ n))))) ! 205: (rmail-show-message lastwin) ! 206: (if (< n 0) ! 207: (message "No previous message with labels %s" labels)) ! 208: (if (> n 0) ! 209: (message "No following message with labels %s" labels)))) ! 210: ! 211: ;;; Manipulate the file's Labels option. ! 212: ! 213: ;; Return a list of symbols for all ! 214: ;; the keywords (labels) recorded in this file's Labels option. ! 215: (defun rmail-keywords () ! 216: (or rmail-keywords (rmail-parse-file-keywords))) ! 217: ! 218: ;; Set rmail-keywords to a list of symbols for all ! 219: ;; the keywords (labels) recorded in this file's Labels option. ! 220: (defun rmail-parse-file-keywords () ! 221: (save-restriction ! 222: (save-excursion ! 223: (widen) ! 224: (goto-char 1) ! 225: (setq rmail-keywords ! 226: (if (search-forward "\nLabels:" (rmail-msgbeg 1) t) ! 227: (progn ! 228: (narrow-to-region (point) (progn (end-of-line) (point))) ! 229: (goto-char (point-min)) ! 230: (cons 'rmail-keywords ! 231: (mapcar 'rmail-force-make-label ! 232: (mail-parse-comma-list))))))))) ! 233: ! 234: ;; Add WORD to the list in the file's Labels option. ! 235: ;; Any keyword used for the first time needs this done. ! 236: (defun rmail-install-keyword (word) ! 237: (let ((keyword (rmail-make-label word t)) ! 238: (keywords (rmail-keywords))) ! 239: (if (not (or (rmail-attribute-p keyword) ! 240: (rmail-keyword-p keyword))) ! 241: (let ((omin (- (buffer-size) (point-min))) ! 242: (omax (- (buffer-size) (point-max)))) ! 243: (unwind-protect ! 244: (save-excursion ! 245: (widen) ! 246: (goto-char 1) ! 247: (let ((case-fold-search t) ! 248: (buffer-read-only nil)) ! 249: (or (search-forward "\nLabels:" nil t) ! 250: (progn ! 251: (end-of-line) ! 252: (insert "\nLabels:"))) ! 253: (delete-region (point) (progn (end-of-line) (point))) ! 254: (setcdr keywords (cons keyword (cdr keywords))) ! 255: (while (setq keywords (cdr keywords)) ! 256: (insert (symbol-name (car keywords)) ",")) ! 257: (delete-char -1))) ! 258: (narrow-to-region (- (buffer-size) omin) ! 259: (- (buffer-size) omax))))) ! 260: keyword))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.