]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch-show.el
emacs: use lexical-bindings in all libraries
[notmuch] / emacs / notmuch-show.el
index 4520d4790efa956f3b885a697fab23a0ea6eb2af..72e21d94387c698739e7cc435d34d13ce40598d1 100644 (file)
@@ -1,4 +1,4 @@
-;;; notmuch-show.el --- displaying notmuch forests.
+;;; notmuch-show.el --- displaying notmuch forests  -*- lexical-binding: t -*-
 ;;
 ;; Copyright © Carl Worth
 ;; Copyright © David Edmondson
 (declare-function notmuch-read-query "notmuch" (prompt))
 (declare-function notmuch-draft-resume "notmuch-draft" (id))
 
+(defvar shr-blocked-images)
+(defvar gnus-blocked-images)
+(defvar shr-content-function)
+
+;;; Options
+
 (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")
   "Headers that should be shown in a message, in this order.
 
@@ -162,23 +168,19 @@ indentation."
   :type '(choice (const nil) regexp)
   :group 'notmuch-show)
 
-(defvar notmuch-show-thread-id nil)
-(make-variable-buffer-local 'notmuch-show-thread-id)
+;;; Variables
 
-(defvar notmuch-show-parent-buffer nil)
-(make-variable-buffer-local 'notmuch-show-parent-buffer)
+(defvar-local notmuch-show-thread-id nil)
 
-(defvar notmuch-show-query-context nil)
-(make-variable-buffer-local 'notmuch-show-query-context)
+(defvar-local notmuch-show-parent-buffer nil)
 
-(defvar notmuch-show-process-crypto nil)
-(make-variable-buffer-local 'notmuch-show-process-crypto)
+(defvar-local notmuch-show-query-context nil)
 
-(defvar notmuch-show-elide-non-matching-messages nil)
-(make-variable-buffer-local 'notmuch-show-elide-non-matching-messages)
+(defvar-local notmuch-show-process-crypto nil)
 
-(defvar notmuch-show-indent-content t)
-(make-variable-buffer-local 'notmuch-show-indent-content)
+(defvar-local notmuch-show-elide-non-matching-messages nil)
+
+(defvar-local notmuch-show-indent-content t)
 
 (defvar notmuch-show-attachment-debug nil
   "If t log stdout and stderr from attachment handlers.
@@ -186,8 +188,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
-\" *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/")
@@ -267,12 +270,14 @@ position of the message in the thread."
   :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
      (let ((id (notmuch-show-get-message-id)))
        (let ((buf (generate-new-buffer (concat "*notmuch-msg-" id "*"))))
-         (with-current-buffer buf
+        (with-current-buffer buf
           (let ((coding-system-for-read 'no-conversion))
             (call-process notmuch-command nil t nil "show" "--format=raw" id))
           ,@body)
@@ -282,6 +287,8 @@ position of the message in the thread."
   "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.
@@ -297,13 +304,12 @@ position of the message in the thread."
    ;;
    ;; Any MIME part not explicitly mentioned here will be handled by an
    ;; external viewer as configured in the various mailcap files.
-   (let ((mm-inline-media-tests '(
-                                 ("text/.*" ignore identity)
-                                 ("application/pgp-signature" ignore identity)
-                                 ("multipart/alternative" ignore identity)
-                                 ("multipart/mixed" ignore identity)
-                                 ("multipart/related" ignore identity)
-                                )))
+   (let ((mm-inline-media-tests
+         '(("text/.*" ignore identity)
+           ("application/pgp-signature" ignore identity)
+           ("multipart/alternative" ignore identity)
+           ("multipart/mixed" ignore identity)
+           ("multipart/related" ignore identity))))
      (mm-display-parts (mm-dissect-buffer)))))
 
 (defun notmuch-show-save-attachments ()
@@ -347,10 +353,10 @@ operation on the contents of the current buffer."
         (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)
@@ -363,6 +369,8 @@ operation on the contents of the current buffer."
   (interactive)
   (notmuch-show-with-message-as-text 'notmuch-print-message))
 
+;;; Headers
+
 (defun notmuch-show-fontify-header ()
   (let ((face (cond
               ((looking-at "[Tt]o:")
@@ -393,61 +401,62 @@ operation on the contents of the current buffer."
   "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
 cell of (AUTHOR_EMAIL AUTHOR_NAME). Return (ADDRESS nil) if
 parsing fails."
   (condition-case nil
-    (let (p-name p-address)
-      ;; It would be convenient to use `mail-header-parse-address',
-      ;; but that expects un-decoded mailbox parts, whereas our
-      ;; mailbox parts are already decoded (and hence may contain
-      ;; UTF-8). Given that notmuch should handle most of the awkward
-      ;; cases, some simple string deconstruction should be sufficient
-      ;; here.
-      (cond
-       ;; "User <user@dom.ain>" style.
-       ((string-match "\\(.*\\) <\\(.*\\)>" address)
-       (setq p-name (match-string 1 address)
-             p-address (match-string 2 address)))
-       ;; "<user@dom.ain>" style.
-       ((string-match "<\\(.*\\)>" address)
-       (setq p-address (match-string 1 address)))
-       ;; Everything else.
-       (t
-       (setq p-address address)))
-      (when p-name
-       ;; Remove elements of the mailbox part that are not relevant for
-       ;; display, even if they are required during transport:
-       ;;
-       ;; Backslashes.
-       (setq p-name (replace-regexp-in-string "\\\\" "" p-name))
-       ;; Outer single and double quotes, which might be nested.
-       (cl-loop with start-of-loop
-                do   (setq start-of-loop p-name)
-                when (string-match "^\"\\(.*\\)\"$" p-name)
-                do   (setq p-name (match-string 1 p-name))
-                when (string-match "^'\\(.*\\)'$" p-name)
-                do   (setq p-name (match-string 1 p-name))
-                until (string= start-of-loop p-name)))
-      ;; If the address is 'foo@bar.com <foo@bar.com>' then show just
-      ;; 'foo@bar.com'.
-      (when (string= p-name p-address)
-       (setq p-name nil))
-      (cons p-address p-name))
+      (let (p-name p-address)
+       ;; It would be convenient to use `mail-header-parse-address',
+       ;; but that expects un-decoded mailbox parts, whereas our
+       ;; mailbox parts are already decoded (and hence may contain
+       ;; UTF-8). Given that notmuch should handle most of the awkward
+       ;; cases, some simple string deconstruction should be sufficient
+       ;; here.
+       (cond
+        ;; "User <user@dom.ain>" style.
+        ((string-match "\\(.*\\) <\\(.*\\)>" address)
+         (setq p-name (match-string 1 address))
+         (setq p-address (match-string 2 address)))
+
+        ;; "<user@dom.ain>" style.
+        ((string-match "<\\(.*\\)>" address)
+         (setq p-address (match-string 1 address)))
+        ;; Everything else.
+        (t
+         (setq p-address address)))
+       (when p-name
+         ;; Remove elements of the mailbox part that are not relevant for
+         ;; display, even if they are required during transport:
+         ;;
+         ;; Backslashes.
+         (setq p-name (replace-regexp-in-string "\\\\" "" p-name))
+         ;; Outer single and double quotes, which might be nested.
+         (cl-loop with start-of-loop
+                  do   (setq start-of-loop p-name)
+                  when (string-match "^\"\\(.*\\)\"$" p-name)
+                  do   (setq p-name (match-string 1 p-name))
+                  when (string-match "^'\\(.*\\)'$" p-name)
+                  do   (setq p-name (match-string 1 p-name))
+                  until (string= start-of-loop p-name)))
+       ;; If the address is 'foo@bar.com <foo@bar.com>' then show just
+       ;; 'foo@bar.com'.
+       (when (string= p-name p-address)
+         (setq p-name nil))
+       (cons p-address p-name))
     (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)))
@@ -468,7 +477,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)))
-    (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
@@ -488,15 +500,17 @@ message at DEPTH in the current thread."
     (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)))))
 
+;;; Parts
+
 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
   'follow-link t
@@ -505,21 +519,17 @@ message at DEPTH in the current thread."
 
 (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
-                           (unless (string-equal declared-type content-type)
-                             (concat " (as " content-type ")"))
+                           (and (not (string-equal declared-type content-type))
+                                (concat " (as " content-type ")"))
                            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)
@@ -556,7 +566,7 @@ message at DEPTH in the current thread."
              (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).")
@@ -575,12 +585,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
-  (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)))
-         ((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)))))))
@@ -606,10 +617,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)
-  (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'.
@@ -639,8 +650,8 @@ will return nil if the CID is unknown or cannot be retrieved."
     ;; should be chosen if there are more than one that match?
     (mapc (lambda (inner-part)
            (let* ((inner-type (plist-get inner-part :content-type))
-                 (hide (not (or notmuch-show-all-multipart/alternative-parts
-                          (string= chosen-type inner-type)))))
+                  (hide (not (or notmuch-show-all-multipart/alternative-parts
+                                 (string= chosen-type inner-type)))))
              (notmuch-show-insert-bodypart msg inner-part depth hide)))
          inner-parts)
 
@@ -767,38 +778,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))
 
-(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.
-  (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)
@@ -821,7 +829,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))))
 
-;; 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")
 
@@ -846,24 +855,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)
 
-;; 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)
-           (if (functionp func)
-               (push func result)))
+           (when (functionp func)
+             (push func result)))
          ;; 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))
 
-;; \f
+;;; Parts
 
 (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth button)
   ;; Run the handlers until one of them succeeds.
@@ -997,9 +1005,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.
-        (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)
@@ -1008,7 +1017,7 @@ is t, hide the part initially and show the button."
     ;; Store the computed mime-type for later use (e.g. by attachment handlers).
     (plist-put part :computed-type mime-type)
     (if show-part
-        (notmuch-show-insert-bodypart-internal msg part mime-type nth depth button)
+       (notmuch-show-insert-bodypart-internal msg part mime-type nth depth button)
       (when button
        (button-put button :notmuch-lazy-part
                    (list msg part mime-type nth depth button))))
@@ -1054,9 +1063,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
-                                   (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))
@@ -1069,8 +1077,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.
-      (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))
@@ -1084,10 +1091,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.
-    (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.
@@ -1110,6 +1117,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))))))
 
+;;; Toggle commands
+
 (defun notmuch-show-toggle-process-crypto ()
   "Toggle the processing of cryptographic MIME parts."
   (interactive)
@@ -1138,6 +1147,8 @@ is t, hide the part initially and show the button."
             "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))
@@ -1155,6 +1166,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))
 
+;;; Link buttons
+
 (defvar notmuch-id-regexp
   (concat
    ;; Match the id: prefix only if it begins a word (to disallow, for
@@ -1215,6 +1228,8 @@ buttons for a corresponding notmuch search."
                          '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.
@@ -1249,21 +1264,23 @@ matched."
                    (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.
-    (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))
@@ -1290,7 +1307,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)
-    (if context (push (list thread "and (" context ")") queries))
+    (when context
+      (push (list thread "and (" context ")") queries))
     queries))
 
 (defun notmuch-show--build-buffer (&optional state)
@@ -1301,8 +1319,8 @@ first relevant message.
 
 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)
@@ -1334,6 +1352,8 @@ If no messages match the query return NIL."
     ;; Report back to the caller whether any messages matched.
     forest))
 
+;;; Refresh command
+
 (defun notmuch-show-capture-state ()
   "Capture the state of the current buffer.
 
@@ -1408,6 +1428,8 @@ reset based on the original query."
       (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)
@@ -1487,7 +1509,8 @@ reset based on the original query."
     (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.
@@ -1518,12 +1541,14 @@ All currently available key bindings:
 
 \\{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)
+       #'notmuch-show-imenu-prev-index-position-function)
   (setq imenu-extract-index-name-function
-        #'notmuch-show-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."
@@ -1539,17 +1564,14 @@ All currently available key bindings:
                      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-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.
@@ -1593,8 +1615,7 @@ effects."
     (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))
@@ -1604,8 +1625,7 @@ effects."
   (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
@@ -1746,8 +1766,8 @@ We only mark it read once: if it is changed back then that is a
 user decision and we should not override it."
   (when (and (notmuch-show-message-visible-p)
             (not (notmuch-show-get-prop :seen)))
-       (notmuch-show-mark-read)
-       (notmuch-show-set-prop :seen t)))
+    (notmuch-show-mark-read)
+    (notmuch-show-set-prop :seen t)))
 
 (defvar notmuch-show--seen-has-errored nil)
 (make-variable-buffer-local 'notmuch-show--seen-has-errored)
@@ -1761,7 +1781,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
-          (setq notmuch-show--seen-has-errored 't)
+          (setq notmuch-show--seen-has-errored t)
           (setq header-line-format
                 (concat header-line-format
                         (propertize
@@ -1778,8 +1798,7 @@ Reshows the current thread with matches defined by the new query-string."
     (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."
@@ -1787,15 +1806,13 @@ Reshows the current thread with matches defined by the new query-string."
     (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)))))
-       (setq done (not (notmuch-show-goto-message-next)))
-       )
-      message-ids
-      )))
+       (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)))
 
-;; Commands typically bound to keys.
+;;; Commands typically bound to keys.
 
 (defun notmuch-show-advance ()
   "Advance through thread.
@@ -1846,8 +1863,8 @@ archives the entire current thread, (apply changes in
 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 \
@@ -1866,9 +1883,9 @@ any effects from previous calls to
   (let ((start-of-message (notmuch-show-message-top))
        (start-of-window (window-start)))
     (cond
-      ;; Either this message is properly aligned with the start of the
-      ;; window or the start of this message is not visible on the
-      ;; screen - scroll.
+     ;; Either this message is properly aligned with the start of the
+     ;; window or the start of this message is not visible on the
+     ;; screen - scroll.
      ((or (= start-of-message start-of-window)
          (< start-of-message start-of-window))
       (scroll-down)
@@ -1923,6 +1940,9 @@ any effects from previous calls to
     (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.
 
@@ -2005,7 +2025,7 @@ to show, nil otherwise."
   (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))
@@ -2064,7 +2084,7 @@ message."
          (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))))))))
 
@@ -2353,7 +2373,9 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
   (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
@@ -2366,10 +2388,12 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
             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)
-  "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>."
@@ -2389,7 +2413,7 @@ omit --in-reply-to=<Message-Id>."
                          (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."
@@ -2412,7 +2436,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))
-        (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)
@@ -2422,10 +2446,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)))
-    ;; 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*")
@@ -2472,7 +2495,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*")))))
-    (switch-to-buffer buf)
+    (pop-to-buffer-same-window buf)
     (if (eq (mm-display-part handle) 'external)
        (kill-buffer buf)
       (goto-char (point-min))
@@ -2512,9 +2535,9 @@ beginning of the line."
 message."
   `(save-excursion
      (save-restriction
-      (let ((extent (notmuch-show-message-extent)))
-       (narrow-to-region (car extent) (cdr extent))
-       ,@body))))
+       (let ((extent (notmuch-show-message-extent)))
+        (narrow-to-region (car extent) (cdr extent))
+        ,@body))))
 
 (defun notmuch-show--gather-urls ()
   "Gather any URLs in the current message."
@@ -2537,6 +2560,8 @@ browsing."
        (funcall fn (completing-read prompt urls nil nil nil nil (car urls)))
       (message "No URLs found."))))
 
+;;; _
+
 (provide 'notmuch-show)
 
 ;;; notmuch-show.el ends here