diff options
| author | Stefan Monnier | 2018-01-23 13:55:35 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2018-01-23 13:55:35 -0500 |
| commit | 5ed5f548aaa1f3fa7941895d48f97ad970b38ff1 (patch) | |
| tree | b94483882700ba8348083e869cc1d3911e5116a3 | |
| parent | f2918640bf35d6bb0130f854b2ea8ed4b4fd89d4 (diff) | |
| download | emacs-5ed5f548aaa1f3fa7941895d48f97ad970b38ff1.tar.gz emacs-5ed5f548aaa1f3fa7941895d48f97ad970b38ff1.zip | |
* lisp/gnus/message.el: Tweak header font-lock and ecomplete completion
(message-font-lock-make-header-matcher): Delete.
(message-match-to-eoh): New function to replace it.
(message-font-lock-keywords): Use it.
(message-strip-forbidden-properties): Remove redundant binding.
(message-goto-body): Avoid called-interactively-p, only use
push-mark when called interactively.
(message-goto-body-1): Merge into message-goto-body. Redefine as alias.
(message-goto-eoh): Call message-goto-body interactively.
(message--in-tocc-p): New function, extracted from message-display-abbrev.
(message-ecomplete-capf): New function.
| -rw-r--r-- | lisp/gnus/message.el | 148 |
1 files changed, 82 insertions, 66 deletions
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 93b897b2beb..a0adccef7ad 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el | |||
| @@ -1544,50 +1544,49 @@ starting with `not' and followed by regexps." | |||
| 1544 | "Face used for displaying MML." | 1544 | "Face used for displaying MML." |
| 1545 | :group 'message-faces) | 1545 | :group 'message-faces) |
| 1546 | 1546 | ||
| 1547 | (defun message-font-lock-make-header-matcher (regexp) | 1547 | (defun message-match-to-eoh (_limit) |
| 1548 | (let ((form | 1548 | (let ((start (point))) |
| 1549 | `(lambda (limit) | 1549 | (rfc822-goto-eoh) |
| 1550 | (let ((start (point))) | 1550 | ;; Typical situation: some temporary change causes the header to be |
| 1551 | (save-restriction | 1551 | ;; incorrect, so EOH comes earlier than intended: the last lines of the |
| 1552 | (widen) | 1552 | ;; intended headers are now not considered part of the header any more, |
| 1553 | (goto-char (point-min)) | 1553 | ;; so they don't have the multiline property set. When the change is |
| 1554 | (if (re-search-forward | 1554 | ;; completed and the header has its correct shape again, the lack of the |
| 1555 | (concat "^" (regexp-quote mail-header-separator) "$") | 1555 | ;; multiline property means we won't rehighlight the last lines of |
| 1556 | nil t) | 1556 | ;; the header. |
| 1557 | (setq limit (min limit (match-beginning 0)))) | 1557 | (if (< (point) start) |
| 1558 | (goto-char start)) | 1558 | nil ;No header within start..limit. |
| 1559 | (and (< start limit) | 1559 | ;; Here we disregard LIMIT so that we may extend the area again. |
| 1560 | (re-search-forward ,regexp limit t)))))) | 1560 | (set-match-data (list start (point))) |
| 1561 | (if (featurep 'bytecomp) | 1561 | (point)))) |
| 1562 | (byte-compile form) | ||
| 1563 | form))) | ||
| 1564 | 1562 | ||
| 1565 | (defvar message-font-lock-keywords | 1563 | (defvar message-font-lock-keywords |
| 1566 | (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?")) | 1564 | (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?")) |
| 1567 | `((,(message-font-lock-make-header-matcher | 1565 | `((message-match-to-eoh |
| 1568 | (concat "^\\([Tt]o:\\)" content)) | 1566 | (,(concat "^\\([Tt]o:\\)" content) |
| 1569 | (1 'message-header-name) | 1567 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1570 | (2 'message-header-to nil t)) | 1568 | (1 'message-header-name) |
| 1571 | (,(message-font-lock-make-header-matcher | 1569 | (2 'message-header-to nil t)) |
| 1572 | (concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content)) | 1570 | (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content) |
| 1573 | (1 'message-header-name) | 1571 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1574 | (2 'message-header-cc nil t)) | 1572 | (1 'message-header-name) |
| 1575 | (,(message-font-lock-make-header-matcher | 1573 | (2 'message-header-cc nil t)) |
| 1576 | (concat "^\\([Ss]ubject:\\)" content)) | 1574 | (,(concat "^\\([Ss]ubject:\\)" content) |
| 1577 | (1 'message-header-name) | 1575 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1578 | (2 'message-header-subject nil t)) | 1576 | (1 'message-header-name) |
| 1579 | (,(message-font-lock-make-header-matcher | 1577 | (2 'message-header-subject nil t)) |
| 1580 | (concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content)) | 1578 | (,(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content) |
| 1581 | (1 'message-header-name) | 1579 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1582 | (2 'message-header-newsgroups nil t)) | 1580 | (1 'message-header-name) |
| 1583 | (,(message-font-lock-make-header-matcher | 1581 | (2 'message-header-newsgroups nil t)) |
| 1584 | (concat "^\\(X-[A-Za-z0-9-]+:\\|In-Reply-To:\\)" content)) | 1582 | (,(concat "^\\(X-[A-Za-z0-9-]+:\\|In-Reply-To:\\)" content) |
| 1585 | (1 'message-header-name) | 1583 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1586 | (2 'message-header-xheader)) | 1584 | (1 'message-header-name) |
| 1587 | (,(message-font-lock-make-header-matcher | 1585 | (2 'message-header-xheader)) |
| 1588 | (concat "^\\([A-Z][^: \n\t]+:\\)" content)) | 1586 | (,(concat "^\\([A-Z][^: \n\t]+:\\)" content) |
| 1589 | (1 'message-header-name) | 1587 | (progn (goto-char (match-beginning 0)) (match-end 0)) nil |
| 1590 | (2 'message-header-other nil t)) | 1588 | (1 'message-header-name) |
| 1589 | (2 'message-header-other nil t))) | ||
| 1591 | ,@(if (and mail-header-separator | 1590 | ,@(if (and mail-header-separator |
| 1592 | (not (equal mail-header-separator ""))) | 1591 | (not (equal mail-header-separator ""))) |
| 1593 | `((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$") | 1592 | `((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$") |
| @@ -2821,8 +2820,7 @@ See also `message-forbidden-properties'." | |||
| 2821 | (message-display-abbrev)) | 2820 | (message-display-abbrev)) |
| 2822 | (when (and message-strip-special-text-properties | 2821 | (when (and message-strip-special-text-properties |
| 2823 | (message-tamago-not-in-use-p begin)) | 2822 | (message-tamago-not-in-use-p begin)) |
| 2824 | (let ((buffer-read-only nil) | 2823 | (let ((inhibit-read-only t)) |
| 2825 | (inhibit-read-only t)) | ||
| 2826 | (remove-text-properties begin end message-forbidden-properties)))) | 2824 | (remove-text-properties begin end message-forbidden-properties)))) |
| 2827 | 2825 | ||
| 2828 | (defvar message-smileys '(":-)" ":)" | 2826 | (defvar message-smileys '(":-)" ":)" |
| @@ -2929,7 +2927,7 @@ M-RET `message-newline-and-reformat' (break the line and reformat)." | |||
| 2929 | (easy-menu-add message-mode-menu message-mode-map) | 2927 | (easy-menu-add message-mode-menu message-mode-map) |
| 2930 | (easy-menu-add message-mode-field-menu message-mode-map) | 2928 | (easy-menu-add message-mode-field-menu message-mode-map) |
| 2931 | ;; Mmmm... Forbidden properties... | 2929 | ;; Mmmm... Forbidden properties... |
| 2932 | (add-hook 'after-change-functions 'message-strip-forbidden-properties | 2930 | (add-hook 'after-change-functions #'message-strip-forbidden-properties |
| 2933 | nil 'local) | 2931 | nil 'local) |
| 2934 | ;; Allow mail alias things. | 2932 | ;; Allow mail alias things. |
| 2935 | (cond | 2933 | (cond |
| @@ -2937,7 +2935,9 @@ M-RET `message-newline-and-reformat' (break the line and reformat)." | |||
| 2937 | (mail-abbrevs-setup)) | 2935 | (mail-abbrevs-setup)) |
| 2938 | ((message-mail-alias-type-p 'ecomplete) | 2936 | ((message-mail-alias-type-p 'ecomplete) |
| 2939 | (ecomplete-setup))) | 2937 | (ecomplete-setup))) |
| 2940 | (add-hook 'completion-at-point-functions 'message-completion-function nil t) | 2938 | ;; FIXME: merge the completion tables from ecomplete/bbdb/...? |
| 2939 | ;;(add-hook 'completion-at-point-functions #'message-ecomplete-capf nil t) | ||
| 2940 | (add-hook 'completion-at-point-functions #'message-completion-function nil t) | ||
| 2941 | (unless buffer-file-name | 2941 | (unless buffer-file-name |
| 2942 | (message-set-auto-save-file-name)) | 2942 | (message-set-auto-save-file-name)) |
| 2943 | (unless (buffer-base-buffer) | 2943 | (unless (buffer-base-buffer) |
| @@ -3071,17 +3071,15 @@ M-RET `message-newline-and-reformat' (break the line and reformat)." | |||
| 3071 | (push-mark) | 3071 | (push-mark) |
| 3072 | (message-position-on-field "Summary" "Subject")) | 3072 | (message-position-on-field "Summary" "Subject")) |
| 3073 | 3073 | ||
| 3074 | (defun message-goto-body () | 3074 | (define-obsolete-function-alias 'message-goto-body-1 'message-goto-body "27.1") |
| 3075 | "Move point to the beginning of the message body." | 3075 | (defun message-goto-body (&optional interactive) |
| 3076 | (interactive) | 3076 | "Move point to the beginning of the message body. |
| 3077 | (when (and (called-interactively-p 'any) | 3077 | Returns point." |
| 3078 | (looking-at "[ \t]*\n")) | 3078 | (interactive "p") |
| 3079 | (when interactive | ||
| 3080 | (when (looking-at "[ \t]*\n") | ||
| 3079 | (expand-abbrev)) | 3081 | (expand-abbrev)) |
| 3080 | (push-mark) | 3082 | (push-mark)) |
| 3081 | (message-goto-body-1)) | ||
| 3082 | |||
| 3083 | (defun message-goto-body-1 () | ||
| 3084 | "Go to the body and return point." | ||
| 3085 | (goto-char (point-min)) | 3083 | (goto-char (point-min)) |
| 3086 | (or (search-forward (concat "\n" mail-header-separator "\n") nil t) | 3084 | (or (search-forward (concat "\n" mail-header-separator "\n") nil t) |
| 3087 | ;; If the message is mangled, find the end of the headers the | 3085 | ;; If the message is mangled, find the end of the headers the |
| @@ -3100,12 +3098,12 @@ M-RET `message-newline-and-reformat' (break the line and reformat)." | |||
| 3100 | "Return t if point is in the message body." | 3098 | "Return t if point is in the message body." |
| 3101 | (>= (point) | 3099 | (>= (point) |
| 3102 | (save-excursion | 3100 | (save-excursion |
| 3103 | (message-goto-body-1)))) | 3101 | (message-goto-body)))) |
| 3104 | 3102 | ||
| 3105 | (defun message-goto-eoh () | 3103 | (defun message-goto-eoh (&optional interactive) |
| 3106 | "Move point to the end of the headers." | 3104 | "Move point to the end of the headers." |
| 3107 | (interactive) | 3105 | (interactive "p") |
| 3108 | (message-goto-body) | 3106 | (message-goto-body interactive) |
| 3109 | (forward-line -1)) | 3107 | (forward-line -1)) |
| 3110 | 3108 | ||
| 3111 | (defun message-goto-signature () | 3109 | (defun message-goto-signature () |
| @@ -7882,6 +7880,7 @@ When FORCE, rebuild the tool bar." | |||
| 7882 | :type 'regexp) | 7880 | :type 'regexp) |
| 7883 | 7881 | ||
| 7884 | (defcustom message-completion-alist | 7882 | (defcustom message-completion-alist |
| 7883 | ;; FIXME: Make it possible to use the standard completion UI. | ||
| 7885 | (list (cons message-newgroups-header-regexp 'message-expand-group) | 7884 | (list (cons message-newgroups-header-regexp 'message-expand-group) |
| 7886 | '("^\\(Resent-\\)?\\(To\\|B?Cc\\):" . message-expand-name) | 7885 | '("^\\(Resent-\\)?\\(To\\|B?Cc\\):" . message-expand-name) |
| 7887 | '("^\\(Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):" | 7886 | '("^\\(Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):" |
| @@ -8206,16 +8205,19 @@ From headers in the original article." | |||
| 8206 | 8205 | ||
| 8207 | (autoload 'ecomplete-display-matches "ecomplete") | 8206 | (autoload 'ecomplete-display-matches "ecomplete") |
| 8208 | 8207 | ||
| 8208 | (defun message--in-tocc-p () | ||
| 8209 | (and (memq (char-after (point-at-bol)) '(?C ?T ?\t ? )) | ||
| 8210 | (message-point-in-header-p) | ||
| 8211 | (save-excursion | ||
| 8212 | (beginning-of-line) | ||
| 8213 | (while (and (memq (char-after) '(?\t ? )) | ||
| 8214 | (zerop (forward-line -1)))) | ||
| 8215 | (looking-at "To:\\|Cc:")))) | ||
| 8216 | |||
| 8209 | (defun message-display-abbrev (&optional choose) | 8217 | (defun message-display-abbrev (&optional choose) |
| 8210 | "Display the next possible abbrev for the text before point." | 8218 | "Display the next possible abbrev for the text before point." |
| 8211 | (interactive (list t)) | 8219 | (interactive (list t)) |
| 8212 | (when (and (memq (char-after (point-at-bol)) '(?C ?T ?\t ? )) | 8220 | (when (message--in-tocc-p) |
| 8213 | (message-point-in-header-p) | ||
| 8214 | (save-excursion | ||
| 8215 | (beginning-of-line) | ||
| 8216 | (while (and (memq (char-after) '(?\t ? )) | ||
| 8217 | (zerop (forward-line -1)))) | ||
| 8218 | (looking-at "To:\\|Cc:"))) | ||
| 8219 | (let* ((end (point)) | 8221 | (let* ((end (point)) |
| 8220 | (start (save-excursion | 8222 | (start (save-excursion |
| 8221 | (and (re-search-backward "[\n\t ]" nil t) | 8223 | (and (re-search-backward "[\n\t ]" nil t) |
| @@ -8228,6 +8230,20 @@ From headers in the original article." | |||
| 8228 | (delete-region start end) | 8230 | (delete-region start end) |
| 8229 | (insert match))))) | 8231 | (insert match))))) |
| 8230 | 8232 | ||
| 8233 | (defun message-ecomplete-capf () | ||
| 8234 | "Return completion data for email addresses in Ecomplete. | ||
| 8235 | Meant for use on `completion-at-point-functions'." | ||
| 8236 | (when (and (bound-and-true-p ecomplete-database) | ||
| 8237 | (fboundp 'ecomplete-completion-table) | ||
| 8238 | (message--in-tocc-p)) | ||
| 8239 | (let ((end (save-excursion | ||
| 8240 | (skip-chars-forward "^, \t\n") | ||
| 8241 | (point))) | ||
| 8242 | (start (save-excursion | ||
| 8243 | (skip-chars-backward "^, \t\n") | ||
| 8244 | (point)))) | ||
| 8245 | `(,start ,end ,(apply-partially #'ecomplete-completion-table 'mail))))) | ||
| 8246 | |||
| 8231 | ;; To send pre-formatted letters like the example below, you can use | 8247 | ;; To send pre-formatted letters like the example below, you can use |
| 8232 | ;; `message-send-form-letter': | 8248 | ;; `message-send-form-letter': |
| 8233 | ;; --8<---------------cut here---------------start------------->8--- | 8249 | ;; --8<---------------cut here---------------start------------->8--- |