diff options
| author | Jeffrey C Honig | 2012-11-24 21:21:02 -0500 |
|---|---|---|
| committer | Jeffrey C Honig | 2012-11-24 21:21:02 -0500 |
| commit | 855c6482c077b22383f8ad4b29db2d091e7e83f4 (patch) | |
| tree | ca83f6e6432acdc3e94fe6d73ccfd968fc77752f | |
| parent | 624d4a5cfbc96febb046c9acd7019ffbe2a977ab (diff) | |
| download | emacs-855c6482c077b22383f8ad4b29db2d091e7e83f4.tar.gz emacs-855c6482c077b22383f8ad4b29db2d091e7e83f4.zip | |
(mh-edit-again): Use the components file to specify
default values for missing headers in the draft.
(mh-regexp-in-field-syntax-table, mh-fcc-syntax-table)
(mh-addr-syntax-table, mh-regexp-in-field-p): Use a syntax table
so we'll properly parse non-address fields.
(mh-components-to-list, mh-extract-header-field): New functions to
read components file.
(mh-find-components, mh-send-sub): Move code to locate components
file into a new function.
(mh-insert-auto-fields, mh-modify-header-field): New syntax for
calling mh-regexp-in-field-p.
(closes SF #1708292)
| -rw-r--r-- | lisp/mh-e/ChangeLog | 15 | ||||
| -rw-r--r-- | lisp/mh-e/mh-comp.el | 174 |
2 files changed, 162 insertions, 27 deletions
diff --git a/lisp/mh-e/ChangeLog b/lisp/mh-e/ChangeLog index 6b2086eff3b..8bb1659a1c0 100644 --- a/lisp/mh-e/ChangeLog +++ b/lisp/mh-e/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2012-11-25 Jeffrey C Honig <jch@honig.net> | ||
| 2 | |||
| 3 | * mh-comp.el: (mh-edit-again): Use the components file to specify | ||
| 4 | default values for missing headers in the draft. | ||
| 5 | (mh-regexp-in-field-syntax-table, mh-fcc-syntax-table) | ||
| 6 | (mh-addr-syntax-table, mh-regexp-in-field-p): Use a syntax table | ||
| 7 | so we'll properly parse non-address fields. | ||
| 8 | (mh-components-to-list, mh-extract-header-field): New functions to | ||
| 9 | read components file. | ||
| 10 | (mh-find-components, mh-send-sub): Move code to locate components | ||
| 11 | file into a new function. | ||
| 12 | (mh-insert-auto-fields, mh-modify-header-field): New syntax for | ||
| 13 | calling mh-regexp-in-field-p. | ||
| 14 | (closes SF #1708292) | ||
| 15 | |||
| 1 | 2012-01-07 Jeffrey C Honig <jch@honig.net> | 16 | 2012-01-07 Jeffrey C Honig <jch@honig.net> |
| 2 | 17 | ||
| 3 | * mh-e.el (mh-invisible-header-fields-internal): Added: X-xsi. | 18 | * mh-e.el (mh-invisible-header-fields-internal): Added: X-xsi. |
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el index eceb7a5fe3a..f7a610e6c58 100644 --- a/lisp/mh-e/mh-comp.el +++ b/lisp/mh-e/mh-comp.el | |||
| @@ -121,6 +121,42 @@ Used by the \\[mh-edit-again] and \\[mh-extract-rejected-mail] commands.") | |||
| 121 | syntax-table) | 121 | syntax-table) |
| 122 | "Syntax table used by MH-E while in MH-Letter mode.") | 122 | "Syntax table used by MH-E while in MH-Letter mode.") |
| 123 | 123 | ||
| 124 | (defvar mh-regexp-in-field-syntax-table nil | ||
| 125 | "Specify a syntax table for mh-regexp-in-field-p to use instead of determining") | ||
| 126 | |||
| 127 | (defvar mh-fcc-syntax-table | ||
| 128 | (let ((syntax-table (make-syntax-table text-mode-syntax-table))) | ||
| 129 | (modify-syntax-entry ?+ "w" syntax-table) | ||
| 130 | (modify-syntax-entry ?/ "w" syntax-table) | ||
| 131 | syntax-table) | ||
| 132 | "Syntax table used by MH-E while searching an Fcc field.") | ||
| 133 | |||
| 134 | (defvar mh-addr-syntax-table | ||
| 135 | (let ((syntax-table (make-syntax-table text-mode-syntax-table))) | ||
| 136 | (modify-syntax-entry ?! "w" syntax-table) | ||
| 137 | (modify-syntax-entry ?# "w" syntax-table) | ||
| 138 | (modify-syntax-entry ?$ "w" syntax-table) | ||
| 139 | (modify-syntax-entry ?% "w" syntax-table) | ||
| 140 | (modify-syntax-entry ?& "w" syntax-table) | ||
| 141 | (modify-syntax-entry ?' "w" syntax-table) | ||
| 142 | (modify-syntax-entry ?* "w" syntax-table) | ||
| 143 | (modify-syntax-entry ?+ "w" syntax-table) | ||
| 144 | (modify-syntax-entry ?- "w" syntax-table) | ||
| 145 | (modify-syntax-entry ?/ "w" syntax-table) | ||
| 146 | (modify-syntax-entry ?= "w" syntax-table) | ||
| 147 | (modify-syntax-entry ?? "w" syntax-table) | ||
| 148 | (modify-syntax-entry ?^ "w" syntax-table) | ||
| 149 | (modify-syntax-entry ?_ "w" syntax-table) | ||
| 150 | (modify-syntax-entry ?` "w" syntax-table) | ||
| 151 | (modify-syntax-entry ?{ "w" syntax-table) | ||
| 152 | (modify-syntax-entry ?| "w" syntax-table) | ||
| 153 | (modify-syntax-entry ?} "w" syntax-table) | ||
| 154 | (modify-syntax-entry ?~ "w" syntax-table) | ||
| 155 | (modify-syntax-entry ?. "w" syntax-table) | ||
| 156 | (modify-syntax-entry ?@ "w" syntax-table) | ||
| 157 | syntax-table) | ||
| 158 | "Syntax table used by MH-E while searching an address field.") | ||
| 159 | |||
| 124 | (defvar mh-send-args "" | 160 | (defvar mh-send-args "" |
| 125 | "Extra args to pass to \"send\" command.") | 161 | "Extra args to pass to \"send\" command.") |
| 126 | 162 | ||
| @@ -391,6 +427,42 @@ See also `mh-send'." | |||
| 391 | (mh-read-draft "clean-up" (mh-msg-filename message) nil))))) | 427 | (mh-read-draft "clean-up" (mh-msg-filename message) nil))))) |
| 392 | (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil) | 428 | (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil) |
| 393 | (mh-insert-header-separator) | 429 | (mh-insert-header-separator) |
| 430 | ;; Merge in components | ||
| 431 | (mh-mapc (function (lambda (header-field) | ||
| 432 | (let ((field (car header-field)) | ||
| 433 | (value (cdr header-field)) | ||
| 434 | (case-fold-search t)) | ||
| 435 | (cond | ||
| 436 | ;; Address field | ||
| 437 | ((string-match field "^To$\\|^Cc$\\|^From$") | ||
| 438 | (cond | ||
| 439 | ((not (mh-goto-header-field (concat field ":"))) | ||
| 440 | ;; Header field does not exist, add it | ||
| 441 | (mh-goto-header-end 0) | ||
| 442 | (insert field ": " value "\n")) | ||
| 443 | ((string-equal value "") | ||
| 444 | ;; Header field already exists and no value | ||
| 445 | ) | ||
| 446 | (t | ||
| 447 | ;; Header field exists and we have a value | ||
| 448 | (let (address mailbox (alias (mh-alias-expand value))) | ||
| 449 | (and alias | ||
| 450 | (setq address (ietf-drums-parse-address alias)) | ||
| 451 | (setq mailbox (car address))) | ||
| 452 | ;; XXX - Need to parse all addresses out of field | ||
| 453 | (if (and | ||
| 454 | (not (mh-regexp-in-field-p (concat "\\b" (regexp-quote value) "\\b") field)) | ||
| 455 | mailbox | ||
| 456 | (not (mh-regexp-in-field-p (concat "\\b" (regexp-quote mailbox) "\\b") field))) | ||
| 457 | (insert " " value ",")) | ||
| 458 | )))) | ||
| 459 | ((string-match field "^Fcc$") | ||
| 460 | ;; Folder reference | ||
| 461 | (mh-modify-header-field field value)) | ||
| 462 | ;; Text field, that's an easy case | ||
| 463 | (t | ||
| 464 | (mh-modify-header-field field value)))))) | ||
| 465 | (mh-components-to-list (mh-find-components))) | ||
| 394 | (goto-char (point-min)) | 466 | (goto-char (point-min)) |
| 395 | (save-buffer) | 467 | (save-buffer) |
| 396 | (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil | 468 | (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil |
| @@ -398,6 +470,34 @@ See also `mh-send'." | |||
| 398 | (mh-letter-mode-message) | 470 | (mh-letter-mode-message) |
| 399 | (mh-letter-adjust-point))) | 471 | (mh-letter-adjust-point))) |
| 400 | 472 | ||
| 473 | (defun mh-extract-header-field () | ||
| 474 | "Extract field name and field value from the field at point. | ||
| 475 | Returns a list of field name and value (which may be null)." | ||
| 476 | (let ((end (save-excursion (mh-header-field-end) | ||
| 477 | (point)))) | ||
| 478 | (if (looking-at mh-letter-header-field-regexp) | ||
| 479 | (save-excursion | ||
| 480 | (goto-char (match-end 1)) | ||
| 481 | (forward-char 1) | ||
| 482 | (skip-chars-forward " \t") | ||
| 483 | (cons (match-string-no-properties 1) (buffer-substring-no-properties (point) end)))))) | ||
| 484 | |||
| 485 | |||
| 486 | (defun mh-components-to-list (components) | ||
| 487 | "Read in the components file and convert to a list of field names and values." | ||
| 488 | (with-current-buffer (get-buffer-create mh-temp-buffer) | ||
| 489 | (erase-buffer) | ||
| 490 | (insert-file-contents components) | ||
| 491 | (goto-char (point-min)) | ||
| 492 | (let | ||
| 493 | ((header-fields nil)) | ||
| 494 | (while (mh-in-header-p) | ||
| 495 | (setq header-fields (append header-fields (list (mh-extract-header-field)))) | ||
| 496 | (mh-header-field-end) | ||
| 497 | (forward-char 1) | ||
| 498 | ) | ||
| 499 | header-fields))) | ||
| 500 | |||
| 401 | ;;;###mh-autoload | 501 | ;;;###mh-autoload |
| 402 | (defun mh-extract-rejected-mail (message) | 502 | (defun mh-extract-rejected-mail (message) |
| 403 | "Edit a MESSAGE that was returned by the mail system. | 503 | "Edit a MESSAGE that was returned by the mail system. |
| @@ -773,6 +873,22 @@ Optional argument BUFFER can be used to specify the buffer." | |||
| 773 | (t | 873 | (t |
| 774 | nil)))) | 874 | nil)))) |
| 775 | 875 | ||
| 876 | (defun mh-find-components () | ||
| 877 | "Return the path to the components file." | ||
| 878 | (let (components) | ||
| 879 | (cond | ||
| 880 | ((file-exists-p | ||
| 881 | (setq components | ||
| 882 | (expand-file-name mh-comp-formfile mh-user-path))) | ||
| 883 | components) | ||
| 884 | ((file-exists-p | ||
| 885 | (setq components | ||
| 886 | (expand-file-name mh-comp-formfile mh-lib))) | ||
| 887 | components) | ||
| 888 | (t | ||
| 889 | (error "Can't find %s in %s or %s" | ||
| 890 | mh-comp-formfile mh-user-path mh-lib))))) | ||
| 891 | |||
| 776 | (defun mh-send-sub (to cc subject config) | 892 | (defun mh-send-sub (to cc subject config) |
| 777 | "Do the real work of composing and sending a letter. | 893 | "Do the real work of composing and sending a letter. |
| 778 | Expects the TO, CC, and SUBJECT fields as arguments. | 894 | Expects the TO, CC, and SUBJECT fields as arguments. |
| @@ -782,19 +898,7 @@ CONFIG is the window configuration before sending mail." | |||
| 782 | (message "Composing a message...") | 898 | (message "Composing a message...") |
| 783 | (let ((draft (mh-read-draft | 899 | (let ((draft (mh-read-draft |
| 784 | "message" | 900 | "message" |
| 785 | (let (components) | 901 | (mh-find-components) |
| 786 | (cond | ||
| 787 | ((file-exists-p | ||
| 788 | (setq components | ||
| 789 | (expand-file-name mh-comp-formfile mh-user-path))) | ||
| 790 | components) | ||
| 791 | ((file-exists-p | ||
| 792 | (setq components | ||
| 793 | (expand-file-name mh-comp-formfile mh-lib))) | ||
| 794 | components) | ||
| 795 | (t | ||
| 796 | (error "Can't find %s in %s or %s" | ||
| 797 | mh-comp-formfile mh-user-path mh-lib)))) | ||
| 798 | nil))) | 902 | nil))) |
| 799 | (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc) | 903 | (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc) |
| 800 | (goto-char (point-max)) | 904 | (goto-char (point-max)) |
| @@ -1036,7 +1140,7 @@ added; otherwise return nil." | |||
| 1036 | (while list | 1140 | (while list |
| 1037 | (let ((regexp (nth 0 (car list))) | 1141 | (let ((regexp (nth 0 (car list))) |
| 1038 | (entries (nth 1 (car list)))) | 1142 | (entries (nth 1 (car list)))) |
| 1039 | (when (mh-regexp-in-field-p regexp "To:" "cc:") | 1143 | (when (mh-regexp-in-field-p regexp mh-addr-syntax-table "To:" "cc:") |
| 1040 | (setq mh-insert-auto-fields-done-local t) | 1144 | (setq mh-insert-auto-fields-done-local t) |
| 1041 | (setq fields-inserted t) | 1145 | (setq fields-inserted t) |
| 1042 | (if (not non-interactive) | 1146 | (if (not non-interactive) |
| @@ -1071,7 +1175,7 @@ discarded." | |||
| 1071 | (insert " " value) | 1175 | (insert " " value) |
| 1072 | (delete-region (point) (mh-line-end-position))) | 1176 | (delete-region (point) (mh-line-end-position))) |
| 1073 | ((and (not overwrite-flag) | 1177 | ((and (not overwrite-flag) |
| 1074 | (mh-regexp-in-field-p (concat "\\b" value "\\b") field)) | 1178 | (mh-regexp-in-field-p (concat "\\b" (regexp-quote value) "\\b") field)) |
| 1075 | ;; Already there, do nothing. | 1179 | ;; Already there, do nothing. |
| 1076 | ) | 1180 | ) |
| 1077 | ((and (not overwrite-flag) | 1181 | ((and (not overwrite-flag) |
| @@ -1083,18 +1187,34 @@ discarded." | |||
| 1083 | 1187 | ||
| 1084 | (defun mh-regexp-in-field-p (regexp &rest fields) | 1188 | (defun mh-regexp-in-field-p (regexp &rest fields) |
| 1085 | "Non-nil means REGEXP was found in FIELDS." | 1189 | "Non-nil means REGEXP was found in FIELDS." |
| 1086 | (save-excursion | 1190 | (let ((old-syntax-table (syntax-table))) |
| 1087 | (let ((search-result nil) | 1191 | (unwind-protect |
| 1088 | (field)) | 1192 | (save-excursion |
| 1089 | (while fields | 1193 | (let ((search-result nil) |
| 1090 | (setq field (car fields)) | 1194 | (field)) |
| 1091 | (if (and (mh-goto-header-field field) | 1195 | (while fields |
| 1092 | (re-search-forward | 1196 | (let ((field (car fields)) |
| 1093 | regexp (save-excursion (mh-header-field-end)(point)) t)) | 1197 | (syntax-table mh-regexp-in-field-syntax-table)) |
| 1094 | (setq fields nil | 1198 | (if (null syntax-table) |
| 1095 | search-result t) | 1199 | (let ((case-fold-search t)) |
| 1096 | (setq fields (cdr fields)))) | 1200 | (cond |
| 1097 | search-result))) | 1201 | ((string-match field "^To$\\|^[BD]?cc$\\|^From$") |
| 1202 | (setq syntax-table mh-addr-syntax-table)) | ||
| 1203 | ((string-match field "^Fcc$") | ||
| 1204 | (setq syntax-table mh-fcc-syntax-table)) | ||
| 1205 | (t | ||
| 1206 | (setq syntax-table (syntax-table))) | ||
| 1207 | ))) | ||
| 1208 | (if (and (mh-goto-header-field field) | ||
| 1209 | (set-syntax-table syntax-table) | ||
| 1210 | (re-search-forward | ||
| 1211 | regexp (save-excursion (mh-header-field-end)(point)) t)) | ||
| 1212 | (setq fields nil | ||
| 1213 | search-result t) | ||
| 1214 | (setq fields (cdr fields))) | ||
| 1215 | (set-syntax-table old-syntax-table))) | ||
| 1216 | search-result)) | ||
| 1217 | (set-syntax-table old-syntax-table)))) | ||
| 1098 | 1218 | ||
| 1099 | (defun mh-ascii-buffer-p () | 1219 | (defun mh-ascii-buffer-p () |
| 1100 | "Check if current buffer is entirely composed of ASCII. | 1220 | "Check if current buffer is entirely composed of ASCII. |