]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch-show.el
emacs: make headings outline-minor-mode compatible
[notmuch] / emacs / notmuch-show.el
index d088c80b3f5371c1b950e0ac7005bd72b869df58..7dfbb32738e0ca949b712b648d547a00db7aa02a 100644 (file)
@@ -1,4 +1,4 @@
-;;; notmuch-show.el --- displaying notmuch forests.
+;;; notmuch-show.el --- displaying notmuch forests
 ;;
 ;; Copyright © Carl Worth
 ;; Copyright © David Edmondson
 ;;
 ;; Copyright © Carl Worth
 ;; Copyright © David Edmondson
@@ -59,6 +59,8 @@
 (declare-function notmuch-read-query "notmuch" (prompt))
 (declare-function notmuch-draft-resume "notmuch-draft" (id))
 
 (declare-function notmuch-read-query "notmuch" (prompt))
 (declare-function notmuch-draft-resume "notmuch-draft" (id))
 
+;;; Options
+
 (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")
   "Headers that should be shown in a message, in this order.
 
 (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")
   "Headers that should be shown in a message, in this order.
 
@@ -162,23 +164,19 @@ indentation."
   :type '(choice (const nil) regexp)
   :group 'notmuch-show)
 
   :type '(choice (const nil) regexp)
   :group 'notmuch-show)
 
-(defvar notmuch-show-thread-id nil)
-(make-variable-buffer-local 'notmuch-show-thread-id)
+;;; Variables
+
+(defvar-local notmuch-show-thread-id nil)
 
 
-(defvar notmuch-show-parent-buffer nil)
-(make-variable-buffer-local 'notmuch-show-parent-buffer)
+(defvar-local notmuch-show-parent-buffer nil)
 
 
-(defvar notmuch-show-query-context nil)
-(make-variable-buffer-local 'notmuch-show-query-context)
+(defvar-local notmuch-show-query-context nil)
 
 
-(defvar notmuch-show-process-crypto nil)
-(make-variable-buffer-local 'notmuch-show-process-crypto)
+(defvar-local notmuch-show-process-crypto nil)
 
 
-(defvar notmuch-show-elide-non-matching-messages nil)
-(make-variable-buffer-local 'notmuch-show-elide-non-matching-messages)
+(defvar-local notmuch-show-elide-non-matching-messages nil)
 
 
-(defvar notmuch-show-indent-content t)
-(make-variable-buffer-local 'notmuch-show-indent-content)
+(defvar-local notmuch-show-indent-content t)
 
 (defvar notmuch-show-attachment-debug nil
   "If t log stdout and stderr from attachment handlers.
 
 (defvar notmuch-show-attachment-debug nil
   "If t log stdout and stderr from attachment handlers.
@@ -186,8 +184,9 @@ indentation."
 When set to nil (the default) stdout and stderr from attachment
 handlers is discarded. When set to t the stdout and stderr from
 each attachment handler is logged in buffers with names beginning
 When set to nil (the default) stdout and stderr from attachment
 handlers is discarded. When set to t the stdout and stderr from
 each attachment handler is logged in buffers with names beginning
-\" *notmuch-part*\". This option requires emacs version at least
-24.3 to work.")
+\" *notmuch-part*\".")
+
+;;; Options
 
 (defcustom notmuch-show-stash-mlarchive-link-alist
   '(("Gmane" . "https://mid.gmane.org/")
 
 (defcustom notmuch-show-stash-mlarchive-link-alist
   '(("Gmane" . "https://mid.gmane.org/")
@@ -267,6 +266,8 @@ position of the message in the thread."
   :type 'boolean
   :group 'notmuch-show)
 
   :type 'boolean
   :group 'notmuch-show)
 
+;;; Utilities
+
 (defmacro with-current-notmuch-show-message (&rest body)
   "Evaluate body with current buffer set to the text of current message."
   `(save-excursion
 (defmacro with-current-notmuch-show-message (&rest body)
   "Evaluate body with current buffer set to the text of current message."
   `(save-excursion
@@ -282,6 +283,8 @@ position of the message in the thread."
   "Enable Visual Line mode."
   (visual-line-mode t))
 
   "Enable Visual Line mode."
   (visual-line-mode t))
 
+;;; Commands
+
 ;; DEPRECATED in Notmuch 0.16 since we now have convenient part
 ;; commands.  We'll keep the command around for a version or two in
 ;; case people want to bind it themselves.
 ;; DEPRECATED in Notmuch 0.16 since we now have convenient part
 ;; commands.  We'll keep the command around for a version or two in
 ;; case people want to bind it themselves.
@@ -346,10 +349,10 @@ operation on the contents of the current buffer."
         (indenting notmuch-show-indent-content))
     (with-temp-buffer
       (insert all)
         (indenting notmuch-show-indent-content))
     (with-temp-buffer
       (insert all)
-      (if indenting
-         (indent-rigidly (point-min)
-                         (point-max)
-                         (- (* notmuch-show-indent-messages-width depth))))
+      (when indenting
+       (indent-rigidly (point-min)
+                       (point-max)
+                       (- (* notmuch-show-indent-messages-width depth))))
       ;; Remove the original header.
       (goto-char (point-min))
       (re-search-forward "^$" (point-max) nil)
       ;; Remove the original header.
       (goto-char (point-min))
       (re-search-forward "^$" (point-max) nil)
@@ -362,6 +365,8 @@ operation on the contents of the current buffer."
   (interactive)
   (notmuch-show-with-message-as-text 'notmuch-print-message))
 
   (interactive)
   (notmuch-show-with-message-as-text 'notmuch-print-message))
 
+;;; Headers
+
 (defun notmuch-show-fontify-header ()
   (let ((face (cond
               ((looking-at "[Tt]o:")
 (defun notmuch-show-fontify-header ()
   (let ((face (cond
               ((looking-at "[Tt]o:")
@@ -392,13 +397,13 @@ operation on the contents of the current buffer."
   "Update the displayed tags of the current message."
   (save-excursion
     (goto-char (notmuch-show-message-top))
   "Update the displayed tags of the current message."
   (save-excursion
     (goto-char (notmuch-show-message-top))
-    (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
-       (let ((inhibit-read-only t))
-         (replace-match (concat "("
-                                (notmuch-tag-format-tags
-                                 tags
-                                 (notmuch-show-get-prop :orig-tags))
-                                ")"))))))
+    (when (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
+      (let ((inhibit-read-only t))
+       (replace-match (concat "("
+                              (notmuch-tag-format-tags
+                               tags
+                               (notmuch-show-get-prop :orig-tags))
+                              ")"))))))
 
 (defun notmuch-clean-address (address)
   "Try to clean a single email ADDRESS for display. Return a cons
 
 (defun notmuch-clean-address (address)
   "Try to clean a single email ADDRESS for display. Return a cons
@@ -415,8 +420,8 @@ parsing fails."
        (cond
         ;; "User <user@dom.ain>" style.
         ((string-match "\\(.*\\) <\\(.*\\)>" address)
        (cond
         ;; "User <user@dom.ain>" style.
         ((string-match "\\(.*\\) <\\(.*\\)>" address)
-         (setq p-name (match-string 1 address)
-               p-address (match-string 2 address)))
+         (setq p-name (match-string 1 address))
+         (setq p-address (match-string 2 address)))
 
         ;; "<user@dom.ain>" style.
         ((string-match "<\\(.*\\)>" address)
 
         ;; "<user@dom.ain>" style.
         ((string-match "<\\(.*\\)>" address)
@@ -446,8 +451,8 @@ parsing fails."
     (error (cons address nil))))
 
 (defun notmuch-show-clean-address (address)
     (error (cons address nil))))
 
 (defun notmuch-show-clean-address (address)
-  "Try to clean a single email ADDRESS for display.  Return
-unchanged ADDRESS if parsing fails."
+  "Try to clean a single email ADDRESS for display.
+Return unchanged ADDRESS if parsing fails."
   (let* ((clean-address (notmuch-clean-address address))
         (p-address (car clean-address))
         (p-name (cdr clean-address)))
   (let* ((clean-address (notmuch-clean-address address))
         (p-address (car clean-address))
         (p-name (cdr clean-address)))
@@ -468,7 +473,10 @@ message at DEPTH in the current thread."
       ;; invisible U+200E LEFT-TO-RIGHT MARK character which forces
       ;; the header paragraph as left-to-right text.
       (insert (propertize (string ?\x200e) 'invisible t)))
       ;; invisible U+200E LEFT-TO-RIGHT MARK character which forces
       ;; the header paragraph as left-to-right text.
       (insert (propertize (string ?\x200e) 'invisible t)))
-    (insert (notmuch-show-spaces-n (* notmuch-show-indent-messages-width depth))
+    (insert (if notmuch-show-indent-content
+               (notmuch-show-spaces-n (* notmuch-show-indent-messages-width
+                                         depth))
+             "")
            from
            " ("
            date
            from
            " ("
            date
@@ -488,15 +496,17 @@ message at DEPTH in the current thread."
     (mapc (lambda (header)
            (let* ((header-symbol (intern (concat ":" header)))
                   (header-value (plist-get headers header-symbol)))
     (mapc (lambda (header)
            (let* ((header-symbol (intern (concat ":" header)))
                   (header-value (plist-get headers header-symbol)))
-             (if (and header-value
-                      (not (string-equal "" header-value)))
-                 (notmuch-show-insert-header header header-value))))
+             (when (and header-value
+                        (not (string-equal "" header-value)))
+               (notmuch-show-insert-header header header-value))))
          notmuch-message-headers)
     (save-excursion
       (save-restriction
        (narrow-to-region start (point-max))
        (run-hooks 'notmuch-show-markup-headers-hook)))))
 
          notmuch-message-headers)
     (save-excursion
       (save-restriction
        (narrow-to-region start (point-max))
        (run-hooks 'notmuch-show-markup-headers-hook)))))
 
+;;; Parts
+
 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
   'follow-link t
 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
   'follow-link t
@@ -505,21 +515,17 @@ message at DEPTH in the current thread."
 
 (defun notmuch-show-insert-part-header (nth content-type declared-type
                                            &optional name comment)
 
 (defun notmuch-show-insert-part-header (nth content-type declared-type
                                            &optional name comment)
-  (let ((button)
-       (base-label (concat (when name (concat name ": "))
+  (let ((base-label (concat (and name (concat name ": "))
                            declared-type
                            declared-type
-                           (unless (string-equal declared-type content-type)
-                             (concat " (as " content-type ")"))
+                           (and (not (string-equal declared-type content-type))
+                                (concat " (as " content-type ")"))
                            comment)))
                            comment)))
-    (setq button
-         (insert-button
-          (concat "[ " base-label " ]")
-          :base-label base-label
-          :type 'notmuch-show-part-button-type
-          :notmuch-part-hidden nil))
-    (insert "\n")
-    ;; return button
-    button))
+    (prog1 (insert-button
+           (concat "[ " base-label " ]")
+           :base-label base-label
+           :type 'notmuch-show-part-button-type
+           :notmuch-part-hidden nil)
+      (insert "\n"))))
 
 (defun notmuch-show-toggle-part-invisibility (&optional button)
   (interactive)
 
 (defun notmuch-show-toggle-part-invisibility (&optional button)
   (interactive)
@@ -556,7 +562,7 @@ message at DEPTH in the current thread."
              (overlay-put overlay 'invisible (not show))
              t)))))))
 
              (overlay-put overlay 'invisible (not show))
              t)))))))
 
-;; Part content ID handling
+;;; Part content ID handling
 
 (defvar notmuch-show--cids nil
   "Alist from raw content ID to (MSG PART).")
 
 (defvar notmuch-show--cids nil
   "Alist from raw content ID to (MSG PART).")
@@ -575,12 +581,13 @@ message at DEPTH in the current thread."
       ;; alternative (even if we can't render it).
       (push (list content-id msg part) notmuch-show--cids)))
   ;; Recurse on sub-parts
       ;; alternative (even if we can't render it).
       (push (list content-id msg part) notmuch-show--cids)))
   ;; Recurse on sub-parts
-  (let ((ctype (notmuch-split-content-type
-               (downcase (plist-get part :content-type)))))
-    (cond ((equal (car ctype) "multipart")
+  (pcase-let ((`(,content ,type)
+              (split-string (downcase (plist-get part :content-type)) "/")))
+    (cond ((equal content "multipart")
           (mapc (apply-partially #'notmuch-show--register-cids msg)
                 (plist-get part :content)))
           (mapc (apply-partially #'notmuch-show--register-cids msg)
                 (plist-get part :content)))
-         ((equal ctype '("message" "rfc822"))
+         ((and (equal content "message")
+               (equal type "rfc822"))
           (notmuch-show--register-cids
            msg
            (car (plist-get (car (plist-get part :content)) :body)))))))
           (notmuch-show--register-cids
            msg
            (car (plist-get (car (plist-get part :content)) :body)))))))
@@ -606,10 +613,10 @@ will return nil if the CID is unknown or cannot be retrieved."
 (defun notmuch-show-setup-w3m ()
   "Instruct w3m how to retrieve content from a \"related\" part of a message."
   (interactive)
 (defun notmuch-show-setup-w3m ()
   "Instruct w3m how to retrieve content from a \"related\" part of a message."
   (interactive)
-  (if (boundp 'w3m-cid-retrieve-function-alist)
-      (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)
-       (push (cons 'notmuch-show-mode #'notmuch-show--cid-w3m-retrieve)
-             w3m-cid-retrieve-function-alist)))
+  (when (and (boundp 'w3m-cid-retrieve-function-alist)
+            (not (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)))
+    (push (cons 'notmuch-show-mode #'notmuch-show--cid-w3m-retrieve)
+         w3m-cid-retrieve-function-alist))
   (setq mm-html-inhibit-images nil))
 
 (defvar w3m-current-buffer) ;; From `w3m.el'.
   (setq mm-html-inhibit-images nil))
 
 (defvar w3m-current-buffer) ;; From `w3m.el'.
@@ -767,38 +774,35 @@ will return nil if the CID is unknown or cannot be retrieved."
 (defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth depth button)
   (notmuch-show-insert-part-text/calendar msg part content-type nth depth button))
 
 (defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth depth button)
   (notmuch-show-insert-part-text/calendar msg part content-type nth depth button))
 
-(if (version< emacs-version "25.3")
-    ;; https://bugs.gnu.org/28350
-    ;;
-    ;; For newer emacs, we fall back to notmuch-show-insert-part-*/*
-    ;; (see notmuch-show-handlers-for)
-    (defun notmuch-show-insert-part-text/enriched
-       (msg part content-type nth depth button)
-      ;; By requiring enriched below, we ensure that the function
-      ;; enriched-decode-display-prop is defined before it will be
-      ;; shadowed by the letf below. Otherwise the version in
-      ;; enriched.el may be loaded a bit later and used instead (for
-      ;; the first time).
-      (require 'enriched)
-      (cl-letf (((symbol-function 'enriched-decode-display-prop)
-                (lambda (start end &optional param) (list start end))))
-       (notmuch-show-insert-part-*/* msg part content-type nth depth button))))
+(when (version< emacs-version "25.3")
+  ;; https://bugs.gnu.org/28350
+  ;;
+  ;; For newer emacs, we fall back to notmuch-show-insert-part-*/*
+  ;; (see notmuch-show-handlers-for)
+  (defun notmuch-show-insert-part-text/enriched
+      (msg part content-type nth depth button)
+    ;; By requiring enriched below, we ensure that the function
+    ;; enriched-decode-display-prop is defined before it will be
+    ;; shadowed by the letf below. Otherwise the version in
+    ;; enriched.el may be loaded a bit later and used instead (for
+    ;; the first time).
+    (require 'enriched)
+    (cl-letf (((symbol-function 'enriched-decode-display-prop)
+              (lambda (start end &optional param) (list start end))))
+      (notmuch-show-insert-part-*/* msg part content-type nth depth button))))
 
 (defun notmuch-show-get-mime-type-of-application/octet-stream (part)
   ;; If we can deduce a MIME type from the filename of the attachment,
   ;; we return that.
 
 (defun notmuch-show-get-mime-type-of-application/octet-stream (part)
   ;; If we can deduce a MIME type from the filename of the attachment,
   ;; we return that.
-  (if (plist-get part :filename)
-      (let ((extension (file-name-extension (plist-get part :filename)))
-           mime-type)
-       (if extension
-           (progn
-             (mailcap-parse-mimetypes)
-             (setq mime-type (mailcap-extension-to-mime extension))
-             (if (and mime-type
-                      (not (string-equal mime-type "application/octet-stream")))
-                 mime-type
-               nil))
-         nil))))
+  (and (plist-get part :filename)
+       (let ((extension (file-name-extension (plist-get part :filename))))
+        (and extension
+             (progn
+               (mailcap-parse-mimetypes)
+               (let ((mime-type (mailcap-extension-to-mime extension)))
+                 (and mime-type
+                      (not (string-equal mime-type "application/octet-stream"))
+                      mime-type)))))))
 
 (defun notmuch-show-insert-part-text/html (msg part content-type nth depth button)
   (if (eq mm-text-html-renderer 'shr)
 
 (defun notmuch-show-insert-part-text/html (msg part content-type nth depth button)
   (if (eq mm-text-html-renderer 'shr)
@@ -821,7 +825,8 @@ will return nil if the CID is unknown or cannot be retrieved."
          (gnus-blocked-images notmuch-show-text/html-blocked-images))
       (notmuch-show-insert-part-*/* msg part content-type nth depth button))))
 
          (gnus-blocked-images notmuch-show-text/html-blocked-images))
       (notmuch-show-insert-part-*/* msg part content-type nth depth button))))
 
-;; These functions are used by notmuch-show--insert-part-text/html-shr
+;;; Functions used by notmuch-show--insert-part-text/html-shr
+
 (declare-function libxml-parse-html-region "xml.c")
 (declare-function shr-insert-document "shr")
 
 (declare-function libxml-parse-html-region "xml.c")
 (declare-function shr-insert-document "shr")
 
@@ -846,24 +851,23 @@ will return nil if the CID is unknown or cannot be retrieved."
   (notmuch-mm-display-part-inline msg part content-type notmuch-show-process-crypto)
   t)
 
   (notmuch-mm-display-part-inline msg part content-type notmuch-show-process-crypto)
   t)
 
-;; Functions for determining how to handle MIME parts.
+;;; Functions for determining how to handle MIME parts.
 
 (defun notmuch-show-handlers-for (content-type)
   "Return a list of content handlers for a part of type CONTENT-TYPE."
   (let (result)
     (mapc (lambda (func)
 
 (defun notmuch-show-handlers-for (content-type)
   "Return a list of content handlers for a part of type CONTENT-TYPE."
   (let (result)
     (mapc (lambda (func)
-           (if (functionp func)
-               (push func result)))
+           (when (functionp func)
+             (push func result)))
          ;; Reverse order of prefrence.
          (list (intern (concat "notmuch-show-insert-part-*/*"))
          ;; Reverse order of prefrence.
          (list (intern (concat "notmuch-show-insert-part-*/*"))
-               (intern (concat
-                        "notmuch-show-insert-part-"
-                        (car (notmuch-split-content-type content-type))
-                        "/*"))
+               (intern (concat "notmuch-show-insert-part-"
+                               (car (split-string content-type "/"))
+                               "/*"))
                (intern (concat "notmuch-show-insert-part-" content-type))))
     result))
 
                (intern (concat "notmuch-show-insert-part-" content-type))))
     result))
 
-;; \f
+;;; Parts
 
 (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth button)
   ;; Run the handlers until one of them succeeds.
 
 (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth button)
   ;; Run the handlers until one of them succeeds.
@@ -997,9 +1001,10 @@ is t, hide the part initially and show the button."
         (beg (point))
         ;; This default header-p function omits the part button for
         ;; the first (or only) part if this is text/plain.
         (beg (point))
         ;; This default header-p function omits the part button for
         ;; the first (or only) part if this is text/plain.
-        (button (when (funcall notmuch-show-insert-header-p-function part hide)
-                  (notmuch-show-insert-part-header nth mime-type content-type
-                                                   (plist-get part :filename))))
+        (button (and (funcall notmuch-show-insert-header-p-function part hide)
+                     (notmuch-show-insert-part-header
+                      nth mime-type content-type
+                      (plist-get part :filename))))
         ;; Hide the part initially if HIDE is t, or if it is too long
         ;; and we have a button to allow toggling.
         (show-part (not (or (equal hide t)
         ;; Hide the part initially if HIDE is t, or if it is too long
         ;; and we have a button to allow toggling.
         (show-part (not (or (equal hide t)
@@ -1054,9 +1059,8 @@ is t, hide the part initially and show the button."
         (bare-subject (notmuch-show-strip-re (plist-get headers :Subject))))
     (setq message-start (point-marker))
     (notmuch-show-insert-headerline headers
         (bare-subject (notmuch-show-strip-re (plist-get headers :Subject))))
     (setq message-start (point-marker))
     (notmuch-show-insert-headerline headers
-                                   (or (if notmuch-show-relative-dates
-                                           (plist-get msg :date_relative)
-                                         nil)
+                                   (or (and notmuch-show-relative-dates
+                                            (plist-get msg :date_relative))
                                        (plist-get headers :Date))
                                    (plist-get msg :tags) depth)
     (setq content-start (point-marker))
                                        (plist-get headers :Date))
                                    (plist-get msg :tags) depth)
     (setq content-start (point-marker))
@@ -1069,8 +1073,7 @@ is t, hide the part initially and show the button."
       ;; If the subject of this message is the same as that of the
       ;; previous message, don't display it when this message is
       ;; collapsed.
       ;; If the subject of this message is the same as that of the
       ;; previous message, don't display it when this message is
       ;; collapsed.
-      (when (not (string= notmuch-show-previous-subject
-                         bare-subject))
+      (unless (string= notmuch-show-previous-subject bare-subject)
        (forward-line 1))
       (setq headers-start (point-marker)))
     (setq headers-end (point-marker))
        (forward-line 1))
       (setq headers-start (point-marker)))
     (setq headers-end (point-marker))
@@ -1084,10 +1087,10 @@ is t, hide the part initially and show the button."
       (insert "\n"))
     (setq content-end (point-marker))
     ;; Indent according to the depth in the thread.
       (insert "\n"))
     (setq content-end (point-marker))
     ;; Indent according to the depth in the thread.
-    (if notmuch-show-indent-content
-       (indent-rigidly content-start
-                       content-end
-                       (* notmuch-show-indent-messages-width depth)))
+    (when notmuch-show-indent-content
+      (indent-rigidly content-start
+                     content-end
+                     (* notmuch-show-indent-messages-width depth)))
     (setq message-end (point-max-marker))
     ;; Save the extents of this message over the whole text of the
     ;; message.
     (setq message-end (point-max-marker))
     ;; Save the extents of this message over the whole text of the
     ;; message.
@@ -1110,6 +1113,8 @@ is t, hide the part initially and show the button."
     (notmuch-show-message-visible msg (and (plist-get msg :match)
                                           (not (plist-get msg :excluded))))))
 
     (notmuch-show-message-visible msg (and (plist-get msg :match)
                                           (not (plist-get msg :excluded))))))
 
+;;; Toggle commands
+
 (defun notmuch-show-toggle-process-crypto ()
   "Toggle the processing of cryptographic MIME parts."
   (interactive)
 (defun notmuch-show-toggle-process-crypto ()
   "Toggle the processing of cryptographic MIME parts."
   (interactive)
@@ -1138,6 +1143,8 @@ is t, hide the part initially and show the button."
             "Content is not indented."))
   (notmuch-show-refresh-view))
 
             "Content is not indented."))
   (notmuch-show-refresh-view))
 
+;;; Main insert functions
+
 (defun notmuch-show-insert-tree (tree depth)
   "Insert the message tree TREE at depth DEPTH in the current thread."
   (let ((msg (car tree))
 (defun notmuch-show-insert-tree (tree depth)
   "Insert the message tree TREE at depth DEPTH in the current thread."
   (let ((msg (car tree))
@@ -1155,6 +1162,8 @@ is t, hide the part initially and show the button."
   "Insert the forest of threads FOREST."
   (mapc (lambda (thread) (notmuch-show-insert-thread thread 0)) forest))
 
   "Insert the forest of threads FOREST."
   (mapc (lambda (thread) (notmuch-show-insert-thread thread 0)) forest))
 
+;;; Link buttons
+
 (defvar notmuch-id-regexp
   (concat
    ;; Match the id: prefix only if it begins a word (to disallow, for
 (defvar notmuch-id-regexp
   (concat
    ;; Match the id: prefix only if it begins a word (to disallow, for
@@ -1215,6 +1224,8 @@ buttons for a corresponding notmuch search."
                          'help-echo "Mouse-1, RET: search for this message"
                          'face goto-address-mail-face)))))
 
                          'help-echo "Mouse-1, RET: search for this message"
                          'face goto-address-mail-face)))))
 
+;;; Show command
+
 ;;;###autoload
 (defun notmuch-show (thread-id &optional elide-toggle parent-buffer query-context buffer-name)
   "Run \"notmuch show\" with the given thread ID and display results.
 ;;;###autoload
 (defun notmuch-show (thread-id &optional elide-toggle parent-buffer query-context buffer-name)
   "Run \"notmuch show\" with the given thread ID and display results.
@@ -1249,21 +1260,23 @@ matched."
                    (eval (car (get 'mm-inline-override-types 'standard-value))))
             (cons "application/*" mm-inline-override-types)
           mm-inline-override-types)))
                    (eval (car (get 'mm-inline-override-types 'standard-value))))
             (cons "application/*" mm-inline-override-types)
           mm-inline-override-types)))
-    (switch-to-buffer (get-buffer-create buffer-name))
+    (pop-to-buffer-same-window (get-buffer-create buffer-name))
     ;; No need to track undo information for this buffer.
     (setq buffer-undo-list t)
     (notmuch-show-mode)
     ;; Set various buffer local variables to their appropriate initial
     ;; state. Do this after enabling `notmuch-show-mode' so that they
     ;; aren't wiped out.
     ;; No need to track undo information for this buffer.
     (setq buffer-undo-list t)
     (notmuch-show-mode)
     ;; Set various buffer local variables to their appropriate initial
     ;; state. Do this after enabling `notmuch-show-mode' so that they
     ;; aren't wiped out.
-    (setq notmuch-show-thread-id thread-id
-         notmuch-show-parent-buffer parent-buffer
-         notmuch-show-query-context (if (or (string= query-context "")
-                                            (string= query-context "*"))
-                                        nil query-context)
-         notmuch-show-process-crypto notmuch-crypto-process-mime
-         ;; If `elide-toggle', invert the default value.
-         notmuch-show-elide-non-matching-messages
+    (setq notmuch-show-thread-id thread-id)
+    (setq notmuch-show-parent-buffer parent-buffer)
+    (setq notmuch-show-query-context
+         (if (or (string= query-context "")
+                 (string= query-context "*"))
+             nil
+           query-context))
+    (setq notmuch-show-process-crypto notmuch-crypto-process-mime)
+    ;; If `elide-toggle', invert the default value.
+    (setq notmuch-show-elide-non-matching-messages
          (if elide-toggle
              (not notmuch-show-only-matching-messages)
            notmuch-show-only-matching-messages))
          (if elide-toggle
              (not notmuch-show-only-matching-messages)
            notmuch-show-only-matching-messages))
@@ -1290,7 +1303,8 @@ and THREAD.  The next query is THREAD alone, and serves as a
 fallback if the prior matches no messages."
   (let (queries)
     (push (list thread) queries)
 fallback if the prior matches no messages."
   (let (queries)
     (push (list thread) queries)
-    (if context (push (list thread "and (" context ")") queries))
+    (when context
+      (push (list thread "and (" context ")") queries))
     queries))
 
 (defun notmuch-show--build-buffer (&optional state)
     queries))
 
 (defun notmuch-show--build-buffer (&optional state)
@@ -1301,8 +1315,8 @@ first relevant message.
 
 If no messages match the query return NIL."
   (let* ((cli-args (cons "--exclude=false"
 
 If no messages match the query return NIL."
   (let* ((cli-args (cons "--exclude=false"
-                        (when notmuch-show-elide-non-matching-messages
-                          (list "--entire-thread=false"))))
+                        (and notmuch-show-elide-non-matching-messages
+                             (list "--entire-thread=false"))))
         (queries (notmuch-show--build-queries
                   notmuch-show-thread-id notmuch-show-query-context))
         (forest nil)
         (queries (notmuch-show--build-queries
                   notmuch-show-thread-id notmuch-show-query-context))
         (forest nil)
@@ -1334,6 +1348,8 @@ If no messages match the query return NIL."
     ;; Report back to the caller whether any messages matched.
     forest))
 
     ;; Report back to the caller whether any messages matched.
     forest))
 
+;;; Refresh command
+
 (defun notmuch-show-capture-state ()
   "Capture the state of the current buffer.
 
 (defun notmuch-show-capture-state ()
   "Capture the state of the current buffer.
 
@@ -1408,6 +1424,8 @@ reset based on the original query."
       (ding)
       (message "Refreshing the buffer resulted in no messages!"))))
 
       (ding)
       (message "Refreshing the buffer resulted in no messages!"))))
 
+;;; Keymaps
+
 (defvar notmuch-show-stash-map
   (let ((map (make-sparse-keymap)))
     (define-key map "c" 'notmuch-show-stash-cc)
 (defvar notmuch-show-stash-map
   (let ((map (make-sparse-keymap)))
     (define-key map "c" 'notmuch-show-stash-cc)
@@ -1487,7 +1505,8 @@ reset based on the original query."
     (define-key map "B" 'notmuch-show-browse-urls)
     map)
   "Keymap for \"notmuch show\" buffers.")
     (define-key map "B" 'notmuch-show-browse-urls)
     map)
   "Keymap for \"notmuch show\" buffers.")
-(fset 'notmuch-show-mode-map notmuch-show-mode-map)
+
+;;; Mode
 
 (define-derived-mode notmuch-show-mode fundamental-mode "notmuch-show"
   "Major mode for viewing a thread with notmuch.
 
 (define-derived-mode notmuch-show-mode fundamental-mode "notmuch-show"
   "Major mode for viewing a thread with notmuch.
@@ -1518,13 +1537,15 @@ All currently available key bindings:
 
 \\{notmuch-show-mode-map}"
   (setq notmuch-buffer-refresh-function #'notmuch-show-refresh-view)
 
 \\{notmuch-show-mode-map}"
   (setq notmuch-buffer-refresh-function #'notmuch-show-refresh-view)
-  (setq buffer-read-only t
-       truncate-lines t)
+  (setq buffer-read-only t)
+  (setq truncate-lines t)
   (setq imenu-prev-index-position-function
        #'notmuch-show-imenu-prev-index-position-function)
   (setq imenu-extract-index-name-function
        #'notmuch-show-imenu-extract-index-name-function))
 
   (setq imenu-prev-index-position-function
        #'notmuch-show-imenu-prev-index-position-function)
   (setq imenu-extract-index-name-function
        #'notmuch-show-imenu-extract-index-name-function))
 
+;;; Tree commands
+
 (defun notmuch-tree-from-show-current-query ()
   "Call notmuch tree with the current query."
   (interactive)
 (defun notmuch-tree-from-show-current-query ()
   "Call notmuch tree with the current query."
   (interactive)
@@ -1539,17 +1560,14 @@ All currently available key bindings:
                      notmuch-show-query-context
                      (notmuch-show-get-message-id)))
 
                      notmuch-show-query-context
                      (notmuch-show-get-message-id)))
 
+;;; Movement related functions.
+
 (defun notmuch-show-move-to-message-top ()
   (goto-char (notmuch-show-message-top)))
 
 (defun notmuch-show-move-to-message-bottom ()
   (goto-char (notmuch-show-message-bottom)))
 
 (defun notmuch-show-move-to-message-top ()
   (goto-char (notmuch-show-message-top)))
 
 (defun notmuch-show-move-to-message-bottom ()
   (goto-char (notmuch-show-message-bottom)))
 
-(defun notmuch-show-message-adjust ()
-  (recenter 0))
-
-;; Movement related functions.
-
 ;; There's some strangeness here where a text property applied to a
 ;; region a->b is not found when point is at b. We walk backwards
 ;; until finding the property.
 ;; There's some strangeness here where a text property applied to a
 ;; region a->b is not found when point is at b. We walk backwards
 ;; until finding the property.
@@ -1593,8 +1611,7 @@ effects."
     (cl-loop do (funcall function)
             while (notmuch-show-goto-message-next))))
 
     (cl-loop do (funcall function)
             while (notmuch-show-goto-message-next))))
 
-;; Functions relating to the visibility of messages and their
-;; components.
+;;; Functions relating to the visibility of messages and their components.
 
 (defun notmuch-show-message-visible (props visible-p)
   (overlay-put (plist-get props :message-overlay) 'invisible (not visible-p))
 
 (defun notmuch-show-message-visible (props visible-p)
   (overlay-put (plist-get props :message-overlay) 'invisible (not visible-p))
@@ -1604,8 +1621,7 @@ effects."
   (overlay-put (plist-get props :headers-overlay) 'invisible (not visible-p))
   (notmuch-show-set-prop :headers-visible visible-p props))
 
   (overlay-put (plist-get props :headers-overlay) 'invisible (not visible-p))
   (notmuch-show-set-prop :headers-visible visible-p props))
 
-;; Functions for setting and getting attributes of the current
-;; message.
+;;; Functions for setting and getting attributes of the current message.
 
 (defun notmuch-show-set-message-properties (props)
   (save-excursion
 
 (defun notmuch-show-set-message-properties (props)
   (save-excursion
@@ -1761,7 +1777,7 @@ user decision and we should not override it."
          (funcall notmuch-show-mark-read-function (window-start) (window-end))
        ((debug error)
         (unless notmuch-show--seen-has-errored
          (funcall notmuch-show-mark-read-function (window-start) (window-end))
        ((debug error)
         (unless notmuch-show--seen-has-errored
-          (setq notmuch-show--seen-has-errored 't)
+          (setq notmuch-show--seen-has-errored t)
           (setq header-line-format
                 (concat header-line-format
                         (propertize
           (setq header-line-format
                 (concat header-line-format
                         (propertize
@@ -1778,8 +1794,7 @@ Reshows the current thread with matches defined by the new query-string."
     (notmuch-show-refresh-view t)
     (notmuch-show-goto-message msg-id)))
 
     (notmuch-show-refresh-view t)
     (notmuch-show-goto-message msg-id)))
 
-;; Functions for getting attributes of several messages in the current
-;; thread.
+;;; Functions for getting attributes of several messages in the current thread.
 
 (defun notmuch-show-get-message-ids-for-open-messages ()
   "Return a list of all id: queries for open messages in the current thread."
 
 (defun notmuch-show-get-message-ids-for-open-messages ()
   "Return a list of all id: queries for open messages in the current thread."
@@ -1787,13 +1802,13 @@ Reshows the current thread with matches defined by the new query-string."
     (let (message-ids done)
       (goto-char (point-min))
       (while (not done)
     (let (message-ids done)
       (goto-char (point-min))
       (while (not done)
-       (if (notmuch-show-message-visible-p)
-           (setq message-ids
-                 (append message-ids (list (notmuch-show-get-message-id)))))
+       (when (notmuch-show-message-visible-p)
+         (setq message-ids
+               (append message-ids (list (notmuch-show-get-message-id)))))
        (setq done (not (notmuch-show-goto-message-next))))
       message-ids)))
 
        (setq done (not (notmuch-show-goto-message-next))))
       message-ids)))
 
-;; Commands typically bound to keys.
+;;; Commands typically bound to keys.
 
 (defun notmuch-show-advance ()
   "Advance through thread.
 
 (defun notmuch-show-advance ()
   "Advance through thread.
@@ -1844,8 +1859,8 @@ archives the entire current thread, (apply changes in
 thread from the search from which this thread was originally
 shown."
   (interactive)
 thread from the search from which this thread was originally
 shown."
   (interactive)
-  (if (notmuch-show-advance)
-      (notmuch-show-archive-thread-then-next)))
+  (when (notmuch-show-advance)
+    (notmuch-show-archive-thread-then-next)))
 
 (defun notmuch-show-rewind ()
   "Backup through the thread (reverse scrolling compared to \
 
 (defun notmuch-show-rewind ()
   "Backup through the thread (reverse scrolling compared to \
@@ -1921,6 +1936,9 @@ any effects from previous calls to
     (message-resend addresses)
     (notmuch-bury-or-kill-this-buffer)))
 
     (message-resend addresses)
     (notmuch-bury-or-kill-this-buffer)))
 
+(defun notmuch-show-message-adjust ()
+  (recenter 0))
+
 (defun notmuch-show-next-message (&optional pop-at-end)
   "Show the next message.
 
 (defun notmuch-show-next-message (&optional pop-at-end)
   "Show the next message.
 
@@ -2003,7 +2021,7 @@ to show, nil otherwise."
   (let* ((id (notmuch-show-get-message-id))
         (buf (get-buffer-create (concat "*notmuch-raw-" id "*")))
         (inhibit-read-only t))
   (let* ((id (notmuch-show-get-message-id))
         (buf (get-buffer-create (concat "*notmuch-raw-" id "*")))
         (inhibit-read-only t))
-    (switch-to-buffer buf)
+    (pop-to-buffer-same-window buf)
     (erase-buffer)
     (let ((coding-system-for-read 'no-conversion))
       (call-process notmuch-command nil t nil "show" "--format=raw" id))
     (erase-buffer)
     (let ((coding-system-for-read 'no-conversion))
       (call-process notmuch-command nil t nil "show" "--format=raw" id))
@@ -2062,7 +2080,7 @@ message."
          (set-buffer-modified-p nil)
          (setq buffer-read-only t)
          (unless (zerop exit-code)
          (set-buffer-modified-p nil)
          (setq buffer-read-only t)
          (unless (zerop exit-code)
-           (switch-to-buffer-other-window buf)
+           (pop-to-buffer buf)
            (message (format "Command '%s' exited abnormally with code %d"
                             shell-command exit-code))))))))
 
            (message (format "Command '%s' exited abnormally with code %d"
                             shell-command exit-code))))))))
 
@@ -2351,7 +2369,9 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
   (browse-url (current-kill 0 t)))
 
 (defun notmuch-show-stash-git-helper (addresses prefix)
   (browse-url (current-kill 0 t)))
 
 (defun notmuch-show-stash-git-helper (addresses prefix)
-  "Escape, trim, quote, and add PREFIX to each address in list of ADDRESSES, and return the result as a single string."
+  "Normalize all ADDRESSES while adding PREFIX.
+Escape, trim, quote and add PREFIX to each address in list
+of ADDRESSES, and return the result as a single string."
   (mapconcat (lambda (x)
               (concat prefix "\""
                       ;; escape double-quotes
   (mapconcat (lambda (x)
               (concat prefix "\""
                       ;; escape double-quotes
@@ -2364,10 +2384,12 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
             addresses " "))
 
 (put 'notmuch-show-stash-git-send-email 'notmuch-prefix-doc
             addresses " "))
 
 (put 'notmuch-show-stash-git-send-email 'notmuch-prefix-doc
-     "Copy From/To/Cc of current message to kill-ring in a form suitable for pasting to git send-email command line.")
+     "Copy From/To/Cc of current message to kill-ring.
+Use a form suitable for pasting to git send-email command line.")
 
 (defun notmuch-show-stash-git-send-email (&optional no-in-reply-to)
 
 (defun notmuch-show-stash-git-send-email (&optional no-in-reply-to)
-  "Copy From/To/Cc/Message-Id of current message to kill-ring in a form suitable for pasting to git send-email command line.
+  "Copy From/To/Cc/Message-Id of current message to kill-ring.
+Use a form suitable for pasting to git send-email command line.
 
 If invoked with a prefix argument (or NO-IN-REPLY-TO is non-nil),
 omit --in-reply-to=<Message-Id>."
 
 If invoked with a prefix argument (or NO-IN-REPLY-TO is non-nil),
 omit --in-reply-to=<Message-Id>."
@@ -2387,7 +2409,7 @@ omit --in-reply-to=<Message-Id>."
                          (list (notmuch-show-get-message-id t)) "--in-reply-to="))))
              " ")))
 
                          (list (notmuch-show-get-message-id t)) "--in-reply-to="))))
              " ")))
 
-;; Interactive part functions and their helpers
+;;; Interactive part functions and their helpers
 
 (defun notmuch-show-generate-part-buffer (msg part)
   "Return a temporary buffer containing the specified part's content."
 
 (defun notmuch-show-generate-part-buffer (msg part)
   "Return a temporary buffer containing the specified part's content."
@@ -2410,7 +2432,7 @@ MIME-TYPE is given then set the handle's mime-type to MIME-TYPE."
         (buf (notmuch-show-generate-part-buffer msg part))
         (computed-type (or mime-type (plist-get part :computed-type)))
         (filename (plist-get part :filename))
         (buf (notmuch-show-generate-part-buffer msg part))
         (computed-type (or mime-type (plist-get part :computed-type)))
         (filename (plist-get part :filename))
-        (disposition (if filename `(attachment (filename . ,filename)))))
+        (disposition (and filename `(attachment (filename . ,filename)))))
     (mm-make-handle buf (list computed-type) nil nil disposition)))
 
 (defun notmuch-show-apply-to-current-part-handle (fn &optional mime-type)
     (mm-make-handle buf (list computed-type) nil nil disposition)))
 
 (defun notmuch-show-apply-to-current-part-handle (fn &optional mime-type)
@@ -2420,10 +2442,9 @@ This ensures that the temporary buffer created for the mm-handle
 is destroyed when FN returns. If MIME-TYPE is given then force
 part to be treated as if it had that mime-type."
   (let ((handle (notmuch-show-current-part-handle mime-type)))
 is destroyed when FN returns. If MIME-TYPE is given then force
 part to be treated as if it had that mime-type."
   (let ((handle (notmuch-show-current-part-handle mime-type)))
-    ;; emacs 24.3+ puts stdout/stderr into the calling buffer so we
-    ;; call it from a temp-buffer, unless
-    ;; notmuch-show-attachment-debug is non-nil in which case we put
-    ;; it in " *notmuch-part*".
+    ;; Emacs puts stdout/stderr into the calling buffer so we call
+    ;; it from a temp-buffer, unless notmuch-show-attachment-debug
+    ;; is non-nil, in which case we put it in " *notmuch-part*".
     (unwind-protect
        (if notmuch-show-attachment-debug
            (with-current-buffer (generate-new-buffer " *notmuch-part*")
     (unwind-protect
        (if notmuch-show-attachment-debug
            (with-current-buffer (generate-new-buffer " *notmuch-part*")
@@ -2470,7 +2491,7 @@ If the part is displayed in an external application then close
 the new buffer."
   (let ((buf (get-buffer-create (generate-new-buffer-name
                                 (concat " *notmuch-internal-part*")))))
 the new buffer."
   (let ((buf (get-buffer-create (generate-new-buffer-name
                                 (concat " *notmuch-internal-part*")))))
-    (switch-to-buffer buf)
+    (pop-to-buffer-same-window buf)
     (if (eq (mm-display-part handle) 'external)
        (kill-buffer buf)
       (goto-char (point-min))
     (if (eq (mm-display-part handle) 'external)
        (kill-buffer buf)
       (goto-char (point-min))
@@ -2535,6 +2556,8 @@ browsing."
        (funcall fn (completing-read prompt urls nil nil nil nil (car urls)))
       (message "No URLs found."))))
 
        (funcall fn (completing-read prompt urls nil nil nil nil (car urls)))
       (message "No URLs found."))))
 
+;;; _
+
 (provide 'notmuch-show)
 
 ;;; notmuch-show.el ends here
 (provide 'notmuch-show)
 
 ;;; notmuch-show.el ends here