[PATCH v2] emacs: Disambiguate point placement after hiding message

Subject: [PATCH v2] emacs: Disambiguate point placement after hiding message

Date: Tue, 8 Jan 2013 17:39:19 -0500

To: notmuch@notmuchmail.org


From: Austin Clements

Currently, if point is in the middle of a message when the user
collapses it, Emacs then displays the cursor on the header line of the
next message, even though point is still on the collapsed message and
even though, if you explicitly move point to the same visual location,
it will be on the next message.  As a result, following actions like
re-expanding the message or modifying tags apply to the collapsed
message, even though, visually, it looks like they will apply to the
message following the collapsed message.

This patch addresses this by explicitly moving point when a message is
collapsed so it is visually unambiguous that the point is still on the
collapsed message.

v2 should fix the strange behavior observed in v1.  The added code is
essentially identical to v1, but v2 adds it to
notmuch-show-toggle-message---which is only used
interactively---rather than the core notmuch-show-message-visible

 emacs/notmuch-show.el |   28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 5751d98..6ab926c 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1789,12 +1789,30 @@ See `notmuch-tag' for information on the format of TAG-CHANGES."
 (defun notmuch-show-toggle-message ()
-  "Toggle the visibility of the current message."
+  "Toggle the visibility of the current message.
+If this hides the current message, it will also move point to
+make it obvious it's still on the current message."
-  (let ((props (notmuch-show-get-message-properties)))
-    (notmuch-show-message-visible
-     props
-     (not (plist-get props :message-visible))))
+  (let* ((props (notmuch-show-get-message-properties))
+	 (visible-p (not (plist-get props :message-visible))))
+    (notmuch-show-message-visible props visible-p)
+    (when (not visible-p)
+      (let ((ov (plist-get props :message-overlay)))
+	;; If point was contained in the overlay, move it to a
+	;; sensible spot that is visible and still on the same
+	;; message.  Strangely, the Emacs event loop doesn't move the
+	;; point out of the invisible region for us like it normally
+	;; does (perhaps because it doesn't know which way to go), so
+	;; if we don't do this, it's visually ambiguous which message
+	;; an action will apply to.
+	(let ((start (overlay-start ov))
+	      (end (overlay-end ov)))
+	  (dolist (win (get-buffer-window-list nil nil t))
+	    (with-selected-window win
+	      (when (and (<= start (point)) (< (point) end))
+		(goto-char (1- start))
+		(beginning-of-visual-line))))))))
 (defun notmuch-show-open-or-close-all ()