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.
This commit is contained in:
Michal Nazarewicz 2016-02-09 14:07:05 +11:00 committed by Lars Ingebrigtsen
parent 824a87f41f
commit 68f0690971
2 changed files with 66 additions and 19 deletions

View file

@ -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
headers value.
+++
** Images are automatically scaled before displaying based on the
`image-scaling-factor' variable (if Emacs supports scaling the images

View file

@ -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 headers 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 its 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 headers 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.
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."
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."