diff options
Diffstat (limited to 'lib/net')
| -rw-r--r-- | lib/net/jao-eww-session.el | 27 | ||||
| -rw-r--r-- | lib/net/jao-notmuch-gnus.el | 70 | ||||
| -rw-r--r-- | lib/net/jao-notmuch.el | 93 | ||||
| -rw-r--r-- | lib/net/jao-proton-utils.el | 2 | ||||
| -rw-r--r-- | lib/net/jao-url.el | 45 | ||||
| -rw-r--r-- | lib/net/randomsig.el | 9 |
6 files changed, 178 insertions, 68 deletions
diff --git a/lib/net/jao-eww-session.el b/lib/net/jao-eww-session.el index 3c60cf8..da5bc8b 100644 --- a/lib/net/jao-eww-session.el +++ b/lib/net/jao-eww-session.el @@ -1,6 +1,6 @@ ;;; jao-eww-session.el --- Persistent eww sessions -*- lexical-binding: t; -*- -;; Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2012, 2021, 2022 Jose A Ortega Ruiz +;; Copyright (C) 2003-2004, 2006-2009, 2012, 2021-2022, 2025 Jose A Ortega Ruiz ;; Author: Jose A Ortega Ruiz <jao@gnu.org> ;; Version: 0.4 @@ -97,7 +97,7 @@ the session is already displayed in a eww tab, jao-eww-session can: (jao-eww-session-eww-buffers (current-buffer)))) (defun jao-eww--current-url () - (when-let* ((url (eww-current-url))) (url-encode-url url))) + (when-let (url (eww-current-url)) (url-encode-url url))) (defun jao-eww-session--current-urls (&optional skip-current) (let ((urls) @@ -107,7 +107,7 @@ the session is already displayed in a eww tab, jao-eww-session can: (dolist (b (jao-eww-session-eww-buffers (when skip-current cb)) (list pos (reverse urls))) (set-buffer b) - (when-let* ((url (jao-eww--current-url))) + (when-let (url (jao-eww--current-url)) (when (eq b cb) (setq pos count)) (setq count (1+ count)) (push (cons url (jao-eww-buffer-title)) urls))))) @@ -133,7 +133,7 @@ the session is already displayed in a eww tab, jao-eww-session can: (seq-filter (lambda (b) (with-current-buffer b - (when-let* ((url (jao-eww--current-url))) + (when-let (url (jao-eww--current-url)) (when (member url urls) (when (y-or-n-p "Already open session, abort? ") (switch-to-buffer b) @@ -168,15 +168,14 @@ the session is already displayed in a eww tab, jao-eww-session can: (defun jao-eww-session--to--file (filename &optional skip) (require 'pp) - (when (jao-eww-session-not-empty) - (let ((inhibit-message t) - (session (jao-eww-session--update-current skip))) - (with-temp-buffer - (insert ";;;; File generated by jao-eww-session. DO NOT EDIT!\n") - (pp session (current-buffer)) - (insert "\n" ";;;; End of " - (file-name-nondirectory jao-eww-session-file) "\n") - (write-region (point-min) (point-max) (expand-file-name filename)))))) + (let ((inhibit-message t) + (session (jao-eww-session--update-current skip))) + (with-temp-buffer + (insert ";;;; File generated by jao-eww-session. DO NOT EDIT!\n") + (pp session (current-buffer)) + (insert "\n" ";;;; End of " + (file-name-nondirectory jao-eww-session-file) "\n") + (write-region (point-min) (point-max) (expand-file-name filename))))) (defun jao-eww-session--backup-name (fname) (concat (expand-file-name fname) ".bak")) @@ -218,7 +217,7 @@ the session is already displayed in a eww tab, jao-eww-session can: (defun jao-eww-session-load () "Load last stored session into eww." (interactive) - (when-let* ((s (jao-eww-session-load-aux))) + (when-let ((s (jao-eww-session-load-aux))) (let* ((urls (jao-eww-session-urls s)) (offset (jao-eww-session-offset s)) (buffers (unless (equal jao-eww-session-duplicate-tabs 'always) diff --git a/lib/net/jao-notmuch-gnus.el b/lib/net/jao-notmuch-gnus.el index 1a03613..aa63d7c 100644 --- a/lib/net/jao-notmuch-gnus.el +++ b/lib/net/jao-notmuch-gnus.el @@ -1,6 +1,6 @@ ;;; jao-notmuch-gnus.el --- notmuch-gnus interoperability -*- lexical-binding: t; -*- -;; Copyright (C) 2022, 2024 jao +;; Copyright (C) 2022, 2024, 2025 jao ;; Author: jao <mail@jao.io> ;; Keywords: mail @@ -52,7 +52,7 @@ "Interactively add or remove tags to the current message." (interactive) (let* ((id (or id (jao-notmuch-gnus-message-id))) - (current (unless tags (jao-notmuch-gnus-message-tags id))) + (current (or tags (jao-notmuch-gnus-message-tags id))) (prompt (format "Change tags %s" (string-join current "/"))) (tags (or tags (notmuch-read-tag-changes current prompt)))) (notmuch-tag (concat "id:" id) tags) @@ -62,9 +62,14 @@ (defun jao-notmuch-gnus-show-tags () "Display in the echo area the tags of the current message." (interactive) - (when-let* ((id (jao-notmuch-gnus-message-id))) + (when-let (id (jao-notmuch-gnus-message-id)) (message "%s" (string-join (jao-notmuch-gnus-message-tags id) " ")))) +(jao-transient-major-mode+ gnus-summary + ["Tags" + ("s" "show message tags" jao-notmuch-gnus-show-tags) + ("t" "tag message" jao-notmuch-gnus-tag-message)]) + (defun jao-notmuch-gnus-toggle-tags (tags &optional id current) "Toggle the given TAGS list for the current Gnus message." (let* ((id (or id (jao-notmuch-gnus-message-id))) @@ -76,9 +81,9 @@ (message "New tags: %s" (jao-notmuch-gnus-message-tags id)))) (defun jao-notmuch-gnus-tag-mark () - "Remove the new tag for an article when it's marked as seen by Gnus." - (when-let* ((id (jao-notmuch-gnus-message-id t))) - (jao-notmuch-gnus-tag-message id '("-new") t))) + "Remove the new and unread tags for an article when it's marked as seen by Gnus." + (when-let (id (jao-notmuch-gnus-message-id t)) + (jao-notmuch-gnus-tag-message id '("-new" "-unread") t))) (add-hook 'gnus-mark-article-hook #'jao-notmuch-gnus-tag-mark) @@ -105,8 +110,32 @@ (add-to-list 'gnus-search-expandable-keys "list") -(cl-defmethod gnus-search-transform-expression ((engine gnus-search-notmuch) +(defclass gnus-search-jao-notmuch (gnus-search-notmuch) ()) + +(cl-defmethod gnus-search-indexed-search-command + ((engine gnus-search-jao-notmuch) (qstring string) query &optional groups) + (let* ((limit (alist-get 'limit query)) + (thread (alist-get 'thread query)) + (qs (cond (thread + (format "thread:\"{%s}\"" + (thread-last (string-replace "\"" "\"\"" qstring) + (string-replace "<" "") + (string-replace ">" "")))) + (groups + (let ((gs (mapconcat 'gnus-group-short-name groups "|"))) + (format "(%s) and folder:/%s/" qstring gs))) + (t qstring)))) + (with-slots (switches config-file) engine + `(,(format "--config=%s" config-file) "search" "--output=files" + ,@(unless thread '("--duplicate=1")) + ,@(when limit (list (format "--limit=%d" limit))) + ,@switches + ,qs)))) + + +(cl-defmethod gnus-search-transform-expression ((engine gnus-search-jao-notmuch) (expr (head list))) + (message "List query: %s" expr) (format "List:%s" (gnus-search-transform-expression engine (cdr expr)))) @@ -171,7 +200,7 @@ Example: (msg-id (when msg-id (replace-regexp-in-string "^id:" "" msg-id)))) (if (and group msg-id) (org-gnus-follow-link group msg-id) - (message "Couldn't get relevant infos for switching to Gnus.")))) + (message "Couldn't get relevant info for switching to Gnus.")))) (defun jao-notmuch-gnus-engine (prefix config) (let ((prefix (file-name-as-directory (expand-file-name prefix "~"))) @@ -191,12 +220,12 @@ Example: (org-gnus-follow-link group id))) (defun jao-notmuch-gnus-org-store () - (when-let* ((d (or (when (derived-mode-p 'notmuch-show-mode 'notmuch-tree-mode) - (cons (notmuch-show-get-message-id) - (notmuch-show-get-subject))) - (when (derived-mode-p 'gnus-summary-mode 'gnus-article-mode) - (cons (jao-notmuch-gnus-message-id) - (gnus-summary-article-subject)))))) + (when-let (d (or (when (derived-mode-p 'notmuch-show-mode 'notmuch-tree-mode) + (cons (notmuch-show-get-message-id) + (notmuch-show-get-subject))) + (when (derived-mode-p 'gnus-summary-mode 'gnus-article-mode) + (cons (jao-notmuch-gnus-message-id) + (gnus-summary-article-subject))))) (org-link-store-props :type "mail" :link (concat "mail:" (car d)) :description (concat "Mail: " (cdr d))))) @@ -223,6 +252,19 @@ Example: (consult-customize jao-gnus-consult-notmuch :preview-key 'any)) +;;; tags and flags + +(defun jao-notmuch-gnus-flag-current (&rest _) + (jao-notmuch-gnus-tag-message nil '("+flagged") t)) + +(defun jao-notmuch-gnus-unflag-current (&rest _) + (jao-notmuch-gnus-tag-message nil '("-flagged") t)) + +(advice-add 'gnus-summary-tick-article-forward + :before #'jao-notmuch-gnus-flag-current) +(advice-add 'gnus-summary-mark-as-read-forward + :before #'jao-notmuch-gnus-unflag-current) + ;;; . (provide 'jao-notmuch-gnus) ;;; jao-notmuch-gnus.el ends here diff --git a/lib/net/jao-notmuch.el b/lib/net/jao-notmuch.el index 2dc4b70..404eab7 100644 --- a/lib/net/jao-notmuch.el +++ b/lib/net/jao-notmuch.el @@ -1,6 +1,6 @@ -;;; jao-notmuch.el --- Extensions for notmuch -*- lexical-binding: t; -*- +;; jao-notmuch.el --- Extensions for notmuch -*- lexical-binding: t; -*- -;; Copyright (C) 2021, 2022, 2023, 2024 jao +;; Copyright (C) 2021, 2022, 2023, 2024, 2025 jao ;; Author: jao <mail@jao.io> ;; Keywords: mail @@ -69,7 +69,7 @@ (user-error "No tree view for this buffer"))) (defun jao-notmuch-tree--looking-at-message () - (when-let* ((id (plist-get (notmuch-tree-get-message-properties) :id))) + (when-let (id (plist-get (notmuch-tree-get-message-properties) :id)) (equal (concat "*notmuch-id:" id "*") (buffer-name (window-buffer notmuch-tree-message-window))))) @@ -105,7 +105,7 @@ (goto-char (point-min)) (let ((pos (point))) (while (setq pos (next-single-property-change pos 'w3m-href-anchor)) - (when-let* ((url (get-text-property pos 'w3m-href-anchor))) + (when-let ((url (get-text-property pos 'w3m-href-anchor))) (when (stringp url) (cl-pushnew url res :test #'string=)))) (seq-uniq res #'string=)))) @@ -117,7 +117,7 @@ (defun jao-notmuch-browse-urls (&optional external) (interactive "P") - (if-let* ((urls (jao-notmuch-message-urls))) + (if-let ((urls (jao-notmuch-message-urls))) (funcall (if external browse-url-secondary-browser-function #'browse-url) (completing-read "Browse URL: " urls)) (message "No URLs in this message"))) @@ -131,22 +131,22 @@ (interactive) (when (get-text-property (point) 'w3m-href-anchor) (goto-char (next-single-property-change (point) 'w3m-href-anchor))) - (if-let* ((pos (next-single-property-change (point) 'w3m-href-anchor))) + (if-let (pos (next-single-property-change (point) 'w3m-href-anchor)) (goto-char pos) (or (forward-button 1 nil t t) (ffap-next-guess)))) (defun jao-notmuch-show-previous-button () (interactive) - (if-let* ((pos (previous-single-property-change (point) 'w3m-href-anchor))) + (if-let (pos (previous-single-property-change (point) 'w3m-href-anchor)) (goto-char (previous-single-property-change pos 'w3m-href-anchor)) (or (backward-button 1 nil t t) (ffap-next-guess t)))) (defun jao-notmuch-show-ret () (interactive) - (when-let* ((url (or (get-text-property (point) 'w3m-href-anchor) - (thing-at-point-url-at-point)))) + (when-let (url (or (get-text-property (point) 'w3m-href-anchor) + (thing-at-point-url-at-point))) (browse-url url))) @@ -167,7 +167,7 @@ (jao-notmuch-goto-tree-buffer t))) (defun jao-notmuch--view-html () - "Open the text/html part of the current message using `notmuch-show-view-part'." + "Open the text/html part of current message using `notmuch-show-view-part'." (interactive) (save-excursion (goto-char @@ -212,10 +212,10 @@ (with-current-buffer notmuch-tree-message-buffer (jao-notmuch--view-html)))))) -;;; header line with thread message counts +;;; header and mode lines with thread message counts (defun jao-notmuch--looking-at-new-p (&optional p) - (when-let* ((ts (if p (plist-get p :tags) (notmuch-show-get-tags)))) + (when-let (ts (if p (plist-get p :tags) (notmuch-show-get-tags))) (or (member "unread" ts) (member "new" ts)))) (defsubst jao-notmuch-tree--first-p (&optional msg) @@ -266,7 +266,8 @@ (with-current-buffer b (and (derived-mode-p 'notmuch-tree-mode) b))) (buffer-list)))) - `((:eval (jao-notmuch--format-header-line ,(buffer-name tb) ,cb ,subject))) + `((:eval + (jao-notmuch--format-header-line ,(buffer-name tb) ,cb ,subject))) (concat " " subject))) (defun jao-notmuch--format-lighter () @@ -316,6 +317,12 @@ (let ((undo (jao-notmuch--has-tag "deleted"))) (jao-notmuch-tree-tag-thread '("+deleted" "-new" "-unread") undo full))) +(defun jao-notmuch-tree-mark-all-read () + (interactive) + (when-let* ((q notmuch-tree-basic-query)) + (when (yes-or-no-p "Mark all messages as read? ") + (notmuch-tag q '("-new" "-unread"))))) + (defun jao-notmuch-tree-read-thread (full) (interactive "P") (jao-notmuch-tree-tag-thread '("-unread" "-new") nil full)) @@ -339,35 +346,28 @@ (let ((tags (plist-get (notmuch-tree-get-message-properties) :orig-tags))) (jao-notmuch-tree--tag tags nil))) +(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))))) + + ;;; fcc -(defvar jao-notmuch-mua-reply-not-inherited - '("attachment" "sent" "new" "bigml" "jao" "trove")) - -(defun jao-notmuch-mua--fcc-dirs () - (let* ((otags (notmuch-show-get-tags)) - (trove (or (seq-some (lambda (x) (and (member x otags) x)) - '("hacking" "bills" "feeds" "jao")) - "jao")) - (tags (seq-difference otags jao-notmuch-mua-reply-not-inherited)) - (tagstr (mapconcat (lambda (s) (concat "+" s)) tags " ")) - (fcc (concat "trove/" trove " " tagstr " -new +sent +trove")) - (fcc-dirs (assoc-delete-all ".*" (copy-alist notmuch-fcc-dirs)))) - (append fcc-dirs `((".*" . ,fcc))))) +(defvar jao-notmuch-tags-not-inherited + '("attachment" "sent" "new" "trove" "flagged" "drivel" "replied")) + +(defvar jao-notmuch-sent-dir "sent") (defun jao-notmuch-mua--inherited-fcc () - (let* ((fn (notmuch-show-get-filename)) - (dest (and (string-match ".*/var/mail/\\(.+?\\)/.+" fn) - (match-string 1 fn))) - (tags (seq-difference (notmuch-show-get-tags) - '("attachment" "sent" "new" "flagged"))) + (let* ((tags (seq-difference (notmuch-show-get-tags) + jao-notmuch-tags-not-inherited)) (tagstr (mapconcat (lambda (s) (concat "+" s)) tags " ")) - (fcc (concat dest " " tagstr " -new +sent +trove")) + (fcc (concat jao-notmuch-sent-dir " " tagstr " -new +sent")) (fcc-dirs (assoc-delete-all ".*" (copy-alist notmuch-fcc-dirs)))) (append fcc-dirs `((".*" . ,fcc))))) (defun jao-notmuch-mua-new-reply (fun &rest args) - (let ((notmuch-fcc-dirs (and (not (notmuch-show-get-header :List-Id)) - (jao-notmuch-mua--inherited-fcc)))) + (let ((notmuch-fcc-dirs (jao-notmuch-mua--inherited-fcc))) (apply fun args))) (advice-add 'notmuch-mua-new-reply :around #'jao-notmuch-mua-new-reply) @@ -384,9 +384,10 @@ (seq-sort #'jao-notmuch-cmp-tags)))) (format-spec fmt `((?s . ,(mapconcat #'identity ts " ")))))) -(defun jao-notmuch-format-tree-and-subject (fmt msg) +(defun jao-notmuch-format-tree-and-subject (_fmt msg) (let ((tr (notmuch-tree-format-field "tree" " %s" msg)) - (sb (notmuch-tree-format-field "subject" " %s" msg))) + (sb (notmuch-tree-format-field "subject" " %s" msg)) + (fmt (format "%%>-%ds" (- (window-width) 60)))) (format-spec fmt `((?s . ,(concat tr sb)))))) (defun jao-notmuch-format-msg-ticks (mails-rx msg) @@ -398,4 +399,24 @@ (t " ")))) (provide 'jao-notmuch) +;;; org links +(defun jao-notmuch-id-file-name (id) + (let ((cmd (format "notmuch search --output=files id:%s" id))) + (car (split-string (shell-command-to-string cmd))))) + +(defun jao-notmuch-org-store () + (when-let* ((d (and (derived-mode-p '(notmuch-show-mode notmuch-tree-mode)) + (cons (notmuch-show-get-message-id) + (notmuch-show-get-subject))))) + (org-link-store-props :type "mail" + :link (concat "mail:" (car d)) + :description (concat "Mail: " (cdr d))))) + +(defun jao-notmuch-org-links () + (org-link-set-parameters "mail" + :follow #'notmuch-show + :store #'jao-notmuch-org-store) + (org-link-set-parameters "gnus" :store #'ignore) + (org-link-set-parameters "notmuch" :store #'ignore)) + ;;; jao-notmuch.el ends here diff --git a/lib/net/jao-proton-utils.el b/lib/net/jao-proton-utils.el index 0c9ccd7..62b97b3 100644 --- a/lib/net/jao-proton-utils.el +++ b/lib/net/jao-proton-utils.el @@ -86,7 +86,7 @@ (jao-proton-vpn--do "s")) (defun proton-vpn--get-status () - (or (when-let* ((b (get-buffer jao-proton-vpn--buffer))) + (or (when-let ((b (get-buffer jao-proton-vpn--buffer))) (with-current-buffer b (goto-char (point-min)) (if (re-search-forward "^Status: *\\(.+\\)$" nil t) diff --git a/lib/net/jao-url.el b/lib/net/jao-url.el new file mode 100644 index 0000000..ac66cef --- /dev/null +++ b/lib/net/jao-url.el @@ -0,0 +1,45 @@ +;;; jao-url.el --- URL handling -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <mail@jao.io> +;; Keywords: hypermedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(require 'shr) +(require 'ffap) +(require 'thingatpt) + +(defun jao-url-around-point (&optional current-url) + (or (and (fboundp 'w3m-anchor) (w3m-anchor)) + (shr-url-at-point nil) + (ffap-url-at-point) + (thing-at-point 'url) + (when current-url + (or (and (fboundp 'w3m-anchor) (w3m-anchor)) + (and (derived-mode-p 'eww-mode) (plist-get eww-data :url)))))) + + +(defun jao-url-email-url () + (save-excursion + (goto-char (point-min)) + (when (or (search-forward-regexp "^Via: h" nil t) + (search-forward-regexp "^URL:[\n ]h" nil t) + (and (search-forward-regexp "^Link$" nil t) + (not (beginning-of-line)))) + (jao-url-around-point)))) + +(provide 'jao-url) +;;; jao-url.el ends here diff --git a/lib/net/randomsig.el b/lib/net/randomsig.el index cb37694..05b95ab 100644 --- a/lib/net/randomsig.el +++ b/lib/net/randomsig.el @@ -1,6 +1,6 @@ ;;; randomsig.el --- insert a randomly selected signature -;; Copyright (C) 2001, 2002, 2013, 2020, 2021 Hans-Jürgen Ficker +;; Copyright (C) 2001, 2002, 2013, 2020, 2021, 2024 Hans-Jürgen Ficker ;; Emacs Lisp Archive Entry ;; Author: Hans-Juergen Ficker <hj@backmes.de> @@ -277,8 +277,11 @@ You probably want to have a newline at the end of it." (defun randomsig-prompt (&optional prompt) ;; Prompt for a signature file. (let ((files (randomsig-files-to-list randomsig-files))) - (completing-read (if prompt prompt "signature: ") - (mapcar 'list files) nil t nil randomsig-history (car files)))) + (if (cdr files) + (completing-read (if prompt prompt "signature: ") + (mapcar 'list files) nil t nil + randomsig-history (car files)) + (car files)))) (defun randomsig-read-signatures-to-buffer (buffer-name &optional files) ;; read the signatures into the signature buffer |
