(if (not (re-search-forward notmuch-show-message-begin-regexp nil t))
(goto-char (point-max))))))
+(defun notmuch-show-move-to-current-message-summary-line ()
+ "Move to the beginning of the one-line summary of the current message.
+
+This gives us a stable place to move to and work from since the
+summary line is always visible. This is important since moving to
+an invisible location is unreliable, (the main command loop moves
+point either forward or backward to the next visible character
+when a command ends with point on an invisible character).
+
+Emits an error if point is not within a valid message, (that is
+not pattern of `notmuch-show-message-begin-regexp' could be found
+by searching backward)."
+ (beginning-of-line)
+ (if (not (looking-at notmuch-show-message-begin-regexp))
+ (if (re-search-backward notmuch-show-message-begin-regexp nil t)
+ (forward-line 2)
+ (error "Not within a valid message."))
+ (forward-line 2)))
+
(defun notmuch-show-next-message ()
- "Advance point to the beginning of the next message in the buffer.
+ "Advance to the beginning of the next message in the buffer.
-Does nothing if already on the last message."
+Moves to the beginning of the current message if already on the
+last message in the buffer."
(interactive)
- ; First, ensure we get off the current message marker
- (if (not (eobp))
- (forward-char))
+ (notmuch-show-move-to-current-message-summary-line)
(re-search-forward notmuch-show-message-begin-regexp nil t)
- ; This dance might look pointless, but it's important. I originally
- ; just had (beginning-of-line) here which looked right on the
- ; display but actually put point all the way back to the first
- ; character of the first invisible line. That is, it put point into
- ; the closing markers of the previous message rather than at the
- ; beginning of the current message. And that in turn meant that
- ; looking up the current message-ID would actually return the
- ; previous message ID.
- ;
- ; So this dance ensures that we're actually on the current message
- ; when it looks like we are.
- (end-of-visible-line)
- (beginning-of-line)
+ (notmuch-show-move-to-current-message-summary-line)
(recenter 0))
(defun notmuch-show-previous-message ()
"Backup to the beginning of the previous message in the buffer.
-Does nothing if already on the first message in the buffer."
+Moves to the beginning of the current message if already on the
+first message in the buffer."
(interactive)
- ; First, ensure we get off the current message marker
- (if (not (bobp))
- (previous-line))
+ (notmuch-show-move-to-current-message-summary-line)
+ ; Go backward twice to skip the current message's marker
(re-search-backward notmuch-show-message-begin-regexp nil t)
- ; This dance might look pointless, but it's important. I originally
- ; just had (beginning-of-line) here which looked right on the
- ; display but actually put point all the way back to the first
- ; character of the first invisible line. That is, it put point into
- ; the closing markers of the previous message rather than at the
- ; beginning of the current message. And that in turn meant that
- ; looking up the current message-ID would actually return the
- ; previous message ID.
- ;
- ; So this dance ensures that we're actually on the current message
- ; when it looks like we are.
- (end-of-visible-line)
- (beginning-of-line)
+ (re-search-backward notmuch-show-message-begin-regexp nil t)
+ (notmuch-show-move-to-current-message-summary-line)
(recenter 0))
(defun notmuch-show-mark-read-then-next-message ()
;;;###autoload
(defun notmuch-show-mode ()
- "Major mode for handling the output of \"notmuch show\""
+ "Major mode for viewing a thread with notmuch.
+
+This buffer contains the results of the \"notmuch show\" command
+for displaying a single thread of email from your email archives.
+
+By default, various components of email messages, (citations,
+signatures, already-read messages), are invisible to help you
+focus on the most important things, (new text from unread
+messages). See the various commands below for toggling the
+visibility of hidden components.
+
+The `notmuch-show-next-message' and
+`notmuch-show-previous-message' commands, (bound to 'n' and 'p by
+default), allow you to navigate to the next and previous
+messages. Each time you navigate away from a message with
+`notmuch-show-next-message' the current message will have its
+\"unread\" tag removed.
+
+You can add or remove tags from the current message with '+' and
+'-'. You can also archive all messages in the current
+view, (remove the \"inbox\" tag from each), with
+`notmuch-show-archive-thread' (bound to 'a' by default).
+
+\\{notmuch-show-mode-map}"
(interactive)
(kill-all-local-variables)
(set (make-local-variable 'notmuch-show-headers-visible) t)
(define-key map "p" 'previous-line)
(define-key map "q" 'kill-this-buffer)
(define-key map "s" 'notmuch-search)
+ (define-key map "t" 'notmuch-search-filter-by-tag)
(define-key map "x" 'kill-this-buffer)
(define-key map "\r" 'notmuch-search-show-thread)
(define-key map "+" 'notmuch-search-add-tag)
;;;###autoload
(defun notmuch-search-mode ()
- "Major mode for handling the output of \"notmuch search\""
+ "Major mode for searching mail with notmuch.
+
+This buffer contains the results of a \"notmuch search\" of your
+email archives. Each line in the buffer represents a single
+thread giving a relative date for the thread and a subject.
+
+Pressing RET on any line displays that thread. The '+' and '-'
+keys can be used to add or remove tags from a thread. The 'a' key
+is a convenience key for archiving a thread (removing the
+\"inbox\" tag).
+
+Other useful commands are `notmuch-search-filter' for filtering
+the current search based on an additional query string,
+`notmuch-search-filter-by-tag' for filtering to include only
+messages with a given tag, and `notmuch-search' to execute a new,
+global search.
+
+\\{notmuch-search-mode-map}"
(interactive)
(kill-all-local-variables)
(make-local-variable 'notmuch-search-query-string)
(notmuch-search-set-tags (delete tag (notmuch-search-get-tags))))
(defun notmuch-search-archive-thread ()
+ "Archive the current thread (remove its \"inbox\" tag).
+
+This function advances point to the next line when finished."
(interactive)
- (notmuch-search-remove-tag "inbox"))
+ (notmuch-search-remove-tag "inbox")
+ (next-line))
(defun notmuch-search (query)
"Run \"notmuch search\" with the given query string and display results."
(goto-char here))))
(defun notmuch-search-filter (query)
- "Run \"notmuch search\" to refine the current search results.
+ "Filter the current search results based on an additional query string.
-A search string will be constructed by appending QUERY to the
-current search string, and the results of \"notmuch search\" for
-the combined query will be displayed."
+Runs a new search matching only messages that match both the
+current search results AND the additional query string provided."
(interactive "sFilter search: ")
(notmuch-search (concat notmuch-search-query-string " and " query)))
+(defun notmuch-search-filter-by-tag (tag)
+ "Filter the current search results based on a single tag.
+
+Runs a new search matching only messages that match both the
+current search results AND that are tagged with the given tag."
+ (interactive "sFilter by tag: ")
+ (notmuch-search (concat notmuch-search-query-string " and tag:" tag)))
+
(defun notmuch ()
"Run notmuch to display all mail with tag of 'inbox'"
(interactive)