diff options
Diffstat (limited to 'custom/jao-custom-notmuch.el')
-rw-r--r-- | custom/jao-custom-notmuch.el | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/custom/jao-custom-notmuch.el b/custom/jao-custom-notmuch.el new file mode 100644 index 0000000..28da05f --- /dev/null +++ b/custom/jao-custom-notmuch.el @@ -0,0 +1,652 @@ +;; -*- lexical-binding: t; -*- + +;;; minibuffer +(defvar jao-notmuch-minibuffer-string "") + +(defvar jao-notmuch-minibuffer-queries + '((:name "" :query "tag:new and not tag:draft" :face jao-themes-f00) + (:name "B" :query "tag:new and tag:bigml and tag:inbox" :face default) + (:name "b" :query "tag:new and tag:bigml and tag:bugs" + :face jao-themes-error) + (:name "S" :query "tag:new and tag:bigml and tag:support" :face default) + (:name "W" + :query "tag:new and tag:bigml and not tag:\"/support|bugs|inbox/\"" + :face default) + (:name "I" + :query "tag:new and tag:jao and tag:inbox" + :face jao-themes-warning) + (:name "J" + :query "tag:new and tag:jao and not tag:\"/local|hacking|draft|inbox|prog|words/\"" + :face default) + (:name "H" :query "tag:new and tag:hacking and not tag:\"/emacs/\"") + (:name "E" :query "tag:new and tag:\"/emacs/\"") + (:name "l" :query "tag:new and tag:local") + (:name "F" :query "tag:new and tag:feeds and not tag:\"/emacs/\""))) + +(defun jao-notmuch-notify () + (let ((cnts (notmuch-hello-query-counts jao-notmuch-minibuffer-queries))) + (setq jao-notmuch-minibuffer-string + (mapconcat (lambda (c) + (propertize (format "%s%s" + (plist-get c :name) + (plist-get c :count)) + 'face (or (plist-get c :face) + 'jao-themes-dimm))) + cnts + " ")) + (jao-minibuffer-refresh))) + +(when jao-notmuch-enabled + (jao-minibuffer-add-variable 'jao-notmuch-minibuffer-string -20)) + +;;; saved searches +(defvar jao-notmuch--new "tag:\"/^(unread|new)$/\"") +(defvar jao-notmuch--newa (concat jao-notmuch--new " AND ")) + +(defun jao-notmuch--q (d0 d1 &optional k qs st) + (let ((q (or (when qs (mapconcat #'identity qs " AND ")) + (concat jao-notmuch--newa + (mapconcat (lambda (d) (when d (concat "tag:" d))) + (list d0 d1) " AND "))))) + (list :name (concat d0 (when (and d1 (not (string= "" d1))) "/") d1) + :key k :query q :search-type (or st 'tree) + :sort-order 'oldest-first))) + +(defun jao-notmuch--qn (d0 d1 k qs &optional st) + (jao-notmuch--q d0 d1 k (cons jao-notmuch--new qs) st)) + +(defun jao-notmuch--sq (tag &optional k d0 d1) + (jao-notmuch--qn (or d0 "feeds") (or d1 tag) k (list (concat "tag:" tag)))) + +(defvar jao-notmuch--shared-tags + '("new" "unread" "flagged" "signed" "sent" "attachment" "forwarded" + "encrypted" "gmane" "gnus" "feeds" "rss" "mce" "trove" "prog" "emacs")) + +(defun jao-notmuch--subtags (tag &rest excl) + (let* ((cmd (concat "notmuch search --output=tags tag:" tag)) + (ts (split-string (shell-command-to-string cmd)))) + (seq-difference ts (append jao-notmuch--shared-tags (cons tag excl))))) + +(defvar jao-notmuch-feed-searches-news + (mapcar #'jao-notmuch--sq '("news" "fun" "words" "computers"))) + +(defvar jao-notmuch-feed-searches-hack + (mapcar #'jao-notmuch--sq + '("xmobar" "geiser" "mdk" "mailutils" "notmuch"))) + +(defvar jao-notmuch-feed-searches-lang + (append (mapcar #'jao-notmuch--sq + '( "lobsters" "clojure" "lisp" "scheme" + "haskell" "idris" "erlang" "pharo")) + `(,(jao-notmuch--qn "feeds" "prog" "fp" + '("tag:prog" "not tag:\"/emacs/\""))))) + +(defvar jao-notmuch-feed-searches-sci + (mapcar #'jao-notmuch--sq + '("philosophy" "math" "physics" "sci" "gr-qc" "quant-ph"))) + +(defvar jao-notmuch-feed-searches + (append jao-notmuch-feed-searches-news + jao-notmuch-feed-searches-hack + jao-notmuch-feed-searches-lang + jao-notmuch-feed-searches-sci)) + +(defvar jao-notmuch-bigml-searches + `(,(jao-notmuch--q "bigml" "inbox" "bi") + ,(jao-notmuch--q "bigml" "alba" "ba") + ,(jao-notmuch--q "bigml" "support" "bs") + ,(jao-notmuch--q "bigml" "bugs" "bb") + ,(jao-notmuch--q "bigml" "drivel" "bd") + ,(jao-notmuch--q "bigml" "lists" "bl"))) + +(defvar jao-notmuch-inbox-searches + `(,(jao-notmuch--q "jao" "inbox" "ji") + ,(jao-notmuch--q "jao" "bills" "jb") + ,(jao-notmuch--q "jao" "drivel" "jd") + ,(jao-notmuch--q "jao" "mdk" "jm") + ,(jao-notmuch--qn "jao" "hacking" "jh" + '("tag:hacking" "not tag:\"/emacs/\"")) + ,(jao-notmuch--qn "jao" "local" "jl" '("tag:local")))) + +(defvar jao-notmuch-mark-searches + `(,(jao-notmuch--q "jao" "drafts" "d" '("tag:draft")) + ,(jao-notmuch--q "bml" "flagged" "rb" '("tag:flagged" "tag:bigml")) + ,(jao-notmuch--q "jao" "flagged" "rj" '("tag:flagged" "tag:jao")) + ,(jao-notmuch--q "feeds" "flagged" "rf" '("tag:flagged" "tag:feeds")))) + +(defvar jao-notmuch-emacs-searches + `(,(jao-notmuch--sq "emacs" "ee" "emacs" "feeds") + ,(jao-notmuch--sq "emacs-help" "eh" "emacs" "help") + ,(jao-notmuch--sq "emacs-github" "eg" "emacs" "github") + ,(jao-notmuch--sq "emacs-devel" "ed" "emacs" "devel") + ,(jao-notmuch--sq "emacs-bugs" "eb" "emacs" "bugs") + ,(jao-notmuch--sq "emacs-diffs" "ec" "emacs" "diffs") + ,(jao-notmuch--sq "emacs-orgmode" "eo" "emacs" "org"))) + +(setq notmuch-saved-searches + (append jao-notmuch-inbox-searches + jao-notmuch-bigml-searches + jao-notmuch-mark-searches + jao-notmuch-feed-searches + jao-notmuch-emacs-searches)) + +(defvar jao-notmuch-dynamic-searches + `(,(jao-notmuch--q "bml" "today" "tb" '("tag:bigml" "date:24h..")) + ,(jao-notmuch--q "jao" "today" "tj" + '("tag:jao" "date:24h.." + "not tag:\"/(feeds|spam|local)/\"")))) + +(defvar jao-notmuch-new-searches + `(,(jao-notmuch--q "new" nil "nn" '("tag:new" "not tag:draft")) + ,(jao-notmuch--q "unread" nil "nu" '("tag:unread")) + (:query "*" :name "messages"))) + +(defun jao-notmuch-tree-widen-search () + (interactive) + (when-let ((query (notmuch-tree-get-query))) + (let ((notmuch-show-process-crypto (notmuch-tree--message-process-crypto))) + (notmuch-tree-close-message-window) + (notmuch-tree (string-replace jao-notmuch--newa "" query))))) + +(defun jao-notmuch-widen-searches (searches &optional extra) + (mapcar (lambda (s) + (let* ((q (plist-get s :query)) + (qs (string-replace jao-notmuch--newa "" q))) + (plist-put (copy-sequence s) :query (concat qs extra)))) + searches)) + +(defvar jao-notmuch-widened-searches + (jao-notmuch-widen-searches notmuch-saved-searches)) + +(defvar jao-notmuch-flagged-searches + (let ((s (seq-difference notmuch-saved-searches + jao-notmuch-mark-searches))) + (jao-notmuch-widen-searches s " AND tag:flagged"))) + +(defun jao-notmuch-jump-search (&optional widen) + (interactive "P") + (let ((notmuch-saved-searches + (if widen jao-notmuch-widened-searches notmuch-saved-searches))) + (notmuch-jump-search))) + +;;; tags +(setq notmuch-archive-tags '("+trove" "-new" "-inbox") + notmuch-show-mark-read-tags '("-new" "-unread") + notmuch-tag-formats + (let ((d `(:foreground ,(face-attribute 'jao-themes-dimm :foreground))) + (e `(:foreground ,(face-attribute 'jao-themes-error :foreground) + :weight bold))) + `(("unread") + ("signed") + ("new" "N") + ("replied" "↩" (propertize tag 'face '(:family "Fira Code"))) + ("sent" "S") + ("attachment" "📎") + ("deleted" "🗙" (propertize tag 'face '(:underline nil ,@e))) + ;; ("attachment" "+") + ;; ("deleted" "xxx" (propertize tag 'face '(:underline nil ,@e))) + ("flagged" "!" (propertize tag 'face ',e)) + ("jao" "j") + ("bigml" "b") + ("feeds" "f") + ("gmane" "g"))) + notmuch-tag-deleted-formats + '(("unread") + ("new") + (".*" (notmuch-apply-face tag 'notmuch-tag-deleted)))) + +(with-eval-after-load "notmuch-tag" + (advice-add #'notmuch-read-tag-changes + :filter-return (lambda (x) (mapcar #'string-trim x)))) + +;;; package +(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/") + +(use-package notmuch + :init + (setq notmuch-address-use-company t + notmuch-address-command (if jao-notmuch-enabled 'internal 'as-is) + notmuch-always-prompt-for-sender t + notmuch-draft-folder "local" + notmuch-draft-quoted-tags '("part") + notmuch-address-internal-completion '(received nil) + notmuch-fcc-dirs + '(("\\(support\\|education\\)@bigml.com" . nil) + (".*@bigml.com" . "bigml/trove +bigml +sent -new -unread") + (".*" . "jao/trove +jao +sent +trove -new -unread")) + notmuch-maildir-use-notmuch-insert t) + + :config + + (add-hook 'message-send-hook #'notmuch-mua-attachment-check) + + (when jao-notmuch-enabled + (define-key message-mode-map (kbd "C-c C-d") #'notmuch-draft-postpone) + (setq message-directory "~/var/mail/" + message-auto-save-directory "/tmp" + mail-user-agent 'message-user-agent)) + + :bind (:map notmuch-common-keymap + (("E" . jao-notmuch-open-enclosure) + ("B" . notmuch-show-resend-message) + ("b" . jao-notmuch-browse-urls)))) + +(use-package jao-notmuch :demand t) + +;;; hello +(defun jao-notmuch-hello--insert-searches (searches title) + (when-let (searches (notmuch-hello-query-counts searches)) + (let* ((cnt (when title + (seq-reduce (lambda (c q) + (+ c (or (plist-get q :count) 0))) + searches + 0))) + (title (if title (format "[ %d %s ]\n\n" cnt title) "\n"))) + (widget-insert (propertize title 'face 'jao-themes-f00)) + (let ((notmuch-column-control 1.0) + (start (point))) + (notmuch-hello-insert-buttons searches) + (indent-rigidly start (point) notmuch-hello-indent)) + cnt))) + +(defun jao-notmuch-hello-insert-inbox-searches () + (jao-notmuch-hello--insert-searches jao-notmuch-inbox-searches "inbox")) + +(defun jao-notmuch-hello-insert-bigml-searches () + (jao-notmuch-hello--insert-searches jao-notmuch-bigml-searches "bigml")) + +(defun jao-notmuch-hello-insert-mark-searches () + (jao-notmuch-hello--insert-searches jao-notmuch-mark-searches "marks") + (jao-notmuch-hello--insert-searches jao-notmuch-flagged-searches nil)) + +(defun jao-notmuch-hello-insert-feeds-searches () + (let ((sect "feeds")) + (dolist (s `(,jao-notmuch-feed-searches-news + ,jao-notmuch-feed-searches-hack + ,jao-notmuch-feed-searches-lang + ,jao-notmuch-feed-searches-sci)) + (let ((i (funcall #'jao-notmuch-hello--insert-searches s sect))) + (setq sect (unless i sect)))))) + +(defun jao-notmuch-hello-insert-emacs-searches () + (jao-notmuch-hello--insert-searches jao-notmuch-emacs-searches "emacs")) + +(defun jao-notmuch-hello-insert-dynamic-searches () + (jao-notmuch-hello--insert-searches jao-notmuch-dynamic-searches "dynamic") + (jao-notmuch-hello--insert-searches jao-notmuch-new-searches nil)) + +(defun jao-notmuch-refresh-agenda () + (interactive) + (save-window-excursion (org-agenda-list)) + (let ((b (current-buffer))) + (pop-to-buffer "*Calendar*") + (goto-char (point-min)) + (calendar-goto-today) + (pop-to-buffer b))) + +(defun jao-notmuch-hello-first () + (interactive) + (let ((inhibit-message t)) + (beginning-of-buffer) + (widget-forward 1))) + +(defun jao-notmuch-refresh-hello (&optional agenda) + (interactive "P") + (ignore-errors + (when (and (string= "Mail" (jao-afio-current-frame)) + (derived-mode-p 'notmuch-hello-mode)) + (when (not (string-blank-p jao-notmuch-minibuffer-string)) + (let ((notmuch-hello-auto-refresh nil)) (notmuch-hello))) + (when agenda (jao-notmuch-refresh-agenda)) + (unless (widget-at) (jao-notmuch-hello-first))))) + +(defvar jao-notmuch-hello--sec-rx "^\\(\\[ [0-9]+\\|All tags:.+\\)") + +(defun jao-notmuch-hello-next-section () + (interactive) + (when (re-search-forward jao-notmuch-hello--sec-rx nil t) + (widget-forward 1))) + +(defun jao-notmuch-hello-prev-section () + (interactive) + (beginning-of-line) + (unless (looking-at-p jao-notmuch-hello--sec-rx) + (re-search-backward jao-notmuch-hello--sec-rx nil t)) + (when (re-search-backward jao-notmuch-hello--sec-rx nil t) + (end-of-line) + (widget-forward 1))) + +(defun jao-notmuch-hello-next () + (interactive) + (if (widget-at) + (widget-button-press (point)) + (jao-notmuch-hello-next-section))) + +(use-package notmuch-hello + :init + (setq notmuch-column-control t + notmuch-hello-sections '(jao-notmuch-hello-insert-bigml-searches + jao-notmuch-hello-insert-inbox-searches + jao-notmuch-hello-insert-feeds-searches + jao-notmuch-hello-insert-emacs-searches + jao-notmuch-hello-insert-mark-searches + jao-notmuch-hello-insert-dynamic-searches + notmuch-hello-insert-alltags) + notmuch-hello-hide-tags nil + notmuch-hello-thousands-separator "," + notmuch-hello-auto-refresh t + notmuch-show-all-tags-list nil + notmuch-show-logo nil + notmuch-show-empty-saved-searches nil) + + :hook ((notmuch-hello-refresh . jao-notmuch-notify) + (jao-afio-switch . jao-notmuch-refresh-hello)) + + :bind (:map notmuch-hello-mode-map + (("a" . jao-notmuch-refresh-agenda) + ("j" . jao-notmuch-jump-search) + ("n" . jao-notmuch-hello-next) + ("p" . widget-backward) + ("S" . consult-notmuch) + ("g" . jao-notmuch-refresh-hello) + ("." . jao-notmuch-hello-first) + ("SPC" . widget-button-press) + ("[" . jao-notmuch-hello-prev-section) + ("]" . jao-notmuch-hello-next-section)))) + +;;; show +(defun jao-notmuch-open-enclosure (add) + (interactive "P") + (with-current-notmuch-show-message + (goto-char (point-min)) + (if (not (search-forward "Enclosure:" nil t)) + (user-error "No enclosure in message body") + (re-search-forward "https?://" nil t) + (if-let (url (thing-at-point-url-at-point)) + (progn + (message "%s %s ..." (if add "Adding" "Playing") url) + (unless add (jao-mpc-clear)) + (jao-mpc-add-url url) + (unless add (jao-mpc-play))) + (error "Found an enclosure, but not a link!"))))) + +(defconst jao-mail-clean-rx + (regexp-opt '("ElDiario.es - ElDiario.es: " "The Guardian: " + "The Conversation – Articles (UK): "))) + +(defun jao-mail-clean-address (args) + (when-let ((address (car args))) + (list (if (string-match ".+ updates on arXiv.org: \\(.+\\)" address) + (with-temp-buffer + (insert (match-string 1 address)) + (let ((shr-width 1000)) + (shr-render-region (point-min) (point-max))) + (replace-regexp-in-string "\"" "" (buffer-string))) + (replace-regexp-in-string jao-mail-clean-rx "" address))))) + +(use-package notmuch-show + :init + (setq gnus-blocked-images "." + notmuch-message-headers + '("To" "Cc" "Date" "Reply-To" "List-Id" "X-RSS-Feed") + notmuch-show-only-matching-messages t + notmuch-show-part-button-default-action 'notmuch-show-view-part + notmuch-wash-signature-lines-max 0 + notmuch-wash-wrap-lines-length 80 + notmuch-wash-citation-lines-prefix 10 + notmuch-wash-citation-lines-suffix 20 + notmuch-show-text/html-blocked-images "." + notmuch-show-header-line #'jao-notmuch-message-header-line) + + :config + + (advice-add 'notmuch-clean-address :filter-args #'jao-mail-clean-address) + + :bind + (:map notmuch-show-mode-map + (("h" . jao-notmuch-goto-tree-buffer) + ("TAB" . jao-notmuch-show-next-button) + ([backtab] . jao-notmuch-show-previous-button) + ("RET" . jao-notmuch-show-ret)))) + +;;; search +(use-package notmuch-search + :init (setq notmuch-search-result-format + '(("date" . "%12s ") + ("count" . "%-7s ") + ("authors" . "%-35s") + ("subject" . " %-100s") + (jao-notmuch-format-tags . " (%s)")) + notmuch-search-buffer-name-format "*%s*" + notmuch-saved-search-buffer-name-format "*%s*") + :bind (:map notmuch-search-mode-map + (("RET" . notmuch-tree-from-search-thread) + ("M-RET" . notmuch-search-show-thread)))) + +;;; tree +(defun jao-notmuch-tree--forward (&optional prev) + (interactive) + (forward-line (if prev -1 1)) + (when prev (forward-char 2)) + (jao-notmuch-tree-scroll-or-next)) + +(defun jao-notmuch-tree--backward () + (interactive) + (jao-notmuch-tree--forward t)) + +(defun jao-notmuch--via-url () + (when (window-live-p notmuch-tree-message-window) + (with-selected-window notmuch-tree-message-window + (goto-char (point-min)) + (when (re-search-forward "^Via: http" nil t) + (thing-at-point-url-at-point))))) + +(defun jao-notmuch-browse-url (ext) + (interactive "P") + (when-let (url (or (jao-notmuch--via-url) + (car (last (jao-notmuch-message-urls))))) + (funcall (if ext browse-url-secondary-browser-function #'browse-url) + url))) + +(defun jao-notmuch-adjust-tree-fonts (&optional family) + (let ((fg (face-attribute 'jao-themes-dimm :foreground))) + (dolist (f '(notmuch-tree-match-tree-face + notmuch-tree-no-match-tree-face)) + (if family + (set-face-attribute f nil :family family :foreground fg) + (set-face-attribute f nil :foreground fg))))) + +(use-package notmuch-tree + :init + (setq notmuch-tree-result-format + `(("date" . "%12s ") + (jao-notmuch-format-author . 25) + (jao-notmuch-format-msg-ticks . ,jao-mails-regexp) + (jao-notmuch-format-tree-and-subject . "%>-85s") + (jao-notmuch-format-tags . " (%s)")) + notmuch-unthreaded-result-format notmuch-search-result-format + consult-notmuch-result-format + `((jao-notmuch-format-msg-ticks . ,jao-mails-regexp) + ("date" . "%12s ") + ("authors" . "%-35s") + ("subject" . " %-100s") + (jao-notmuch-format-tags . " (%s)")) + ;; notmuch-tree-thread-symbols + ;; '((prefix . "─") (top . "─") (top-tee . "┬") + ;; (vertical . "│") (vertical-tee . "├") (bottom . "╰") + ;; (arrow . "")) + notmuch-tree-thread-symbols + '((prefix . " ") (top . " ") (top-tee . " ") + (vertical . " ") (vertical-tee . " ") (bottom . " ") + (arrow . ""))) + :config + + (when (display-graphic-p) + (jao-notmuch-adjust-tree-fonts + (when (string-prefix-p "Hack" jao-themes-default-face) "Source Code Pro"))) + + (jao-notmuch-tree-setup "T") + + (defun jao-notmuch-before-tree (&rest args) + (when (string= (buffer-name) "*notmuch-hello*") + (split-window-right 40) + (other-window 1))) + + (defvar jao-notmuch--visits 0) + + (defun jao-notmuch-after-tree-quit (&optional both) + (when (and (not (derived-mode-p 'notmuch-tree-mode 'notmuch-hello-mode)) + (save-window-excursion (other-window -1) + (derived-mode-p 'notmuch-hello-mode))) + (delete-window) + (jao-notmuch-refresh-hello (= 0 (mod (cl-incf jao-notmuch--visits) 10))))) + + (advice-add 'notmuch-tree :before #'jao-notmuch-before-tree) + (advice-add 'notmuch-tree-quit :after #'jao-notmuch-after-tree-quit) + + :bind (:map notmuch-tree-mode-map + (("b" . jao-notmuch-browse-urls) + ("d" . jao-notmuch-tree-toggle-delete) + ("D" . jao-notmuch-tree-toggle-delete-thread) + ("h" . jao-notmuch-goto-message-buffer) + ("H" . jao-notmuch-click-message-buffer) + ("i" . jao-notmuch-toggle-images) + ("K" . jao-notmuch-tag-jump-and-next) + ("k" . jao-notmuch-tree-read-thread) + ("n" . jao-notmuch-tree-next) + ("N" . jao-notmuch-tree--forward) + ("O" . notmuch-tree-toggle-order) + ("o" . jao-notmuch-tree-widen-search) + ("p" . jao-notmuch-tree-previous) + ("P" . jao-notmuch-tree--backward) + ("r" . notmuch-tree-reply) + ("R" . notmuch-tree-reply-sender) + ("s" . jao-notmuch-tree-toggle-spam) + ("u" . jao-notmuch-tree-toggle-flag) + ("v" . notmuch-tree-scroll-message-window) + ("V" . notmuch-tree-scroll-message-window-back) + ("x" . jao-notmuch-arXiv-capture) + ("<" . jao-notmuch-tree-beginning-of-buffer) + (">" . jao-notmuch-tree-end-of-buffer) + ("\\" . notmuch-tree-view-raw-message) + ("." . jao-notmuch-toggle-mime-parts) + ("=" . jao-notmuch-tree-toggle-message) + ("RET" . jao-notmuch-tree-show-or-scroll) + ("SPC" . jao-notmuch-tree-scroll-or-next) + ("M-g" . jao-notmuch-browse-url) + ("M-u" . jao-notmuch-tree-reset-tags)))) + +;;; org mode +(defvar jao-org-notmuch-last-subject nil) +(defun jao-org-notmuch-last-subject () jao-org-notmuch-last-subject) + +(defun jao-notmuch--add-tags (tags) + (if (derived-mode-p 'notmuch-show-mode) + (notmuch-show-add-tag tags) + (notmuch-tree-add-tag tags))) + +(defun org-notmuch-store-link () + "Store a link to a notmuch mail message." + (cl-case major-mode + ((notmuch-show-mode notmuch-tree-mode) + ;; Store link to the current message + (let* ((id (notmuch-show-get-message-id)) + (link (concat "notmuch:" id)) + (subj (notmuch-show-get-subject)) + (description (format "Mail: %s" subj))) + (setq jao-org-notmuch-last-subject subj) + (when (y-or-n-p "Archive message? ") + (jao-notmuch--add-tags '("+trove"))) + (when (y-or-n-p "Flag message as todo? ") + (jao-notmuch--add-tags '("+flagged"))) + (org-store-link-props "notmuch" link description))) + (notmuch-search-mode + ;; Store link to the thread on the current line + (let* ((id (notmuch-search-find-thread-id)) + (link (concat "notmuch:" id)) + (subj (notmuch-search-find-subject)) + (description (format "Mail: %s" subj))) + (setq jao-org-notmuch-last-subject subj) + (org-store-link-props + :type "notmuch" + :link link + :description description))))) + +(with-eval-after-load "org" + (org-link-set-parameters "notmuch" + :follow 'notmuch-show + :store 'org-notmuch-store-link)) +;;; arXiv +(use-package org-capture + :config + (add-to-list 'org-capture-templates + '("X" "arXiv" entry (file "notes/physics/arxiv.org") + "* %(jao-org-notmuch-last-subject)\n %i" + :immediate-finish t) + t) + (org-capture-upgrade-templates org-capture-templates)) + +(defun jao-notmuch-arXiv-capture () + (interactive) + (save-window-excursion + (jao-notmuch-goto-message-buffer) + (save-excursion + (goto-char (point-min)) + (re-search-forward "\\[ text/html \\]") + (forward-paragraph) + (setq-local transient-mark-mode 'lambda) + (set-mark (point)) + (goto-char (point-max)) + (org-capture nil "X")))) + +;;; html renderer +(when jao-notmuch-enabled (setq mm-text-html-renderer 'shr)) + +;;; consult +(jao-load-path "consult-notmuch") +(require 'consult-notmuch) +(consult-customize consult-notmuch :preview-key 'any) + +(defvar jao-consult-notmuch-history nil) + +(defvar jao-mailbox-folders '("bigml" "jao")) + +(defun jao-consult-notmuch-folder (&optional tree folder) + (interactive "P") + (let ((folder (if folder + (file-name-as-directory folder) + (completing-read "Group: " + jao-mailbox-folders + nil nil nil + jao-consult-notmuch-history + "."))) + (folder (replace-regexp-in-string "/\\(.\\)" ".\\1" folder)) + (init (read-string "Initial query: ")) + (init (format "folder:/%s/ %s" folder init))) + (if tree (consult-notmuch-tree init) (consult-notmuch init)))) + +(with-eval-after-load "notmuch-hello" + (define-key notmuch-hello-mode-map "f" #'jao-consult-notmuch-folder)) + +;;; link hint +(with-eval-after-load "link-hint" + (defun jao-link-hint--notmuch-next-part (&optional bound) + (when-let (p (next-single-property-change (point) :notmuch-part nil bound)) + (and (< p (or bound (point-max))) p))) + + (defun jao-link-hint--notmuch-part-p () + (and (get-text-property (point) :notmuch-part) + (when-let (b (button-at (point))) (button-label b)))) + + (link-hint-define-type 'notmuch-part + :next #'jao-link-hint--notmuch-next-part + :at-point-p #'jao-link-hint--notmuch-part-p + :vars '(notmuch-show-mode) + :open #'push-button + :open-message "Toggled" + :open-multiple t) + + (push 'link-hint-notmuch-part link-hint-types)) + +;;; . +(provide 'jao-custom-notmuch) |