"Predicate testing whether current message is unread."
(member "unread" (notmuch-show-get-tags)))
+(defun notmuch-show-message-open-p ()
+ "Predicate testing whether current message is open (body is visible)."
+ (let ((btn (previous-button (point) t)))
+ (while (not (button-has-type-p btn 'notmuch-button-body-toggle-type))
+ (setq btn (previous-button (button-start btn))))
+ (not (invisible-p (button-get btn 'invisibility-spec)))))
+
(defun notmuch-show-next-message ()
"Advance to the beginning of the next message in the buffer.
Moves to the last visible character of the current message if
-already on the last message in the buffer."
+already on the last message in the buffer.
+
+Returns nil if already on the last message in the buffer."
(interactive)
(notmuch-show-move-to-current-message-summary-line)
(if (re-search-forward notmuch-show-message-begin-regexp nil t)
- (notmuch-show-move-to-current-message-summary-line)
+ (progn
+ (notmuch-show-move-to-current-message-summary-line)
+ (recenter 0)
+ t)
(goto-char (- (point-max) 1))
(while (point-invisible-p)
- (backward-char)))
- (recenter 0))
+ (backward-char))
+ (recenter 0)
+ nil))
(defun notmuch-show-find-next-message ()
"Returns the position of the next message in the buffer.
(notmuch-show-next-message)))
(defun notmuch-show-next-open-message ()
- "Advance to the next message which is not hidden.
-
-If read messages are currently hidden, advance to the next unread
-message. Otherwise, advance to the next message."
- (if (or (memq 'notmuch-show-body-read buffer-invisibility-spec)
- (assq 'notmuch-show-body-read buffer-invisibility-spec))
- (notmuch-show-next-unread-message)
- (notmuch-show-next-message)))
+ "Advance to the next open message (that is, body is not invisible)."
+ (while (and (notmuch-show-next-message)
+ (not (notmuch-show-message-open-p)))))
(defun notmuch-show-previous-message ()
"Backup to the beginning of the previous message in the buffer.
(force-window-update)
(redisplay t))
-(define-button-type 'notmuch-button-invisibility-toggle-type 'action 'notmuch-toggle-invisible-action 'follow-link t)
+(define-button-type 'notmuch-button-invisibility-toggle-type
+ 'action 'notmuch-toggle-invisible-action
+ 'follow-link t
+ 'face "default")
(define-button-type 'notmuch-button-citation-toggle-type 'help-echo "mouse-1, RET: Show citation"
:supertype 'notmuch-button-invisibility-toggle-type)
(define-button-type 'notmuch-button-signature-toggle-type 'help-echo "mouse-1, RET: Show signature"
:supertype 'notmuch-button-invisibility-toggle-type)
(define-button-type 'notmuch-button-headers-toggle-type 'help-echo "mouse-1, RET: Show headers"
:supertype 'notmuch-button-invisibility-toggle-type)
-(define-button-type 'notmuch-button-body-toggle-type 'help-echo "mouse-1, RET: Show message"
+(define-button-type 'notmuch-button-body-toggle-type
+ 'help-echo "mouse-1, RET: Show message"
+ 'face 'notmuch-message-summary-face
:supertype 'notmuch-button-invisibility-toggle-type)
(defun notmuch-show-markup-citations-region (beg end depth)
(set-marker beg nil)
(set-marker end nil)
)))
+
(defun notmuch-fontify-headers ()
- (progn
- (if (looking-at "[Tt]o:")
- (progn
- (overlay-put (make-overlay (point) (re-search-forward ":"))
- 'face 'message-header-name)
- (overlay-put (make-overlay (point) (re-search-forward ".*$"))
- 'face 'message-header-to))
+ (while (looking-at "[[:space:]]")
+ (forward-char))
+ (if (looking-at "[Tt]o:")
+ (progn
+ (overlay-put (make-overlay (point) (re-search-forward ":"))
+ 'face 'message-header-name)
+ (overlay-put (make-overlay (point) (re-search-forward ".*$"))
+ 'face 'message-header-to))
(if (looking-at "[B]?[Cc][Cc]:")
(progn
(overlay-put (make-overlay (point) (re-search-forward ":"))
- 'face 'message-header-name)
- (overlay-put (make-overlay (point) (re-search-forward ".*$"))
- 'face 'message-header-cc))
- (if (looking-at "[Ss]ubject:")
- (progn
- (overlay-put (make-overlay (point) (re-search-forward ":"))
- 'face 'message-header-name)
- (overlay-put (make-overlay (point) (re-search-forward ".*$"))
- 'face 'message-header-subject))
- (if (looking-at "[Ff]rom:")
- (progn
- (overlay-put (make-overlay (point) (re-search-forward ":"))
- 'face 'message-header-name)
- (overlay-put (make-overlay (point) (re-search-forward ".*$"))
- 'face 'message-header-other))))))))
-
-(defun notmuch-show-markup-header (depth)
+ 'face 'message-header-name)
+ (overlay-put (make-overlay (point) (re-search-forward ".*$"))
+ 'face 'message-header-cc))
+ (if (looking-at "[Ss]ubject:")
+ (progn
+ (overlay-put (make-overlay (point) (re-search-forward ":"))
+ 'face 'message-header-name)
+ (overlay-put (make-overlay (point) (re-search-forward ".*$"))
+ 'face 'message-header-subject))
+ (if (looking-at "[Ff]rom:")
+ (progn
+ (overlay-put (make-overlay (point) (re-search-forward ":"))
+ 'face 'message-header-name)
+ (overlay-put (make-overlay (point) (re-search-forward ".*$"))
+ 'face 'message-header-other)))))))
+
+(defun notmuch-show-markup-header (message-begin depth)
+ "Buttonize and decorate faces in a message header.
+
+MESSAGE-BEGIN is the position of the absolute first character in
+the message (including all delimiters that will end up being
+invisible etc.). This is to allow a button to reliably extend to
+the beginning of the message even if point is positioned at an
+invisible character (such as the beginning of the buffer).
+
+DEPTH specifies the depth at which this message appears in the
+tree of the current thread, (the top-level messages have depth 0
+and each reply increases depth by 1)."
(re-search-forward notmuch-show-header-begin-regexp)
(forward-line)
(let ((beg (point-marker))
+ (summary-end (copy-marker (line-beginning-position 2)))
+ (subject-end (copy-marker (line-end-position 2)))
+ (invis-spec (make-symbol "notmuch-show-header"))
(btn nil))
- (end-of-line)
- ; Inverse video for subject
- (overlay-put (make-overlay beg (point)) 'face '(:inverse-video t))
- (setq btn (make-button beg (point) :type 'notmuch-button-body-toggle-type))
- (forward-line 1)
- (end-of-line)
- (let ((beg-hidden (point-marker)))
- (re-search-forward notmuch-show-header-end-regexp)
- (beginning-of-line)
- (let ((end (point-marker)))
- (goto-char beg)
- (forward-line)
- (while (looking-at "[A-Za-z][-A-Za-z0-9]*:")
- (beginning-of-line)
- (notmuch-fontify-headers)
- (forward-line)
- )
- (indent-rigidly beg end depth)
- (let ((invis-spec (make-symbol "notmuch-show-header")))
- (add-to-invisibility-spec (cons invis-spec t))
- (overlay-put (make-overlay beg-hidden end)
- 'invisible invis-spec)
- (goto-char beg)
- (forward-line)
- (make-button (line-beginning-position) (line-end-position)
- 'invisibility-spec (cons invis-spec t)
- :type 'notmuch-button-headers-toggle-type))
- (goto-char end)
- (insert "\n")
- (set-marker beg nil)
- (set-marker beg-hidden nil)
- (set-marker end nil)
- ))
- btn))
+ (re-search-forward notmuch-show-header-end-regexp)
+ (beginning-of-line)
+ (let ((end (point-marker)))
+ (indent-rigidly beg end depth)
+ (goto-char beg)
+ (setq btn (make-button message-begin summary-end :type 'notmuch-button-body-toggle-type))
+ (forward-line)
+ (add-to-invisibility-spec invis-spec)
+ (overlay-put (make-overlay subject-end end)
+ 'invisible invis-spec)
+ (make-button (line-beginning-position) subject-end
+ 'invisibility-spec invis-spec
+ :type 'notmuch-button-headers-toggle-type)
+ (while (looking-at "[[:space:]]*[A-Za-z][-A-Za-z0-9]*:")
+ (beginning-of-line)
+ (notmuch-fontify-headers)
+ (forward-line)
+ )
+ (goto-char end)
+ (insert "\n")
+ (set-marker beg nil)
+ (set-marker summary-end nil)
+ (set-marker subject-end nil)
+ (set-marker end nil)
+ )
+ btn))
(defun notmuch-show-markup-message ()
(if (re-search-forward notmuch-show-message-begin-regexp nil t)
- (progn
+ (let ((message-begin (match-beginning 0)))
(re-search-forward notmuch-show-depth-regexp)
(let ((depth (string-to-number (buffer-substring (match-beginning 1) (match-end 1))))
(btn nil))
- (setq btn (notmuch-show-markup-header depth))
+ (setq btn (notmuch-show-markup-header message-begin depth))
(notmuch-show-markup-body depth btn)))
(goto-char (point-max))))
(interactive)
(goto-char (point-min)))
+(defface notmuch-message-summary-face
+ '((((class color) (background light)) (:background "#f0f0f0"))
+ (((class color) (background dark)) (:background "#303030")))
+ "Face for the single-line message summary in notmuch-show-mode."
+ :group 'notmuch)
+
(defface notmuch-tag-face
'((((class color)
(background dark))