X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=emacs%2Fnotmuch-tree.el;h=6812d7e9204e5918d377b02a4298d099cb6b90a1;hp=ebfb5e7b8c2a449be91453a20079a211d472441f;hb=b6f87c3085e25e5bf65a4f956af8846bc0681c52;hpb=66612063813c8c6179eb06dd83a75be6c427b215 diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index ebfb5e7b..6812d7e9 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -1,4 +1,4 @@ -;; notmuch-tree.el --- displaying notmuch forests. +;;; notmuch-tree.el --- displaying notmuch forests. ;; ;; Copyright © Carl Worth ;; Copyright © David Edmondson @@ -17,11 +17,13 @@ ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with Notmuch. If not, see . +;; along with Notmuch. If not, see . ;; ;; Authors: David Edmondson ;; Mark Walters +;;; Code: + (require 'mail-parse) (require 'notmuch-lib) @@ -70,8 +72,14 @@ Note the author string should not contain :group 'notmuch-tree) ;; Faces for messages that match the query. -(defface notmuch-tree-match-date-face +(defface notmuch-tree-match-face '((t :inherit default)) + "Default face used in tree mode face for matching messages" + :group 'notmuch-tree + :group 'notmuch-faces) + +(defface notmuch-tree-match-date-face + nil "Face used in tree mode for the date in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) @@ -90,13 +98,13 @@ Note the author string should not contain :group 'notmuch-faces) (defface notmuch-tree-match-subject-face - '((t :inherit default)) + nil "Face used in tree mode for the subject in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) (defface notmuch-tree-match-tree-face - '((t :inherit default)) + nil "Face used in tree mode for the thread tree block graphics in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) @@ -115,32 +123,38 @@ Note the author string should not contain :group 'notmuch-faces) ;; Faces for messages that do not match the query. -(defface notmuch-tree-no-match-date-face +(defface notmuch-tree-no-match-face '((t (:foreground "gray"))) + "Default face used in tree mode face for non-matching messages" + :group 'notmuch-tree + :group 'notmuch-faces) + +(defface notmuch-tree-no-match-date-face + nil "Face used in tree mode for non-matching dates." :group 'notmuch-tree :group 'notmuch-faces) (defface notmuch-tree-no-match-subject-face - '((t (:foreground "gray"))) + nil "Face used in tree mode for non-matching subjects." :group 'notmuch-tree :group 'notmuch-faces) (defface notmuch-tree-no-match-tree-face - '((t (:foreground "gray"))) + nil "Face used in tree mode for the thread tree block graphics in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) (defface notmuch-tree-no-match-author-face - '((t (:foreground "gray"))) + nil "Face used in tree mode for the date in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) (defface notmuch-tree-no-match-tag-face - '((t (:foreground "gray"))) + nil "Face used in tree mode face for non-matching tags." :group 'notmuch-tree :group 'notmuch-faces) @@ -195,6 +209,13 @@ open (if the message pane is closed it does nothing)." (with-selected-window notmuch-tree-message-window (call-interactively #',func))))) +(defun notmuch-tree-inherit-from-message-pane (sym) + "Return value of SYM in message-pane if open, or tree-pane if not" + (if (window-live-p notmuch-tree-message-window) + (with-selected-window notmuch-tree-message-window + (symbol-value sym)) + (symbol-value sym))) + (defun notmuch-tree-button-activate (&optional button) "Activate BUTTON or button at point @@ -212,33 +233,40 @@ FUNC." `(lambda () ,(concat "(Close message pane and) " (documentation func t)) (interactive) - (notmuch-tree-close-message-window) - (call-interactively #',func))) + (let ((notmuch-show-process-crypto + (notmuch-tree-inherit-from-message-pane 'notmuch-show-process-crypto))) + (notmuch-tree-close-message-window) + (call-interactively #',func)))) (defvar notmuch-tree-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map notmuch-common-keymap) ;; The following override the global keymap. ;; Override because we want to close message pane first. - (define-key map "?" (notmuch-tree-close-message-pane-and #'notmuch-help)) + (define-key map [remap notmuch-help] (notmuch-tree-close-message-pane-and #'notmuch-help)) ;; Override because we first close message pane and then close tree buffer. - (define-key map "q" 'notmuch-tree-quit) + (define-key map [remap notmuch-bury-or-kill-this-buffer] 'notmuch-tree-quit) ;; Override because we close message pane after the search query is entered. - (define-key map "s" 'notmuch-tree-to-search) + (define-key map [remap notmuch-search] 'notmuch-tree-to-search) ;; Override because we want to close message pane first. - (define-key map "m" (notmuch-tree-close-message-pane-and #'notmuch-mua-new-mail)) + (define-key map [remap notmuch-mua-new-mail] (notmuch-tree-close-message-pane-and #'notmuch-mua-new-mail)) + ;; Override because we want to close message pane first. + (define-key map [remap notmuch-jump-search] (notmuch-tree-close-message-pane-and #'notmuch-jump-search)) + + (define-key map "S" 'notmuch-search-from-tree-current-query) ;; these use notmuch-show functions directly (define-key map "|" 'notmuch-show-pipe-message) (define-key map "w" 'notmuch-show-save-attachments) (define-key map "v" 'notmuch-show-view-all-mime-parts) (define-key map "c" 'notmuch-show-stash-map) + (define-key map "b" 'notmuch-show-resend-message) ;; these apply to the message pane (define-key map (kbd "M-TAB") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "TAB") (notmuch-tree-to-message-pane #'notmuch-show-next-button)) - (define-key map "e" (notmuch-tree-to-message-pane #'notmuch-tree-button-activate)) + (define-key map "$" (notmuch-tree-to-message-pane #'notmuch-show-toggle-process-crypto)) ;; bindings from show (or elsewhere) but we close the message pane first. (define-key map "f" (notmuch-tree-close-message-pane-and #'notmuch-show-forward-message)) @@ -252,7 +280,6 @@ FUNC." (define-key map "x" 'notmuch-tree-quit) (define-key map "A" 'notmuch-tree-archive-thread) (define-key map "a" 'notmuch-tree-archive-message-then-next) - (define-key map "=" 'notmuch-tree-refresh-view) (define-key map "z" 'notmuch-tree-to-tree) (define-key map "n" 'notmuch-tree-next-matching-message) (define-key map "p" 'notmuch-tree-prev-matching-message) @@ -260,11 +287,13 @@ FUNC." (define-key map "P" 'notmuch-tree-prev-message) (define-key map (kbd "M-p") 'notmuch-tree-prev-thread) (define-key map (kbd "M-n") 'notmuch-tree-next-thread) + (define-key map "k" 'notmuch-tag-jump) (define-key map "-" 'notmuch-tree-remove-tag) (define-key map "+" 'notmuch-tree-add-tag) (define-key map "*" 'notmuch-tree-tag-thread) (define-key map " " 'notmuch-tree-scroll-or-next) - (define-key map "b" 'notmuch-tree-scroll-message-window-back) + (define-key map (kbd "DEL") 'notmuch-tree-scroll-message-window-back) + (define-key map "e" 'notmuch-tree-resume-message) map)) (fset 'notmuch-tree-mode-map notmuch-tree-mode-map) @@ -278,22 +307,6 @@ Some useful entries are: (beginning-of-line) (get-text-property (point) :notmuch-message-properties))) -;; XXX This should really be a lib function but we are trying to -;; reduce impact on the code base. -(defun notmuch-show-get-prop (prop &optional props) - "This is a tree view overridden version of notmuch-show-get-prop - -It gets property PROP from PROPS or, if PROPS is nil, the current -message in either tree or show. This means that several functions -in notmuch-show now work unchanged in tree as they just need the -correct message properties." - (let ((props (or props - (cond ((eq major-mode 'notmuch-show-mode) - (notmuch-show-get-message-properties)) - ((eq major-mode 'notmuch-tree-mode) - (notmuch-tree-get-message-properties)))))) - (plist-get props prop))) - (defun notmuch-tree-set-message-properties (props) (save-excursion (beginning-of-line) @@ -319,11 +332,13 @@ correct message properties." "Return the tags of the current message." (notmuch-tree-get-prop :tags)) -(defun notmuch-tree-get-message-id () +(defun notmuch-tree-get-message-id (&optional bare) "Return the message id of the current message." (let ((id (notmuch-tree-get-prop :id))) (if id - (notmuch-id-to-query id) + (if bare + id + (notmuch-id-to-query id)) nil))) (defun notmuch-tree-get-match () @@ -359,12 +374,18 @@ updated." (defun notmuch-tree-tag-update-display (&optional tag-changes) "Update display for TAG-CHANGES to current message. -Does NOT change the database." +Updates the message in the message pane if appropriate, but does +NOT change the database." (let* ((current-tags (notmuch-tree-get-tags)) - (new-tags (notmuch-update-tags current-tags tag-changes))) + (new-tags (notmuch-update-tags current-tags tag-changes)) + (tree-msg-id (notmuch-tree-get-message-id))) (unless (equal current-tags new-tags) (notmuch-tree-set-tags new-tags) - (notmuch-tree-refresh-result)))) + (notmuch-tree-refresh-result) + (when (window-live-p notmuch-tree-message-window) + (with-selected-window notmuch-tree-message-window + (when (string= tree-msg-id (notmuch-show-get-message-id)) + (notmuch-show-update-tags new-tags))))))) (defun notmuch-tree-tag (tag-changes) "Change tags for the current message" @@ -385,6 +406,15 @@ Does NOT change the database." (list (notmuch-read-tag-changes (notmuch-tree-get-tags) "Tag message" "-"))) (notmuch-tree-tag tag-changes)) +(defun notmuch-tree-resume-message () + "Resume EDITING the current draft message." + (interactive) + (notmuch-tree-close-message-window) + (let ((id (notmuch-tree-get-message-id))) + (if id + (notmuch-draft-resume id) + (message "No message to resume!")))) + ;; The next two functions close the message window before calling ;; notmuch-search or notmuch-tree but they do so after the user has ;; entered the query (in case the user was basing the query on @@ -404,32 +434,11 @@ Does NOT change the database." (notmuch-tree-close-message-window) (notmuch-tree query))) -;; This function should be in notmuch-show.el but be we trying to -;; minimise impact on the rest of the codebase. -(defun notmuch-tree-from-show-current-query () - "Call notmuch tree with the current query" - (interactive) - (notmuch-tree notmuch-show-thread-id - notmuch-show-query-context - (notmuch-show-get-message-id))) - -;; This function should be in notmuch.el but be we trying to minimise -;; impact on the rest of the codebase. -(defun notmuch-tree-from-search-current-query () - "Call notmuch tree with the current query" +(defun notmuch-search-from-tree-current-query () + "Call notmuch search with the current query" (interactive) - (notmuch-tree notmuch-search-query-string)) - -;; This function should be in notmuch.el but be we trying to minimise -;; impact on the rest of the codebase. -(defun notmuch-tree-from-search-thread () - "Show the selected thread with notmuch-tree" - (interactive) - (notmuch-tree (notmuch-search-find-thread-id) - notmuch-search-query-string - nil - (notmuch-prettify-subject (notmuch-search-find-subject)) - t)) + (notmuch-tree-close-message-window) + (notmuch-search (notmuch-tree-get-query))) (defun notmuch-tree-message-window-kill-hook () "Close the message pane when exiting the show buffer." @@ -442,6 +451,13 @@ Does NOT change the database." (ignore-errors (delete-window notmuch-tree-message-window))))) +(defun notmuch-tree-command-hook () + (when (eq major-mode 'notmuch-tree-mode) + ;; We just run the notmuch-show-command-hook on the message pane. + (when (buffer-live-p notmuch-tree-message-buffer) + (with-current-buffer notmuch-tree-message-buffer + (notmuch-show-command-hook))))) + (defun notmuch-tree-show-message-in () "Show the current message (in split-pane)." (interactive) @@ -714,20 +730,22 @@ unchanged ADDRESS if parsing fails." ((string-equal field "tags") (let ((tags (plist-get msg :tags)) + (orig-tags (plist-get msg :orig-tags)) (face (if match 'notmuch-tree-match-tag-face 'notmuch-tree-no-match-tag-face))) - (propertize (format format-string - (mapconcat #'identity tags ", ")) - 'face face)))))) - + (format format-string (notmuch-tag-format-tags tags orig-tags face))))))) (defun notmuch-tree-format-field-list (field-list msg) "Format fields of MSG according to FIELD-LIST and return string" - (let (result-string) + (let ((face (if (plist-get msg :match) + 'notmuch-tree-match-face + 'notmuch-tree-no-match-face)) + (result-string)) (dolist (spec field-list result-string) (let ((field-string (notmuch-tree-format-field (car spec) (cdr spec) msg))) - (setq result-string (concat result-string field-string)))))) + (setq result-string (concat result-string field-string)))) + (notmuch-apply-face result-string face t))) (defun notmuch-tree-insert-msg (msg) "Insert the message MSG according to notmuch-tree-result-format" @@ -778,8 +796,10 @@ message together with all its descendents." (push "├" tree-status))) (push (concat (if replies "┬" "─") "►") tree-status) - (plist-put msg :first (and first (eq 0 depth))) - (notmuch-tree-goto-and-insert-msg (plist-put msg :tree-status tree-status)) + (setq msg (plist-put msg :first (and first (eq 0 depth)))) + (setq msg (plist-put msg :tree-status tree-status)) + (setq msg (plist-put msg :orig-tags (plist-get msg :tags))) + (notmuch-tree-goto-and-insert-msg msg) (pop tree-status) (pop tree-status) @@ -811,7 +831,7 @@ This function inserts a collection of several complete threads as passed to it by notmuch-tree-process-filter." (mapc 'notmuch-tree-insert-forest-thread forest)) -(defun notmuch-tree-mode () +(define-derived-mode notmuch-tree-mode fundamental-mode "notmuch-tree" "Major mode displaying messages (as opposed to threads) of of a notmuch search. This buffer contains the results of a \"notmuch tree\" of your @@ -825,12 +845,7 @@ Complete list of currently available key bindings: \\{notmuch-tree-mode-map}" - (interactive) - (kill-all-local-variables) (setq notmuch-buffer-refresh-function #'notmuch-tree-refresh-view) - (use-local-map notmuch-tree-mode-map) - (setq major-mode 'notmuch-tree-mode - mode-name "notmuch-tree") (hl-line-mode 1) (setq buffer-read-only t truncate-lines t)) @@ -880,10 +895,16 @@ This is is a helper function for notmuch-tree. The arguments are the same as for the function notmuch-tree." (interactive) (notmuch-tree-mode) + (add-hook 'post-command-hook #'notmuch-tree-command-hook t t) (setq notmuch-tree-basic-query basic-query) (setq notmuch-tree-query-context query-context) (setq notmuch-tree-target-msg target) (setq notmuch-tree-open-target open-target) + ;; Set the default value for `notmuch-show-process-crypto' in this + ;; buffer. Although we don't use this some of the functions we call + ;; (such as reply) do. It is a buffer local variable so setting it + ;; will not affect genuine show buffers. + (setq notmuch-show-process-crypto notmuch-crypto-process-mime) (erase-buffer) (goto-char (point-min)) @@ -893,9 +914,10 @@ the same as for the function notmuch-tree." (message-arg "--entire-thread")) (if (equal (car (process-lines notmuch-command "count" search-args)) "0") (setq search-args basic-query)) + (notmuch-tag-clear-cache) (let ((proc (notmuch-start-notmuch "notmuch-tree" (current-buffer) #'notmuch-tree-process-sentinel - "show" "--body=false" "--format=sexp" + "show" "--body=false" "--format=sexp" "--format-version=3" message-arg search-args)) ;; Use a scratch buffer to accumulate partial output. ;; This buffer will be killed by the sentinel, which @@ -905,6 +927,15 @@ the same as for the function notmuch-tree." (set-process-filter proc 'notmuch-tree-process-filter) (set-process-query-on-exit-flag proc nil)))) +(defun notmuch-tree-get-query () + "Return the current query in this tree buffer" + (if notmuch-tree-query-context + (concat notmuch-tree-basic-query + " and (" + notmuch-tree-query-context + ")") + notmuch-tree-basic-query)) + (defun notmuch-tree (&optional query query-context target buffer-name open-target) "Display threads matching QUERY in Tree View. @@ -936,8 +967,8 @@ The arguments are: (setq truncate-lines t)) -;; Set up key bindings from the rest of notmuch. -(define-key notmuch-common-keymap "z" 'notmuch-tree) -(define-key notmuch-show-mode-map "Z" 'notmuch-tree-from-show-current-query) +;; (provide 'notmuch-tree) + +;;; notmuch-tree.el ends here