mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-21 18:38:08 +01:00
notmuch.el: Un-break the magic space bar to scroll a long, single message.
Clearly some recent code was very fragile, which I noticed in that the space bar would no longer scroll a long message if it was the only message in a thread. This resulted in a lot of churn, but hopefully things are more robust now, (for example by using new predicates like notmuch-show-last-message-p rather than doing heuristics based on (eobp) or (window-end)). As usual, the presence of invisible characters complicates the task of making this stuff robust.
This commit is contained in:
parent
9fc6f4e60d
commit
1d68e75c21
1 changed files with 60 additions and 38 deletions
98
notmuch.el
98
notmuch.el
|
@ -59,6 +59,20 @@
|
||||||
(defvar notmuch-show-id-regexp "ID: \\(.*\\)$")
|
(defvar notmuch-show-id-regexp "ID: \\(.*\\)$")
|
||||||
(defvar notmuch-show-tags-regexp "(\\([^)]*\\))$")
|
(defvar notmuch-show-tags-regexp "(\\([^)]*\\))$")
|
||||||
|
|
||||||
|
; XXX: This should be a generic function in emacs somewhere, not here
|
||||||
|
(defun point-invisible-p ()
|
||||||
|
"Return whether the character at point is invisible.
|
||||||
|
|
||||||
|
Here visibility is determined by `buffer-invisibility-spec' and
|
||||||
|
the invisible property of any overlays for point. It doesn't have
|
||||||
|
anything to do with whether point is currently being displayed
|
||||||
|
within the current window."
|
||||||
|
(let ((prop (get-char-property (point) 'invisible)))
|
||||||
|
(if (eq buffer-invisibility-spec t)
|
||||||
|
prop
|
||||||
|
(or (memq prop buffer-invisibility-spec)
|
||||||
|
(assq prop buffer-invisibility-spec)))))
|
||||||
|
|
||||||
(defun notmuch-show-get-message-id ()
|
(defun notmuch-show-get-message-id ()
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(beginning-of-line)
|
(beginning-of-line)
|
||||||
|
@ -147,23 +161,36 @@ by searching backward)."
|
||||||
(error "Not within a valid message."))
|
(error "Not within a valid message."))
|
||||||
(forward-line 2)))
|
(forward-line 2)))
|
||||||
|
|
||||||
|
(defun notmuch-show-last-message-p ()
|
||||||
|
"Predicate testing whether point is within the last message."
|
||||||
|
(save-window-excursion
|
||||||
|
(save-excursion
|
||||||
|
(notmuch-show-move-to-current-message-summary-line)
|
||||||
|
(not (re-search-forward notmuch-show-message-begin-regexp nil t)))))
|
||||||
|
|
||||||
|
(defun notmuch-show-message-unread-p ()
|
||||||
|
"Preficate testing whether current message is unread."
|
||||||
|
(member "unread" (notmuch-show-get-tags)))
|
||||||
|
|
||||||
(defun notmuch-show-next-message ()
|
(defun notmuch-show-next-message ()
|
||||||
"Advance to the beginning of the next message in the buffer.
|
"Advance to the beginning of the next message in the buffer.
|
||||||
|
|
||||||
Moves to the end of the buffer if already on the last message in
|
Moves to the last visible character of the current message if
|
||||||
the buffer."
|
already on the last message in the buffer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(notmuch-show-move-to-current-message-summary-line)
|
(notmuch-show-move-to-current-message-summary-line)
|
||||||
(if (re-search-forward notmuch-show-message-begin-regexp nil t)
|
(if (re-search-forward notmuch-show-message-begin-regexp nil t)
|
||||||
(notmuch-show-move-to-current-message-summary-line)
|
(notmuch-show-move-to-current-message-summary-line)
|
||||||
(goto-char (point-max)))
|
(goto-char (- (point-max) 1))
|
||||||
|
(while (point-invisible-p)
|
||||||
|
(backward-char)))
|
||||||
(recenter 0))
|
(recenter 0))
|
||||||
|
|
||||||
(defun notmuch-show-find-next-message ()
|
(defun notmuch-show-find-next-message ()
|
||||||
"Returns the position of the next message in the buffer.
|
"Returns the position of the next message in the buffer.
|
||||||
|
|
||||||
Or the end of the buffer if already within the last message in
|
Or the position of the last visible character of the current
|
||||||
the buffer."
|
message if already within the last message in the buffer."
|
||||||
; save-excursion doesn't save our window position
|
; save-excursion doesn't save our window position
|
||||||
; save-window-excursion doesn't save point
|
; save-window-excursion doesn't save point
|
||||||
; Looks like we have to use both.
|
; Looks like we have to use both.
|
||||||
|
@ -175,24 +202,14 @@ the buffer."
|
||||||
(defun notmuch-show-next-unread-message ()
|
(defun notmuch-show-next-unread-message ()
|
||||||
"Advance to the beginning of the next unread message in the buffer.
|
"Advance to the beginning of the next unread message in the buffer.
|
||||||
|
|
||||||
Moves to the end of the buffer if there are no more unread
|
Moves to the last visible character of the current message if
|
||||||
messages past the current point."
|
there are no more unread messages past the current point."
|
||||||
(while (and (not (eobp))
|
(notmuch-show-next-message)
|
||||||
(not (member "unread" (notmuch-show-get-tags))))
|
(while (and (not (notmuch-show-last-message-p))
|
||||||
(notmuch-show-next-message)))
|
(not (notmuch-show-message-unread-p)))
|
||||||
|
(notmuch-show-next-message))
|
||||||
(defun notmuch-show-find-next-unread-message ()
|
(if (not (notmuch-show-message-unread-p))
|
||||||
"Returns the position of the next message in the buffer.
|
(notmuch-show-next-message)))
|
||||||
|
|
||||||
Or the end of the buffer if there are no more unread messages
|
|
||||||
past the current point."
|
|
||||||
; save-excursion doesn't save our window position
|
|
||||||
; save-window-excursion doesn't save point
|
|
||||||
; Looks like we have to use both.
|
|
||||||
(save-excursion
|
|
||||||
(save-window-excursion
|
|
||||||
(notmuch-show-next-unread-message)
|
|
||||||
(point))))
|
|
||||||
|
|
||||||
(defun notmuch-show-previous-message ()
|
(defun notmuch-show-previous-message ()
|
||||||
"Backup to the beginning of the previous message in the buffer.
|
"Backup to the beginning of the previous message in the buffer.
|
||||||
|
@ -227,8 +244,8 @@ If the current message in the thread is not yet fully visible,
|
||||||
scroll by a near screenful to read more of the message.
|
scroll by a near screenful to read more of the message.
|
||||||
|
|
||||||
Otherwise, (the end of the current message is already within the
|
Otherwise, (the end of the current message is already within the
|
||||||
current window), remove the \"unread\" tag from the current
|
current window), remove the \"unread\" tag (if present) from the
|
||||||
message and advance to the next message.
|
current message and advance to the next message.
|
||||||
|
|
||||||
Finally, if there is no further message to advance to, and this
|
Finally, if there is no further message to advance to, and this
|
||||||
last message is already read, then archive the entire current
|
last message is already read, then archive the entire current
|
||||||
|
@ -236,15 +253,15 @@ thread, (remove the \"inbox\" tag from each message). Also kill
|
||||||
this buffer, and display the next thread from the search from
|
this buffer, and display the next thread from the search from
|
||||||
which this thread was originally shown."
|
which this thread was originally shown."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((next (notmuch-show-find-next-unread-message))
|
(let ((next (notmuch-show-find-next-message))
|
||||||
(unread (member "unread" (notmuch-show-get-tags))))
|
(unread (notmuch-show-message-unread-p)))
|
||||||
(if (and (not unread)
|
(if (> next (window-end))
|
||||||
(equal next (point)))
|
(scroll-up nil)
|
||||||
(notmuch-show-archive-thread)
|
(if unread
|
||||||
(if (and (> next (window-end))
|
(notmuch-show-mark-read-then-next-unread-message)
|
||||||
(< next (point-max)))
|
(if (notmuch-show-last-message-p)
|
||||||
(scroll-up nil)
|
(notmuch-show-archive-thread)
|
||||||
(notmuch-show-mark-read-then-next-unread-message)))))
|
(notmuch-show-next-unread-message))))))
|
||||||
|
|
||||||
(defun notmuch-show-markup-citations-region (beg end)
|
(defun notmuch-show-markup-citations-region (beg end)
|
||||||
(goto-char beg)
|
(goto-char beg)
|
||||||
|
@ -277,7 +294,7 @@ which this thread was originally shown."
|
||||||
(re-search-forward notmuch-show-body-end-regexp)
|
(re-search-forward notmuch-show-body-end-regexp)
|
||||||
(let ((end (match-beginning 0)))
|
(let ((end (match-beginning 0)))
|
||||||
(notmuch-show-markup-citations-region beg end)
|
(notmuch-show-markup-citations-region beg end)
|
||||||
(if (not (member "unread" (notmuch-show-get-tags)))
|
(if (not (notmuch-show-message-unread-p))
|
||||||
(overlay-put (make-overlay beg end)
|
(overlay-put (make-overlay beg end)
|
||||||
'invisible 'notmuch-show-body-read)))))
|
'invisible 'notmuch-show-body-read)))))
|
||||||
|
|
||||||
|
@ -422,9 +439,14 @@ thread from that buffer can be show when done with this one)."
|
||||||
(call-process "notmuch" nil t nil "show" thread-id)
|
(call-process "notmuch" nil t nil "show" thread-id)
|
||||||
(notmuch-show-markup-messages)
|
(notmuch-show-markup-messages)
|
||||||
)
|
)
|
||||||
(notmuch-show-next-unread-message)
|
; Move straight to the first unread message
|
||||||
(if (eobp)
|
(if (not (notmuch-show-message-unread-p))
|
||||||
(goto-char (point-min)))
|
(progn
|
||||||
|
(notmuch-show-next-unread-message)
|
||||||
|
; But if there are no unread messages, go back to the
|
||||||
|
; beginning of the buffer.
|
||||||
|
(if (not (notmuch-show-message-unread-p))
|
||||||
|
(goto-char (point-min)))))
|
||||||
)))
|
)))
|
||||||
|
|
||||||
(defvar notmuch-search-mode-map
|
(defvar notmuch-search-mode-map
|
||||||
|
|
Loading…
Reference in a new issue