]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch.el
emacs: use lexical-bindings in all libraries
[notmuch] / emacs / notmuch.el
index 93e92b391fde9753ae6d15f4a869fc19f89fb995..ba9488ca42d5b80f1e69a21843718274c063f96a 100644 (file)
@@ -1,4 +1,4 @@
-;;; notmuch.el --- run notmuch within emacs
+;;; notmuch.el --- run notmuch within emacs  -*- lexical-binding: t -*-
 ;;
 ;; Copyright © Carl Worth
 ;;
 ;;
 ;; Copyright © Carl Worth
 ;;
@@ -18,7 +18,7 @@
 ;; along with Notmuch.  If not, see <https://www.gnu.org/licenses/>.
 ;;
 ;; Authors: Carl Worth <cworth@cworth.org>
 ;; along with Notmuch.  If not, see <https://www.gnu.org/licenses/>.
 ;;
 ;; Authors: Carl Worth <cworth@cworth.org>
-;; Homepage: https://notmuchmail.org/
+;; Homepage: https://notmuchmail.org
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
@@ -62,7 +62,7 @@
 ;;
 ;; TL;DR: notmuch-emacs from MELPA and notmuch from distro packages is
 ;; NOT SUPPORTED.
 ;;
 ;; TL;DR: notmuch-emacs from MELPA and notmuch from distro packages is
 ;; NOT SUPPORTED.
-;;
+
 ;;; Code:
 
 (eval-when-compile (require 'cl-lib))
 ;;; Code:
 
 (eval-when-compile (require 'cl-lib))
@@ -80,6 +80,8 @@
 (require 'notmuch-message)
 (require 'notmuch-parser)
 
 (require 'notmuch-message)
 (require 'notmuch-parser)
 
+;;; Options
+
 (defcustom notmuch-search-result-format
   `(("date" . "%12s ")
     ("count" . "%-7s ")
 (defcustom notmuch-search-result-format
   `(("date" . "%12s ")
     ("count" . "%-7s ")
@@ -115,6 +117,8 @@ there will be called at other points of notmuch execution."
 (defvar notmuch-query-history nil
   "Variable to store minibuffer history for notmuch queries.")
 
 (defvar notmuch-query-history nil
   "Variable to store minibuffer history for notmuch queries.")
 
+;;; Mime Utilities
+
 (defun notmuch-foreach-mime-part (function mm-handle)
   (cond ((stringp (car mm-handle))
         (dolist (part (cdr mm-handle))
 (defun notmuch-foreach-mime-part (function mm-handle)
   (cond ((stringp (car mm-handle))
         (dolist (part (cdr mm-handle))
@@ -151,6 +155,8 @@ there will be called at other points of notmuch execution."
            (mm-save-part p))))
    mm-handle))
 
            (mm-save-part p))))
    mm-handle))
 
+;;; Integrations
+
 (require 'hl-line)
 
 (defun notmuch-hl-line-mode ()
 (require 'hl-line)
 
 (defun notmuch-hl-line-mode ()
@@ -158,6 +164,8 @@ there will be called at other points of notmuch execution."
     (when hl-line-overlay
       (overlay-put hl-line-overlay 'priority 1))))
 
     (when hl-line-overlay
       (overlay-put hl-line-overlay 'priority 1))))
 
+;;; Options
+
 (defcustom notmuch-search-hook '(notmuch-hl-line-mode)
   "List of functions to call when notmuch displays the search results."
   :type 'hook
 (defcustom notmuch-search-hook '(notmuch-hl-line-mode)
   "List of functions to call when notmuch displays the search results."
   :type 'hook
@@ -165,6 +173,8 @@ there will be called at other points of notmuch execution."
   :group 'notmuch-search
   :group 'notmuch-hooks)
 
   :group 'notmuch-search
   :group 'notmuch-hooks)
 
+;;; Keymap
+
 (defvar notmuch-search-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map notmuch-common-keymap)
 (defvar notmuch-search-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map notmuch-common-keymap)
@@ -194,7 +204,8 @@ there will be called at other points of notmuch execution."
     (define-key map "U" 'notmuch-unthreaded-from-search-current-query)
     map)
   "Keymap for \"notmuch search\" buffers.")
     (define-key map "U" 'notmuch-unthreaded-from-search-current-query)
     map)
   "Keymap for \"notmuch search\" buffers.")
-(fset 'notmuch-search-mode-map notmuch-search-mode-map)
+
+;;; Stashing
 
 (defvar notmuch-search-stash-map
   (let ((map (make-sparse-keymap)))
 
 (defvar notmuch-search-stash-map
   (let ((map (make-sparse-keymap)))
@@ -215,12 +226,16 @@ there will be called at other points of notmuch execution."
   (interactive)
   (notmuch-common-do-stash (notmuch-search-get-query)))
 
   (interactive)
   (notmuch-common-do-stash (notmuch-search-get-query)))
 
+;;; Variables
+
 (defvar notmuch-search-query-string)
 (defvar notmuch-search-target-thread)
 (defvar notmuch-search-target-line)
 
 (defvar notmuch-search-disjunctive-regexp      "\\<[oO][rR]\\>")
 
 (defvar notmuch-search-query-string)
 (defvar notmuch-search-target-thread)
 (defvar notmuch-search-target-line)
 
 (defvar notmuch-search-disjunctive-regexp      "\\<[oO][rR]\\>")
 
+;;; Movement
+
 (defun notmuch-search-scroll-up ()
   "Move forward through search results by one window's worth."
   (interactive)
 (defun notmuch-search-scroll-up ()
   "Move forward through search results by one window's worth."
   (interactive)
@@ -272,9 +287,15 @@ there will be called at other points of notmuch execution."
   (interactive)
   (goto-char (point-min)))
 
   (interactive)
   (goto-char (point-min)))
 
+;;; Faces
+
 (defface notmuch-message-summary-face
 (defface notmuch-message-summary-face
-  '((((class color) (background light)) (:background "#f0f0f0"))
-    (((class color) (background dark)) (:background "#303030")))
+  `((((class color) (background light))
+     ,@(and (>= emacs-major-version 27) '(:extend t))
+     :background "#f0f0f0")
+    (((class color) (background dark))
+     ,@(and (>= emacs-major-version 27) '(:extend t))
+     :background "#303030"))
   "Face for the single-line message summary in notmuch-show-mode."
   :group 'notmuch-show
   :group 'notmuch-faces)
   "Face for the single-line message summary in notmuch-show-mode."
   :group 'notmuch-show
   :group 'notmuch-faces)
@@ -339,7 +360,7 @@ there will be called at other points of notmuch execution."
   "Face used in search mode face for flagged threads.
 
 This face is the default value for the \"flagged\" tag in
   "Face used in search mode face for flagged threads.
 
 This face is the default value for the \"flagged\" tag in
-`notmuch-search-line-faces`."
+`notmuch-search-line-faces'."
   :group 'notmuch-search
   :group 'notmuch-faces)
 
   :group 'notmuch-search
   :group 'notmuch-faces)
 
@@ -349,10 +370,12 @@ This face is the default value for the \"flagged\" tag in
   "Face used in search mode for unread threads.
 
 This face is the default value for the \"unread\" tag in
   "Face used in search mode for unread threads.
 
 This face is the default value for the \"unread\" tag in
-`notmuch-search-line-faces`."
+`notmuch-search-line-faces'."
   :group 'notmuch-search
   :group 'notmuch-faces)
 
   :group 'notmuch-search
   :group 'notmuch-faces)
 
+;;; Mode
+
 (define-derived-mode notmuch-search-mode fundamental-mode "notmuch-search"
   "Major mode displaying results of a notmuch search.
 
 (define-derived-mode notmuch-search-mode fundamental-mode "notmuch-search"
   "Major mode displaying results of a notmuch search.
 
@@ -388,7 +411,7 @@ Complete list of currently available key bindings:
   (make-local-variable 'notmuch-search-target-thread)
   (make-local-variable 'notmuch-search-target-line)
   (setq notmuch-buffer-refresh-function #'notmuch-search-refresh-view)
   (make-local-variable 'notmuch-search-target-thread)
   (make-local-variable 'notmuch-search-target-line)
   (setq notmuch-buffer-refresh-function #'notmuch-search-refresh-view)
-  (set (make-local-variable 'scroll-preserve-screen-position) t)
+  (setq-local scroll-preserve-screen-position t)
   (add-to-invisibility-spec (cons 'ellipsis t))
   (setq truncate-lines t)
   (setq buffer-read-only t)
   (add-to-invisibility-spec (cons 'ellipsis t))
   (setq truncate-lines t)
   (setq buffer-read-only t)
@@ -397,6 +420,8 @@ Complete list of currently available key bindings:
   (setq imenu-extract-index-name-function
        #'notmuch-search-imenu-extract-index-name-function))
 
   (setq imenu-extract-index-name-function
        #'notmuch-search-imenu-extract-index-name-function))
 
+;;; Search Results
+
 (defun notmuch-search-get-result (&optional pos)
   "Return the result object for the thread at POS (or point).
 
 (defun notmuch-search-get-result (&optional pos)
   "Return the result object for the thread at POS (or point).
 
@@ -428,11 +453,10 @@ returns nil."
 (defun notmuch-search-foreach-result (beg end fn)
   "Invoke FN for each result between BEG and END.
 
 (defun notmuch-search-foreach-result (beg end fn)
   "Invoke FN for each result between BEG and END.
 
-FN should take one argument.  It will be applied to the
-character position of the beginning of each result that overlaps
-the region between points BEG and END.  As a special case, if (=
-BEG END), FN will be applied to the result containing point
-BEG."
+FN should take one argument.  It will be applied to the character
+position of the beginning of each result that overlaps the region
+between points BEG and END.  As a special case, if (= BEG END),
+FN will be applied to the result containing point BEG."
   (let ((pos (notmuch-search-result-beginning beg))
        ;; End must be a marker in case fn changes the
        ;; text.
   (let ((pos (notmuch-search-result-beginning beg))
        ;; End must be a marker in case fn changes the
        ;; text.
@@ -542,7 +566,7 @@ thread."
                notmuch-search-query-string
                nil
                (notmuch-prettify-subject (notmuch-search-find-subject))
                notmuch-search-query-string
                nil
                (notmuch-prettify-subject (notmuch-search-find-subject))
-               t))
+               t nil (current-buffer)))
 
 (defun notmuch-search-reply-to-thread (&optional prompt-for-sender)
   "Begin composing a reply-all to the entire current thread in a new buffer."
 
 (defun notmuch-search-reply-to-thread (&optional prompt-for-sender)
   "Begin composing a reply-all to the entire current thread in a new buffer."
@@ -556,6 +580,8 @@ thread."
   (let ((message-id (notmuch-search-find-thread-id)))
     (notmuch-mua-new-reply message-id prompt-for-sender nil)))
 
   (let ((message-id (notmuch-search-find-thread-id)))
     (notmuch-mua-new-reply message-id prompt-for-sender nil)))
 
+;;; Tags
+
 (defun notmuch-search-set-tags (tags &optional pos)
   (let ((new-result (plist-put (notmuch-search-get-result pos) :tags tags)))
     (notmuch-search-update-result new-result pos)))
 (defun notmuch-search-set-tags (tags &optional pos)
   (let ((new-result (plist-put (notmuch-search-get-result pos) :tags tags)))
     (notmuch-search-update-result new-result pos)))
@@ -637,6 +663,8 @@ This function advances the next thread when finished."
   (when (eq beg end)
     (notmuch-search-next-thread)))
 
   (when (eq beg end)
     (notmuch-search-next-thread)))
 
+;;; Search Results
+
 (defun notmuch-search-update-result (result &optional pos)
   "Replace the result object of the thread at POS (or point) by
 RESULT and redraw it.
 (defun notmuch-search-update-result (result &optional pos)
   "Replace the result object of the thread at POS (or point) by
 RESULT and redraw it.
@@ -674,28 +702,28 @@ of the result."
     (when (memq status '(exit signal))
       (catch 'return
        (kill-buffer (process-get proc 'parse-buf))
     (when (memq status '(exit signal))
       (catch 'return
        (kill-buffer (process-get proc 'parse-buf))
-       (if (buffer-live-p buffer)
-           (with-current-buffer buffer
-             (save-excursion
-               (let ((inhibit-read-only t)
-                     (atbob (bobp)))
-                 (goto-char (point-max))
-                 (if (eq status 'signal)
-                     (insert "Incomplete search results (search process was killed).\n"))
-                 (when (eq status 'exit)
-                   (insert "End of search results.\n")
-                   ;; For version mismatch, there's no point in
-                   ;; showing the search buffer
-                   (when (or (= exit-status 20) (= exit-status 21))
-                     (kill-buffer)
-                     (throw 'return nil))
-                   (if (and atbob
+       (when (buffer-live-p buffer)
+         (with-current-buffer buffer
+           (save-excursion
+             (let ((inhibit-read-only t)
+                   (atbob (bobp)))
+               (goto-char (point-max))
+               (when (eq status 'signal)
+                 (insert "Incomplete search results (search process was killed).\n"))
+               (when (eq status 'exit)
+                 (insert "End of search results.\n")
+                 ;; For version mismatch, there's no point in
+                 ;; showing the search buffer
+                 (when (or (= exit-status 20) (= exit-status 21))
+                   (kill-buffer)
+                   (throw 'return nil))
+                 (when (and atbob
                             (not (string= notmuch-search-target-thread "found")))
                             (not (string= notmuch-search-target-thread "found")))
-                       (set 'never-found-target-thread t)))))
-             (when (and never-found-target-thread
-                        notmuch-search-target-line)
-               (goto-char (point-min))
-               (forward-line (1- notmuch-search-target-line)))))))))
+                   (setq never-found-target-thread t)))))
+           (when (and never-found-target-thread
+                      notmuch-search-target-line)
+             (goto-char (point-min))
+             (forward-line (1- notmuch-search-target-line)))))))))
 
 (define-widget 'notmuch--custom-face-edit 'lazy
   "Custom face edit with a tag Edit Face"
 
 (define-widget 'notmuch--custom-face-edit 'lazy
   "Custom face edit with a tag Edit Face"
@@ -760,31 +788,31 @@ non-authors is found, assume that all of the authors match."
           (invisible-string "")
           (padding ""))
       ;; Truncate the author string to fit the specification.
           (invisible-string "")
           (padding ""))
       ;; Truncate the author string to fit the specification.
-      (if (> (length formatted-authors)
-            (length formatted-sample))
-         (let ((visible-length (- (length formatted-sample)
-                                  (length "... "))))
-           ;; Truncate the visible string according to the width of
-           ;; the display string.
-           (setq visible-string (substring formatted-authors 0 visible-length))
-           (setq invisible-string (substring formatted-authors visible-length))
-           ;; If possible, truncate the visible string at a natural
-           ;; break (comma or pipe), as incremental search doesn't
-           ;; match across the visible/invisible border.
-           (when (string-match "\\(.*\\)\\([,|] \\)\\([^,|]*\\)" visible-string)
-             ;; Second clause is destructive on `visible-string', so
-             ;; order is important.
-             (setq invisible-string (concat (match-string 3 visible-string)
-                                            invisible-string))
-             (setq visible-string (concat (match-string 1 visible-string)
-                                          (match-string 2 visible-string))))
-           ;; `visible-string' may be shorter than the space allowed
-           ;; by `format-string'. If so we must insert some padding
-           ;; after `invisible-string'.
-           (setq padding (make-string (- (length formatted-sample)
-                                         (length visible-string)
-                                         (length "..."))
-                                      ? ))))
+      (when (> (length formatted-authors)
+              (length formatted-sample))
+       (let ((visible-length (- (length formatted-sample)
+                                (length "... "))))
+         ;; Truncate the visible string according to the width of
+         ;; the display string.
+         (setq visible-string (substring formatted-authors 0 visible-length))
+         (setq invisible-string (substring formatted-authors visible-length))
+         ;; If possible, truncate the visible string at a natural
+         ;; break (comma or pipe), as incremental search doesn't
+         ;; match across the visible/invisible border.
+         (when (string-match "\\(.*\\)\\([,|] \\)\\([^,|]*\\)" visible-string)
+           ;; Second clause is destructive on `visible-string', so
+           ;; order is important.
+           (setq invisible-string (concat (match-string 3 visible-string)
+                                          invisible-string))
+           (setq visible-string (concat (match-string 1 visible-string)
+                                        (match-string 2 visible-string))))
+         ;; `visible-string' may be shorter than the space allowed
+         ;; by `format-string'. If so we must insert some padding
+         ;; after `invisible-string'.
+         (setq padding (make-string (- (length formatted-sample)
+                                       (length visible-string)
+                                       (length "..."))
+                                    ? ))))
       ;; Use different faces to show matching and non-matching authors.
       (if (string-match "\\(.*\\)|\\(.*\\)" visible-string)
          ;; The visible string contains both matching and
       ;; Use different faces to show matching and non-matching authors.
       (if (string-match "\\(.*\\)|\\(.*\\)" visible-string)
          ;; The visible string contains both matching and
@@ -879,6 +907,8 @@ sets the :orig-tag property."
        (notmuch-sexp-parse-partial-list 'notmuch-search-append-result
                                         results-buf)))))
 
        (notmuch-sexp-parse-partial-list 'notmuch-search-append-result
                                         results-buf)))))
 
+;;; Commands (and some helper functions used by them)
+
 (defun notmuch-search-tag-all (tag-changes)
   "Add/remove tags from all messages in current search buffer.
 
 (defun notmuch-search-tag-all (tag-changes)
   "Add/remove tags from all messages in current search buffer.
 
@@ -991,23 +1021,19 @@ the configured default sort order."
         (buffer (get-buffer-create (notmuch-search-buffer-title query))))
     (if no-display
        (set-buffer buffer)
         (buffer (get-buffer-create (notmuch-search-buffer-title query))))
     (if no-display
        (set-buffer buffer)
-      (switch-to-buffer buffer))
-    ;; avoid wiping out third party buffer-local variables in the case
-    ;; where we're just refreshing or changing the sort order of an
-    ;; existing search results buffer
-    (unless (eq major-mode 'notmuch-search-mode)
-      (notmuch-search-mode))
+      (pop-to-buffer-same-window buffer))
+    (notmuch-search-mode)
     ;; Don't track undo information for this buffer
     ;; Don't track undo information for this buffer
-    (set 'buffer-undo-list t)
-    (set 'notmuch-search-query-string query)
-    (set 'notmuch-search-oldest-first oldest-first)
-    (set 'notmuch-search-target-thread target-thread)
-    (set 'notmuch-search-target-line target-line)
+    (setbuffer-undo-list t)
+    (setnotmuch-search-query-string query)
+    (setnotmuch-search-oldest-first oldest-first)
+    (setnotmuch-search-target-thread target-thread)
+    (setnotmuch-search-target-line target-line)
     (notmuch-tag-clear-cache)
     (let ((proc (get-buffer-process (current-buffer)))
          (inhibit-read-only t))
     (notmuch-tag-clear-cache)
     (let ((proc (get-buffer-process (current-buffer)))
          (inhibit-read-only t))
-      (if proc
-         (error "notmuch search process already running for query `%s'" query))
+      (when proc
+       (error "notmuch search process already running for query `%s'" query))
       (erase-buffer)
       (goto-char (point-min))
       (save-excursion
       (erase-buffer)
       (goto-char (point-min))
       (save-excursion
@@ -1050,7 +1076,7 @@ same relative position within the new buffer."
 This command toggles the sort order for the current search. The
 default sort order is defined by `notmuch-search-oldest-first'."
   (interactive)
 This command toggles the sort order for the current search. The
 default sort order is defined by `notmuch-search-oldest-first'."
   (interactive)
-  (set 'notmuch-search-oldest-first (not notmuch-search-oldest-first))
+  (setnotmuch-search-oldest-first (not notmuch-search-oldest-first))
   (notmuch-search-refresh-view))
 
 (defun notmuch-group-disjunctive-query-string (query-string)
   (notmuch-search-refresh-view))
 
 (defun notmuch-group-disjunctive-query-string (query-string)
@@ -1131,10 +1157,10 @@ notmuch buffers exist, run `notmuch'."
        ;; If the first one we found is any other than the starting
        ;; buffer, switch to it.
        (unless (eq first start)
        ;; If the first one we found is any other than the starting
        ;; buffer, switch to it.
        (unless (eq first start)
-         (switch-to-buffer first))
+         (pop-to-buffer-same-window first))
       (notmuch))))
 
       (notmuch))))
 
-;;;; Imenu Support
+;;; Imenu Support
 
 (defun notmuch-search-imenu-prev-index-position-function ()
   "Move point to previous message in notmuch-search buffer.
 
 (defun notmuch-search-imenu-prev-index-position-function ()
   "Move point to previous message in notmuch-search buffer.
@@ -1151,12 +1177,14 @@ beginning of the line."
        (author (notmuch-search-find-authors)))
     (format "%s (%s)" subject author)))
 
        (author (notmuch-search-find-authors)))
     (format "%s (%s)" subject author)))
 
+;;; _
+
 (setq mail-user-agent 'notmuch-user-agent)
 
 (provide 'notmuch)
 
 ;; After provide to avoid loops if notmuch was require'd via notmuch-init-file.
 (setq mail-user-agent 'notmuch-user-agent)
 
 (provide 'notmuch)
 
 ;; After provide to avoid loops if notmuch was require'd via notmuch-init-file.
-(if init-file-user ; don't load init file if the -q option was used.
-    (load notmuch-init-file t t nil t))
+(when init-file-user ; don't load init file if the -q option was used.
+  (load notmuch-init-file t t nil t))
 
 ;;; notmuch.el ends here
 
 ;;; notmuch.el ends here