From 68f06909711dc87eb7af7d32424578db6667a395 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 9 Feb 2016 14:07:05 +1100 Subject: [PATCH] Make `message-beginning-of-line' aware of folded headers * lisp/gnus/message.pl (message-beginning-of-header): New function which moves point to the beginning of a mail header. The function is aware of folded headers and with non-nil argument looks for the true beginning of a header while with nil argument moves to the indented text of header's value. (message-beginning-of-line): Function is now aware of folded headers and either moves point to the indention of a header or, in visual-line-mode, searches for the beginning of the header. --- etc/NEWS | 5 +++ lisp/gnus/message.el | 82 +++++++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index bcb70d4aeed..3f5f5b0de5e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -772,6 +772,11 @@ there are now top-level domains added all the time. Message will no longer warn about sending emails to top-level domains it hasn't heard about. +*** `message-beginning-of-line' (bound to C-a) understands folded headers. +In `visual-line-mode' it will look for the true beginning of a header +while in non-`visual-line-mode' it will move the point to the indented +header’s value. + +++ ** Images are automatically scaled before displaying based on the `image-scaling-factor' variable (if Emacs supports scaling the images diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 9460710a477..5551820a2cd 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -6349,35 +6349,77 @@ they are." (defvar visual-line-mode) (declare-function beginning-of-visual-line "simple" (&optional n)) +(defun message-beginning-of-header (handle-folded) + "Move point to beginning of header’s value. + +When point is at the first header line, moves it after the colon +and spaces separating header name and header value. + +When point is in a continuation line of a folded header (i.e. the +line starts with a space), the behaviour depends on HANDLE-FOLDED +argument. If it’s nil, function moves the point to the start of +the header continuation; otherwise, function locates the +beginning of the header and moves point past the colon as is the +case of single-line headers. + +No check whether point is inside of a header or body of the +message is performed. + +Returns point or nil if beginning of header’s value could not be +found. In the latter case, the point is still moved to the +beginning of line (possibly after attempting to move it to the +beginning of a folded header)." + ;; https://www.rfc-editor.org/rfc/rfc2822.txt, section 2.2.3. says that when + ;; unfolding a single WSP should be consumed. WSP is defined as a space + ;; character or a horizontal tab. + (beginning-of-line) + (when handle-folded + (while (and (> (point) (point-min)) + (or (eq (char-after) ?\s) (eq (char-after) ?\t))) + (beginning-of-line 0))) + (when (or (eq (char-after) ?\s) (eq (char-after) ?\t) + (search-forward ":" (point-at-eol) t)) + ;; We are a bit more lacks than the RFC and allow any positive number of WSP + ;; characters. + (skip-chars-forward " \t" (point-at-eol)) + (point))) + (defun message-beginning-of-line (&optional n) "Move point to beginning of header value or to beginning of line. The prefix argument N is passed directly to `beginning-of-line'. This command is identical to `beginning-of-line' if point is -outside the message header or if the option `message-beginning-of-line' -is nil. - -If point is in the message header and on a (non-continued) header -line, move point to the beginning of the header value or the beginning of line, -whichever is closer. If point is already at beginning of line, move point to -beginning of header value. Therefore, repeated calls will toggle point -between beginning of field and beginning of line." +outside the message header or if the option +`message-beginning-of-line' is nil. + +If point is in the message header and on a header line, move +point to the beginning of the header value or the beginning of +line, whichever is closer. If point is already at beginning of +line, move point to beginning of header value. Therefore, +repeated calls will toggle point between beginning of field and +beginning of line. + +When called without a prefix argument, header value spanning +multiple lines is treated as a single line. Otherwise, even if +N is 1, when point is on a continuation header line, it will be +moved to the beginning " (interactive "p") (let ((zrs 'zmacs-region-stays)) (when (and (featurep 'xemacs) (interactive-p) (boundp zrs)) (set zrs t))) - (if (and message-beginning-of-line - (message-point-in-header-p)) - (let* ((here (point)) - (bol (progn (beginning-of-line n) (point))) - (eol (point-at-eol)) - (eoh (re-search-forward ": *" eol t))) - (goto-char - (if (and eoh (or (< eoh here) (= bol here))) - eoh bol))) - (if (and (boundp 'visual-line-mode) visual-line-mode) - (beginning-of-visual-line n) - (beginning-of-line n)))) + (cond + ;; Go to beginning of header or beginning of line. + ((and message-beginning-of-line (message-point-in-header-p)) + (let* ((point (point)) + (bol (progn (beginning-of-line n) (point))) + (boh (message-beginning-of-header (and (boundp 'visual-line-mode) + visual-line-mode)))) + (goto-char (if (and boh (or (< boh point) (= bol point))) boh bol)))) + ;; Go to beginning of visual line + ((and (boundp 'visual-line-mode) visual-line-mode) + (beginning-of-visual-line n)) + ;; Go to beginning of line. + ((beginning-of-line n)))) (defun message-buffer-name (type &optional to group) "Return a new (unique) buffer name based on TYPE and TO." -- 2.39.2