;;; email/notmuch/autoload.el -*- lexical-binding: t; -*- ;;;###autoload (defun =notmuch () "Activate (or switch to) `notmuch' in its workspace." (interactive) (unless (featurep! :ui workspaces) (user-error ":ui workspaces is required, but disabled")) (condition-case-unless-debug e (progn (+workspace-switch "*MAIL*" t) (if-let* ((buf (cl-find-if (lambda (it) (string-match-p "^\\*notmuch" (buffer-name (window-buffer it)))) (doom-visible-windows)))) (select-window (get-buffer-window buf)) (notmuch-search "tag:inbox")) (+workspace/display)) ('error (+notmuch/quit) (signal (car e) (cdr e))))) ;; ;; Commands ;;;###autoload (defun +notmuch/quit () (interactive) ;; (+popup/close (get-buffer-window "*notmuch-hello*")) (doom-kill-matching-buffers "^\\*notmuch") (+workspace/delete "*MAIL*")) ;;;###autoload (defun +notmuch/update () (interactive) ;; create output buffer and jump to beginning (let ((buf (get-buffer-create "*notmuch update*"))) (with-current-buffer buf (erase-buffer)) (pop-to-buffer buf nil t) (set-process-sentinel (start-process-shell-command "notmuch update" buf (pcase +notmuch-sync-backend (`gmi (concat "cd " +notmuch-mail-folder " && gmi push && gmi pull && notmuch new && afew -a -t")) (`mbsync "mbsync -a && notmuch new && afew -a -t") (`mbsync-xdg "mbsync -c \"$XDG_CONFIG_HOME\"/isync/mbsyncrc -a && notmuch new && afew -a -t") (`offlineimap "offlineimap && notmuch new && afew -a -t") (`custom +notmuch-sync-command))) ;; refresh notmuch buffers if sync was successful (lambda (_process event) (if (string= event "finished\n") (notmuch-refresh-all-buffers)))))) ;;;###autoload (defun +notmuch/search-delete () (interactive) (notmuch-search-add-tag (list "+trash" "-inbox" "-unread")) (notmuch-tree-next-message)) ;;;###autoload (defun +notmuch/tree-delete () (interactive) (notmuch-tree-add-tag (list "+trash" "-inbox" "-unread")) (notmuch-tree-next-message)) ;;;###autoload (defun +notmuch/show-delete () "Mark email for deletion in notmuch-show" (interactive) (notmuch-show-add-tag (list "+trash" "-inbox" "-unread")) (notmuch-show-next-thread-show)) ;;;###autoload (defun +notmuch/search-spam () (interactive) (notmuch-search-add-tag (list "+spam" "-inbox" "-unread")) (notmuch-search-next-thread)) ;;;###autoload (defun +notmuch/tree-spam () (interactive) (notmuch-tree-add-tag (list "+spam" "-inbox" "-unread")) (notmuch-tree-next-message)) ;;;###autoload (defun +notmuch/compose () "Compose new mail" (interactive) (notmuch-mua-mail nil nil (list (cons 'From (completing-read "From: " (notmuch-user-emails)))))) ;;;###autoload (defun +notmuch/open-message-with-mail-app-notmuch-tree () (interactive) (let* ((msg-path (car (plist-get (notmuch-tree-get-message-properties) :filename))) (temp (make-temp-file "notmuch-message-" nil ".eml"))) (doom-call-process "cp" msg-path temp) (start-process-shell-command "email" nil (format "xdg-open '%s'" temp)))) ;;;###autoload (defun +notmuch/open-message-with-mail-app-notmuch-show () (interactive) (let* ((msg-path (car (plist-get (notmuch-show-get-message-properties) :filename))) (temp (make-temp-file "notmuch-message-" nil ".eml"))) (doom-call-process "cp" msg-path temp) (start-process-shell-command "email" nil (format "xdg-open '%s'" temp)))) ;;;###autoload (defun +notmuch/show-filter-thread () "Show the current thread with a different filter" (interactive) (setq notmuch-show-query-context (notmuch-read-query "Filter thread: ")) (notmuch-show-refresh-view t)) ;;;###autoload (defun +notmuch-show-expand-only-unread-h () (interactive) (let ((unread nil) (open (notmuch-show-get-message-ids-for-open-messages))) (notmuch-show-mapc (lambda () (when (member "unread" (notmuch-show-get-tags)) (setq unread t)))) (when unread (let ((notmuch-show-hook (remove '+notmuch-show-expand-only-unread-h notmuch-show-hook))) (notmuch-show-filter-thread "tag:unread"))))) ;; ;; Advice ;;;###autoload (defun +notmuch-dont-confirm-on-kill-process-a (orig-fn &rest args) "Don't prompt for confirmation when killing notmuch sentinel." (let (confirm-kill-processes) (apply orig-fn args))) ;; (defun +notmuch*hello-insert-searches (title query-list &rest options) ;; (widget-insert (propertize title 'face 'org-agenda-structure)) ;; (if (and notmuch-hello-first-run (plist-get options :initially-hidden)) ;; (add-to-list 'notmuch-hello-hidden-sections title)) ;; (let ((is-hidden (member title notmuch-hello-hidden-sections)) ;; (widget-push-button-prefix "") ;; (widget-push-button-suffix "") ;; (start (point))) ;; (if is-hidden ;; (widget-create 'push-button ;; :notify `(lambda (widget &rest ignore) ;; (setq notmuch-hello-hidden-sections ;; (delete ,title notmuch-hello-hidden-sections)) ;; (notmuch-hello-update)) ;; (propertize " +" 'face 'org-agenda-structure)) ;; (widget-create 'push-button ;; :notify `(lambda (widget &rest ignore) ;; (add-to-list 'notmuch-hello-hidden-sections ;; ,title) ;; (notmuch-hello-update)) ;; " -")) ;; (widget-insert "\n") ;; (when (not is-hidden) ;; (let ((searches (apply 'notmuch-hello-query-counts query-list options))) ;; (when (or (not (plist-get options :hide-if-empty)) ;; searches) ;; (widget-insert "\n") ;; (notmuch-hello-insert-buttons searches) ;; (indent-rigidly start (point) notmuch-hello-indent)))))) ;; (defun +notmuch*hello-insert-saved-searches () ;; "Insert the saved-searches section." ;; (let ((searches (notmuch-hello-query-counts ;; (if notmuch-saved-search-sort-function ;; (funcall notmuch-saved-search-sort-function ;; notmuch-saved-searches) ;; notmuch-saved-searches) ;; :show-empty-searches notmuch-show-empty-saved-searches))) ;; (when searches ;; (widget-insert (propertize "Notmuch" 'face 'org-agenda-date-today)) ;; (widget-insert "\n\n") ;; (widget-insert (propertize "Saved searches" 'face 'org-agenda-structure)) ;; (widget-insert "\n\n") ;; (let ((start (point))) ;; (notmuch-hello-insert-buttons searches) ;; (indent-rigidly start (point) notmuch-hello-indent))))) ;; (defun +notmuch*hello-insert-buttons (searches) ;; (let* ((widest (notmuch-hello-longest-label searches)) ;; (tags-and-width (notmuch-hello-tags-per-line widest)) ;; (tags-per-line (car tags-and-width)) ;; (column-width (cdr tags-and-width)) ;; (column-indent 0) ;; (count 0) ;; (reordered-list (notmuch-hello-reflect searches tags-per-line)) ;; ;; Hack the display of the buttons used. ;; (widget-push-button-prefix "") ;; (widget-push-button-suffix "")) ;; ;; dme: It feels as though there should be a better way to ;; ;; implement this loop than using an incrementing counter. ;; (mapc (lambda (elem) ;; ;; (not elem) indicates an empty slot in the matrix. ;; (when elem ;; (if (> column-indent 0) ;; (widget-insert (make-string column-indent ? ))) ;; (let* ((name (plist-get elem :name)) ;; (query (plist-get elem :query)) ;; (oldest-first (case (plist-get elem :sort-order) ;; (newest-first nil) ;; (oldest-first t) ;; (otherwise notmuch-search-oldest-first))) ;; (search-type (eq (plist-get elem :search-type) 'tree)) ;; (msg-count (plist-get elem :count))) ;; (widget-insert (format "\n%5s " ;; (notmuch-hello-nice-number msg-count))) ;; (widget-create 'push-button ;; :notify #'notmuch-hello-widget-search ;; :notmuch-search-terms query ;; :notmuch-search-oldest-first oldest-first ;; :notmuch-search-type search-type ;; name) ;; (setq column-indent ;; (1+ (max 0 (- column-width (length name))))))) ;; (setq count (1+ count)) ;; (when (eq (% count tags-per-line) 0) ;; (setq column-indent 0) ;; (widget-insert "\n"))) ;; reordered-list) ;; ;; If the last line was not full (and hence did not include a ;; ;; carriage return), insert one now. ;; (unless (eq (% count tags-per-line) 0) ;; (widget-insert "\n"))))