From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Manuel Giraud Newsgroups: gmane.emacs.bugs Subject: bug#53877: 29.0.50; [PATCH] async Gnus/nnml Date: Tue, 08 Feb 2022 15:22:18 +0100 Message-ID: <87leyl1lr9.fsf@elite.giraud> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="18637"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (berkeley-unix) To: 53877@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Feb 08 16:12:05 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nHSA0-0004YH-Lv for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 08 Feb 2022 16:12:04 +0100 Original-Received: from localhost ([::1]:43542 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nHS9z-0004yF-Ek for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 08 Feb 2022 10:12:03 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:51740) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nHROZ-0006u0-QY for bug-gnu-emacs@gnu.org; Tue, 08 Feb 2022 09:23:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:52067) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nHROY-0006BA-9H for bug-gnu-emacs@gnu.org; Tue, 08 Feb 2022 09:23:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nHROY-0004jL-0n for bug-gnu-emacs@gnu.org; Tue, 08 Feb 2022 09:23:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Manuel Giraud Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 08 Feb 2022 14:23:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 53877 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.164433017218148 (code B ref -1); Tue, 08 Feb 2022 14:23:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 8 Feb 2022 14:22:52 +0000 Original-Received: from localhost ([127.0.0.1]:45964 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nHROM-0004ic-4E for submit@debbugs.gnu.org; Tue, 08 Feb 2022 09:22:52 -0500 Original-Received: from lists.gnu.org ([209.51.188.17]:53482) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nHROI-0004iO-MT for submit@debbugs.gnu.org; Tue, 08 Feb 2022 09:22:49 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:51620) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nHRO8-0006X2-US for bug-gnu-emacs@gnu.org; Tue, 08 Feb 2022 09:22:42 -0500 Original-Received: from ledu-giraud.fr ([51.159.28.247]:30481) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nHRNz-00065L-Vy for bug-gnu-emacs@gnu.org; Tue, 08 Feb 2022 09:22:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=rsa; bh=MflCLgKLhS03eJRr foezj4gmZOHn5HowuWq1hJOQWso=; h=date:subject:to:from; d=ledu-giraud.fr; b=HuvqSTFk2gA8MYXXGPAnQQH6XN9jbbpFQa3ogfPGdf/afIPIWl 9CW3yfU8D+/FgO5IsHMgH/WK5Zcn1HGAERj6Q2pfyWWaaX0kKHcjkfdE7j31NEKvBc7W0K aPKTaYF8gvwAcs9W0ursTqXljpdkJJUCgEoX73ZRumdaAsXb33eqlD61U1wSkol2dgU36+ IpzCaP5UGsKkBZx7hYamIJKujcWBOz81aPGLAVV40w7PS+szk0DnX6+Zz3rHLWkm9Z7fCW nf4wIxa28lBgXENRM31OjUzK26cCLS7ki5OTxx5IL8TzAZGTVoKooNTrqmwek/uRWwyfvI Xnh2cQtksvnA== Original-Received: from elite.giraud ( [10.1.1.1]) by ledu-giraud.fr (OpenSMTPD) with ESMTPSA id f2382942 (TLSv1.3:AEAD-AES256-GCM-SHA384:256:NO) for ; Tue, 8 Feb 2022 15:22:19 +0100 (CET) Received-SPF: pass client-ip=51.159.28.247; envelope-from=manuel@ledu-giraud.fr; helo=ledu-giraud.fr X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:226377 Archived-At: --=-=-= Content-Type: text/plain Hi, I'm trying to have an asynchronous Gnus nnml backend. In the process, I found some things that I'd like to have first in nnmail.el and mail-sources.el (see patches). There is nothing asynchronous so far so Gnus behaviour shouldn't have changed that much. Best regards, --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-just-use-temp-buffer-for-nnmail-article-buffer.patch >From 21a6dfc1648cf5ec3a773d7624806a24c9b358a4 Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Tue, 8 Feb 2022 13:19:44 +0100 Subject: [PATCH 1/4] just use temp-buffer for `nnmail-article-buffer'. It is used in one and only place as a temporary buffer. --- lisp/gnus/nnmail.el | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el index c71627f83a..af9c439280 100644 --- a/lisp/gnus/nnmail.el +++ b/lisp/gnus/nnmail.el @@ -571,9 +571,6 @@ nnmail-debug-splitting ;;; Internal variables. -(defvar nnmail-article-buffer " *nnmail incoming*" - "The buffer used for splitting incoming mails.") - (defvar nnmail-split-history nil "List of group/article elements that say where the previous split put messages.") @@ -1043,8 +1040,7 @@ nnmail-split-incoming (list (list group "")) nnmail-split-methods))) ;; Insert the incoming file. - (with-current-buffer (gnus-get-buffer-create nnmail-article-buffer) - (erase-buffer) + (with-temp-buffer (if (bufferp incoming) (insert-buffer-substring incoming) ;; The following coding system is set to @@ -1072,8 +1068,7 @@ nnmail-split-incoming (t (nnmail-process-unix-mail-format func artnum-func)))) (when exit-func - (funcall exit-func)) - (kill-buffer (current-buffer)))))) + (funcall exit-func)))))) (defun nnmail-article-group (func &optional trace junk-func) "Look at the headers and return an alist of groups that match. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-uniquify-mail-source-crash-box-on-each-different-mai.patch >From 798555baaa3f4afca663a6ac29bc42bf313144bc Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Wed, 2 Feb 2022 10:50:57 +0100 Subject: [PATCH 2/4] uniquify mail-source-crash-box on each different mail-source fetcher. --- lisp/gnus/mail-source.el | 386 ++++++++++++++++++++------------------- 1 file changed, 202 insertions(+), 184 deletions(-) diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el index 5d0c0e2654..4498ea13f6 100644 --- a/lisp/gnus/mail-source.el +++ b/lisp/gnus/mail-source.el @@ -238,10 +238,12 @@ mail-source-flash "If non-nil, flash periodically when mail is available." :type 'boolean) -(defcustom mail-source-crash-box "~/.emacs-mail-crash-box" - "File where mail will be stored while processing it." +(defcustom mail-source-crash-box-prefix "~/.emacs-mail-crash-box-" + "Prefix of files where mail will be stored while processing it." :type 'file) +(make-obsolete-variable 'mail-source-crash-box 'mail-source-crash-box-prefix "29.1") + (defcustom mail-source-directory message-directory "Directory where incoming mail source files (if any) will be stored." :type 'directory) @@ -518,6 +520,18 @@ mail-source-value (autoload 'nnheader-message "nnheader") +(defun mail-source-fetcher (source) + (cadr (assq (car source) mail-source-fetcher-alist))) + +(defun mail-source-crash-box () + (make-temp-name mail-source-crash-box-prefix)) + +(defun mail-source-existing-crash-boxes () + (let ((directory (file-name-directory mail-source-crash-box-prefix)) + (partial (file-name-nondirectory mail-source-crash-box-prefix))) + (mapcar #'(lambda (name) (file-name-concat directory name)) + (file-name-all-completions partial directory)))) + (defun mail-source-fetch (source callback &optional method) "Fetch mail from SOURCE and call CALLBACK zero or more times. CALLBACK will be called with the name of the file where (some of) @@ -536,21 +550,20 @@ mail-source-fetch (format "%s: " method) "") (car source))) - (let ((function (cadr (assq (car source) mail-source-fetcher-alist))) + (let ((fetcher (mail-source-fetcher source)) (found 0)) - (unless function + (unless fetcher (error "%S is an invalid mail source specification" source)) - ;; If there's anything in the crash box, we do it first. - (when (file-exists-p mail-source-crash-box) - (message "Processing mail from %s..." mail-source-crash-box) - (setq found (mail-source-callback - callback mail-source-crash-box)) - (mail-source-delete-crash-box)) + ;; If there's anything in some crash boxes, we do it first. + (dolist (box (mail-source-existing-crash-boxes)) + (message "Processing mail from %s..." box) + (setq found (mail-source-callback callback box box)) + (mail-source-delete-crash-box box)) (+ found (if (or debug-on-quit debug-on-error) - (funcall function source callback) + (funcall fetcher source callback) (condition-case err - (funcall function source callback) + (funcall fetcher source callback) (error (gnus-error 5 @@ -596,24 +609,24 @@ mail-source-delete-old-incoming t)) (delete-file ffile)))))) -(defun mail-source-callback (callback info) +(defun mail-source-callback (callback info crash-box) "Call CALLBACK on the mail file. Pass INFO on to CALLBACK." - (if (or (not (file-exists-p mail-source-crash-box)) + (if (or (not (file-exists-p crash-box)) (zerop (file-attribute-size - (file-attributes mail-source-crash-box)))) + (file-attributes crash-box)))) (progn - (when (file-exists-p mail-source-crash-box) - (delete-file mail-source-crash-box)) + (when (file-exists-p crash-box) + (delete-file crash-box)) 0) - (funcall callback mail-source-crash-box info))) + (funcall callback crash-box info))) (defvar mail-source-incoming-last-checked-time nil) -(defun mail-source-delete-crash-box () - (when (file-exists-p mail-source-crash-box) +(defun mail-source-delete-crash-box (crash-box) + (when (file-exists-p crash-box) ;; Delete or move the incoming mail out of the way. (if (eq mail-source-delete-incoming t) - (delete-file mail-source-crash-box) + (delete-file crash-box) (let ((incoming (make-temp-file (expand-file-name @@ -621,7 +634,7 @@ mail-source-delete-crash-box mail-source-directory)))) (unless (file-exists-p (file-name-directory incoming)) (make-directory (file-name-directory incoming) t)) - (rename-file mail-source-crash-box incoming t) + (rename-file crash-box incoming t) ;; remove old incoming files? (when (natnump mail-source-delete-incoming) ;; Don't check for old incoming files more than once per day to @@ -750,17 +763,18 @@ mail-source-call-script (defun mail-source-fetch-file (source callback) "Fetcher for single-file sources." (mail-source-bind (file source) - (mail-source-run-script - prescript `((?t . ,mail-source-crash-box)) - prescript-delay) - (let ((mail-source-string (format "file:%s" path))) - (if (mail-source-movemail path mail-source-crash-box) - (prog1 - (mail-source-callback callback path) - (mail-source-run-script - postscript `((?t . ,mail-source-crash-box))) - (mail-source-delete-crash-box)) - 0)))) + (let ((crash-box (mail-source-crash-box))) + (mail-source-run-script + prescript `((?t . ,crash-box)) + prescript-delay) + (let ((mail-source-string (format "file:%s" path))) + (if (mail-source-movemail path crash-box) + (prog1 + (mail-source-callback callback path crash-box) + (mail-source-run-script + postscript `((?t . ,crash-box))) + (mail-source-delete-crash-box crash-box)) + 0))))) (defun mail-source-fetch-directory (source callback) "Fetcher for directory sources." @@ -768,92 +782,94 @@ mail-source-fetch-directory (mail-source-run-script prescript `((?t . ,path)) prescript-delay) (let ((found 0) - (mail-source-string (format "directory:%s" path))) + (mail-source-string (format "directory:%s" path)) + (crash-box (mail-source-crash-box))) (dolist (file (directory-files path t (concat (regexp-quote suffix) "$"))) (when (and (file-regular-p file) (funcall predicate file) - (mail-source-movemail file mail-source-crash-box)) - (cl-incf found (mail-source-callback callback file)) + (mail-source-movemail file crash-box)) + (cl-incf found (mail-source-callback callback file crash-box)) (mail-source-run-script postscript `((?t . ,path))) - (mail-source-delete-crash-box))) + (mail-source-delete-crash-box crash-box))) found))) (defun mail-source-fetch-pop (source callback) "Fetcher for single-file sources." (mail-source-bind (pop source) - ;; fixme: deal with stream type in format specs - (mail-source-run-script - prescript - `((?p . ,password) (?t . ,mail-source-crash-box) - (?s . ,server) (?P . ,port) (?u . ,user)) - prescript-delay) - (let ((from (format "%s:%s:%s" server user port)) - (mail-source-string (format "pop:%s@%s" user server)) - (process-environment (if server - (cons (concat "MAILHOST=" server) - process-environment) - process-environment)) - result) - (when (eq authentication 'password) - (setq password - (or password - (cdr (assoc from mail-source-password-cache)) - (read-passwd - (format "Password for %s at %s: " user server))))) - (setq result - (cond - (program - (mail-source-fetch-with-program - (format-spec - program - `((?p . ,password) (?t . ,mail-source-crash-box) - (?s . ,server) (?P . ,port) (?u . ,user))))) - (function - (funcall function mail-source-crash-box)) - ;; The default is to use pop3.el. - (t - (require 'pop3) - (dlet ((pop3-password password) - (pop3-maildrop user) - (pop3-mailhost server) - (pop3-port port) - (pop3-authentication-scheme - (if (eq authentication 'apop) 'apop 'pass)) - (pop3-stream-type stream) - (pop3-leave-mail-on-server leave)) - (if (or debug-on-quit debug-on-error) - (save-excursion (pop3-movemail mail-source-crash-box)) - (condition-case err - (save-excursion (pop3-movemail mail-source-crash-box)) - (error - ;; We nix out the password in case the error - ;; was because of a wrong password being given. - (setq mail-source-password-cache - (delq (assoc from mail-source-password-cache) - mail-source-password-cache)) - (signal (car err) (cdr err))))))))) - (if result - (progn - (when (eq authentication 'password) - (unless (assoc from mail-source-password-cache) - (push (cons from password) mail-source-password-cache))) - (prog1 - (mail-source-callback callback server) - ;; Update display-time's mail flag, if relevant. - (if (equal source mail-source-primary-source) - (setq mail-source-new-mail-available nil)) - (mail-source-run-script - postscript - `((?p . ,password) (?t . ,mail-source-crash-box) - (?s . ,server) (?P . ,port) (?u . ,user))) - (mail-source-delete-crash-box))) - ;; We nix out the password in case the error - ;; was because of a wrong password being given. - (setq mail-source-password-cache - (delq (assoc from mail-source-password-cache) - mail-source-password-cache)) - 0)))) + (let ((crash-box (mail-source-crash-box))) + ;; fixme: deal with stream type in format specs + (mail-source-run-script + prescript + `((?p . ,password) (?t . ,crash-box) + (?s . ,server) (?P . ,port) (?u . ,user)) + prescript-delay) + (let ((from (format "%s:%s:%s" server user port)) + (mail-source-string (format "pop:%s@%s" user server)) + (process-environment (if server + (cons (concat "MAILHOST=" server) + process-environment) + process-environment)) + result) + (when (eq authentication 'password) + (setq password + (or password + (cdr (assoc from mail-source-password-cache)) + (read-passwd + (format "Password for %s at %s: " user server))))) + (setq result + (cond + (program + (mail-source-fetch-with-program + (format-spec + program + `((?p . ,password) (?t . ,crash-box) + (?s . ,server) (?P . ,port) (?u . ,user))))) + (function + (funcall function crash-box)) + ;; The default is to use pop3.el. + (t + (require 'pop3) + (dlet ((pop3-password password) + (pop3-maildrop user) + (pop3-mailhost server) + (pop3-port port) + (pop3-authentication-scheme + (if (eq authentication 'apop) 'apop 'pass)) + (pop3-stream-type stream) + (pop3-leave-mail-on-server leave)) + (if (or debug-on-quit debug-on-error) + (save-excursion (pop3-movemail crash-box)) + (condition-case err + (save-excursion (pop3-movemail crash-box)) + (error + ;; We nix out the password in case the error + ;; was because of a wrong password being given. + (setq mail-source-password-cache + (delq (assoc from mail-source-password-cache) + mail-source-password-cache)) + (signal (car err) (cdr err))))))))) + (if result + (progn + (when (eq authentication 'password) + (unless (assoc from mail-source-password-cache) + (push (cons from password) mail-source-password-cache))) + (prog1 + (mail-source-callback callback server crash-box) + ;; Update display-time's mail flag, if relevant. + (if (equal source mail-source-primary-source) + (setq mail-source-new-mail-available nil)) + (mail-source-run-script + postscript + `((?p . ,password) (?t . ,crash-box) + (?s . ,server) (?P . ,port) (?u . ,user))) + (mail-source-delete-crash-box crash-box))) + ;; We nix out the password in case the error + ;; was because of a wrong password being given. + (setq mail-source-password-cache + (delq (assoc from mail-source-password-cache) + mail-source-password-cache)) + 0))))) (defun mail-source-check-pop (source) "Check whether there is new mail." @@ -1001,6 +1017,7 @@ mail-source-fetch-maildir "Fetcher for maildir sources." (mail-source-bind (maildir source) (let ((found 0) + (crash-box (mail-source-crash-box)) mail-source-string) (unless (string-match "/$" path) (setq path (concat path "/"))) @@ -1011,12 +1028,12 @@ mail-source-fetch-maildir (when (and (not (file-directory-p file)) (not (if function ;; `function' should return nil if successful. - (funcall function file mail-source-crash-box) + (funcall function file crash-box) (let ((coding-system-for-write mm-text-coding-system) (coding-system-for-read mm-text-coding-system)) - (with-temp-file mail-source-crash-box + (with-temp-file crash-box (insert-file-contents file) (goto-char (point-min)) ;;; ;; Unix mail format @@ -1031,8 +1048,8 @@ mail-source-fetch-maildir (insert "\001\001\001\001\n")) (delete-file file) nil)))) - (cl-incf found (mail-source-callback callback file)) - (mail-source-delete-crash-box))))) + (cl-incf found (mail-source-callback callback file crash-box)) + (mail-source-delete-crash-box crash-box))))) found))) (autoload 'imap-open "imap") @@ -1058,78 +1075,79 @@ mail-source-imap-file-coding-system (defun mail-source-fetch-imap (source callback) "Fetcher for imap sources." (mail-source-bind (imap source) - (mail-source-run-script - prescript - `((?p . ,password) (?t . ,mail-source-crash-box) - (?s . ,server) (?P . ,port) (?u . ,user)) - prescript-delay) - (let ((from (format "%s:%s:%s" server user port)) - (found 0) - (buf (generate-new-buffer " *imap source*")) - (mail-source-string (format "imap:%s:%s" server mailbox)) - (imap-shell-program (or (list program) imap-shell-program)) - remove) - (if (and (imap-open server port stream authentication buf) - (imap-authenticate - user (or (cdr (assoc from mail-source-password-cache)) - password) - buf)) - (let ((mailbox-list (if (listp mailbox) mailbox (list mailbox)))) - (dolist (mailbox mailbox-list) - (when (imap-mailbox-select mailbox nil buf) - (let ((coding-system-for-write mail-source-imap-file-coding-system) - str) - (message "Fetching from %s..." mailbox) - (with-temp-file mail-source-crash-box - ;; Avoid converting 8-bit chars from inserted strings to - ;; multibyte. - (mm-disable-multibyte) - ;; remember password - (with-current-buffer buf - (when (and imap-password - (not (member (cons from imap-password) - mail-source-password-cache))) - (push (cons from imap-password) mail-source-password-cache))) - ;; if predicate is nil, use all uids - (dolist (uid (imap-search (or predicate "1:*") buf)) - (when (setq str - (if (imap-capability 'IMAP4rev1 buf) - (caddar (imap-fetch uid "BODY.PEEK[]" - 'BODYDETAIL nil buf)) - (imap-fetch uid "RFC822.PEEK" 'RFC822 nil buf))) - (push uid remove) - (insert "From imap " (current-time-string) "\n") - (save-excursion - (insert str "\n\n")) - (while (let ((case-fold-search nil)) - (re-search-forward "^From " nil t)) - (replace-match ">From ")) - (goto-char (point-max)))) - (nnheader-ms-strip-cr)) - (cl-incf found (mail-source-callback callback server)) - (mail-source-delete-crash-box) - (when (and remove fetchflag) - (setq remove (nreverse remove)) - (imap-message-flags-add - (imap-range-to-message-set (gnus-compress-sequence remove)) - fetchflag nil buf)) - (if dontexpunge - (imap-mailbox-unselect buf) - (imap-mailbox-close nil buf))))) - (imap-close buf)) - (imap-close buf) - ;; We nix out the password in case the error - ;; was because of a wrong password being given. - (setq mail-source-password-cache - (delq (assoc from mail-source-password-cache) - mail-source-password-cache)) - (error "IMAP error: %s" (imap-error-text buf))) - (kill-buffer buf) + (let ((crash-box (mail-source-crash-box))) (mail-source-run-script - postscript - `((?p . ,password) (?t . ,mail-source-crash-box) - (?s . ,server) (?P . ,port) (?u . ,user))) - found))) + prescript + `((?p . ,password) (?t . ,crash-box) + (?s . ,server) (?P . ,port) (?u . ,user)) + prescript-delay) + (let ((from (format "%s:%s:%s" server user port)) + (found 0) + (buf (generate-new-buffer " *imap source*")) + (mail-source-string (format "imap:%s:%s" server mailbox)) + (imap-shell-program (or (list program) imap-shell-program)) + remove) + (if (and (imap-open server port stream authentication buf) + (imap-authenticate + user (or (cdr (assoc from mail-source-password-cache)) + password) + buf)) + (let ((mailbox-list (if (listp mailbox) mailbox (list mailbox)))) + (dolist (mailbox mailbox-list) + (when (imap-mailbox-select mailbox nil buf) + (let ((coding-system-for-write mail-source-imap-file-coding-system) + str) + (message "Fetching from %s..." mailbox) + (with-temp-file crash-box + ;; Avoid converting 8-bit chars from inserted strings to + ;; multibyte. + (mm-disable-multibyte) + ;; remember password + (with-current-buffer buf + (when (and imap-password + (not (member (cons from imap-password) + mail-source-password-cache))) + (push (cons from imap-password) mail-source-password-cache))) + ;; if predicate is nil, use all uids + (dolist (uid (imap-search (or predicate "1:*") buf)) + (when (setq str + (if (imap-capability 'IMAP4rev1 buf) + (caddar (imap-fetch uid "BODY.PEEK[]" + 'BODYDETAIL nil buf)) + (imap-fetch uid "RFC822.PEEK" 'RFC822 nil buf))) + (push uid remove) + (insert "From imap " (current-time-string) "\n") + (save-excursion + (insert str "\n\n")) + (while (let ((case-fold-search nil)) + (re-search-forward "^From " nil t)) + (replace-match ">From ")) + (goto-char (point-max)))) + (nnheader-ms-strip-cr)) + (cl-incf found (mail-source-callback callback server crash-box)) + (mail-source-delete-crash-box crash-box) + (when (and remove fetchflag) + (setq remove (nreverse remove)) + (imap-message-flags-add + (imap-range-to-message-set (gnus-compress-sequence remove)) + fetchflag nil buf)) + (if dontexpunge + (imap-mailbox-unselect buf) + (imap-mailbox-close nil buf))))) + (imap-close buf)) + (imap-close buf) + ;; We nix out the password in case the error + ;; was because of a wrong password being given. + (setq mail-source-password-cache + (delq (assoc from mail-source-password-cache) + mail-source-password-cache)) + (error "IMAP error: %s" (imap-error-text buf))) + (kill-buffer buf) + (mail-source-run-script + postscript + `((?p . ,password) (?t . ,crash-box) + (?s . ,server) (?P . ,port) (?u . ,user))) + found)))) (provide 'mail-source) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-mutex-on-nnmail-cache.patch >From a1dc119bfb777f813f7967256fc0835c34d2c0be Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Thu, 3 Feb 2022 13:52:41 +0100 Subject: [PATCH 3/4] mutex on nnmail cache. --- lisp/gnus/nnmail.el | 83 ++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el index af9c439280..642ca16e28 100644 --- a/lisp/gnus/nnmail.el +++ b/lisp/gnus/nnmail.el @@ -1556,6 +1556,7 @@ nnmail-message-id ;;; (defvar nnmail-cache-buffer nil) +(defvar nnmail-cache-buffer-mutex (make-mutex)) (defun nnmail-cache-open () (if (or (not nnmail-treat-duplicates) @@ -1574,22 +1575,23 @@ nnmail-cache-close (when (and nnmail-treat-duplicates (buffer-live-p nnmail-cache-buffer) (buffer-modified-p nnmail-cache-buffer)) - (with-current-buffer nnmail-cache-buffer - ;; Weed out the excess number of Message-IDs. - (goto-char (point-max)) - (when (search-backward "\n" nil t nnmail-message-id-cache-length) - (progn - (beginning-of-line) - (delete-region (point-min) (point)))) - ;; Save the buffer. - (or (file-exists-p (file-name-directory nnmail-message-id-cache-file)) - (make-directory (file-name-directory nnmail-message-id-cache-file) - t)) - (nnmail-write-region (point-min) (point-max) - nnmail-message-id-cache-file nil 'silent) - (set-buffer-modified-p nil) - (setq nnmail-cache-buffer nil) - (gnus-kill-buffer (current-buffer))))) + (with-mutex nnmail-cache-buffer-mutex + (with-current-buffer nnmail-cache-buffer + ;; Weed out the excess number of Message-IDs. + (goto-char (point-max)) + (when (search-backward "\n" nil t nnmail-message-id-cache-length) + (progn + (beginning-of-line) + (delete-region (point-min) (point)))) + ;; Save the buffer. + (or (file-exists-p (file-name-directory nnmail-message-id-cache-file)) + (make-directory (file-name-directory nnmail-message-id-cache-file) + t)) + (nnmail-write-region (point-min) (point-max) + nnmail-message-id-cache-file nil 'silent) + (set-buffer-modified-p nil) + (setq nnmail-cache-buffer nil) + (gnus-kill-buffer (current-buffer)))))) (defun nnmail-cache-insert (id grp &optional subject sender) (when (stringp id) @@ -1605,18 +1607,19 @@ nnmail-cache-insert ;; pass the first (of possibly >1) group which matches. -Josh (unless (gnus-buffer-live-p nnmail-cache-buffer) (nnmail-cache-open)) - (with-current-buffer nnmail-cache-buffer - (goto-char (point-max)) - (if (and grp (not (string= "" grp)) - (gnus-methods-equal-p gnus-command-method - (nnmail-cache-primary-mail-backend))) - (let ((regexp (if (consp nnmail-cache-ignore-groups) - (mapconcat #'identity nnmail-cache-ignore-groups - "\\|") - nnmail-cache-ignore-groups))) - (unless (and regexp (string-match regexp grp)) - (insert id "\t" grp "\n"))) - (insert id "\n")))))) + (with-mutex nnmail-cache-buffer-mutex + (with-current-buffer nnmail-cache-buffer + (goto-char (point-max)) + (if (and grp (not (string= "" grp)) + (gnus-methods-equal-p gnus-command-method + (nnmail-cache-primary-mail-backend))) + (let ((regexp (if (consp nnmail-cache-ignore-groups) + (mapconcat #'identity nnmail-cache-ignore-groups + "\\|") + nnmail-cache-ignore-groups))) + (unless (and regexp (string-match regexp grp)) + (insert id "\t" grp "\n"))) + (insert id "\n"))))))) (defun nnmail-cache-primary-mail-backend () (let ((be-list (cons gnus-select-method gnus-secondary-select-methods)) @@ -1638,14 +1641,15 @@ nnmail-cache-primary-mail-backend ;; cache. (defun nnmail-cache-fetch-group (id) (when (and nnmail-treat-duplicates nnmail-cache-buffer) - (with-current-buffer nnmail-cache-buffer - (goto-char (point-max)) - (when (search-backward id nil t) - (beginning-of-line) - (skip-chars-forward "^\n\r\t") - (unless (looking-at "[\r\n]") - (forward-char 1) - (buffer-substring (point) (point-at-eol))))))) + (with-mutex nnmail-cache-buffer-mutex + (with-current-buffer nnmail-cache-buffer + (goto-char (point-max)) + (when (search-backward id nil t) + (beginning-of-line) + (skip-chars-forward "^\n\r\t") + (unless (looking-at "[\r\n]") + (forward-char 1) + (buffer-substring (point) (point-at-eol)))))))) ;; Function for nnmail-split-fancy: look up all references in the ;; cache and if a match is found, return that group. @@ -1682,9 +1686,10 @@ nnmail-split-fancy-with-parent (defun nnmail-cache-id-exists-p (id) (when nnmail-treat-duplicates - (with-current-buffer nnmail-cache-buffer - (goto-char (point-max)) - (search-backward id nil t)))) + (with-mutex nnmail-cache-buffer-mutex + (with-current-buffer nnmail-cache-buffer + (goto-char (point-max)) + (search-backward id nil t))))) (defun nnmail-fetch-field (header) (save-excursion -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-separate-update-unread-of-group.patch >From 07dae695797f2646a1653691cdda7123b2c0e160 Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Sat, 5 Feb 2022 16:39:01 +0100 Subject: [PATCH 4/4] separate update unread of group. --- lisp/gnus/gnus-start.el | 174 ++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index dd9c277805..edf7296bee 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el @@ -1485,6 +1485,93 @@ gnus-activate-group ;; Return the new active info. active))))) +(defun gnus-update-unread-group (info active) + (let* ((range (gnus-info-read info)) + (num 0)) + + ;; These checks are present in gnus-activate-group but skipped + ;; due to setting dont-check in the preceding call. + + ;; If a cache is present, we may have to alter the active info. + (when (and gnus-use-cache info) + (inline (gnus-cache-possibly-alter-active + (gnus-info-group info) active))) + + ;; If the agent is enabled, we may have to alter the active info. + (when (and gnus-agent info) + (gnus-agent-possibly-alter-active (gnus-info-group info) active info)) + + ;; Modify the list of read articles according to what articles + ;; are available; then tally the unread articles and add the + ;; number to the group hash table entry. + (cond + ((zerop (cdr active)) + (setq num 0)) + ((not range) + (setq num (- (1+ (cdr active)) (car active)))) + ((not (listp (cdr range))) + ;; Fix a single (num . num) range according to the + ;; active hash table. + ;; Fix by Carsten Bormann . + (and (< (cdr range) (car active)) (setcdr range (1- (car active)))) + (and (> (cdr range) (cdr active)) (setcdr range (cdr active))) + ;; Compute number of unread articles. + (setq num (max 0 (- (cdr active) (- (1+ (cdr range)) (car range)))))) + (t + ;; The read list is a list of ranges. Fix them according to + ;; the active hash table. + ;; First peel off any elements that are below the lower + ;; active limit. + (while (and (cdr range) + (>= (car active) + (or (and (atom (cadr range)) (cadr range)) + (caadr range)))) + (if (numberp (car range)) + (setcar range + (cons (car range) + (or (and (numberp (cadr range)) + (cadr range)) + (cdadr range)))) + (setcdr (car range) + (or (and (numberp (nth 1 range)) (nth 1 range)) + (cdadr range)))) + (setcdr range (cddr range))) + ;; Adjust the first element to be the same as the lower limit. + (when (and (not (atom (car range))) + (< (cdar range) (car active))) + (setcdr (car range) (1- (car active)))) + ;; Then we want to peel off any elements that are higher + ;; than the upper active limit. + (let ((srange range)) + ;; Go past all valid elements. + (while (and (cdr srange) + (<= (or (and (atom (cadr srange)) + (cadr srange)) + (caadr srange)) + (cdr active))) + (setq srange (cdr srange))) + (when (cdr srange) + ;; Nuke all remaining invalid elements. + (setcdr srange nil)) + + ;; Adjust the final element. + (when (and (not (atom (car srange))) + (> (cdar srange) (cdr active))) + (setcdr (car srange) (cdr active)))) + ;; Compute the number of unread articles. + (while range + (setq num (+ num (- (1+ (or (and (atom (car range)) (car range)) + (cdar range))) + (or (and (atom (car range)) (car range)) + (caar range))))) + (setq range (cdr range))) + (setq num (max 0 (- (cdr active) num))))) + ;; Set the number of unread articles. + (when (and info + (gnus-group-entry (gnus-info-group info))) + (setcar (gnus-group-entry (gnus-info-group info)) num)) + num)) + (defun gnus-get-unread-articles-in-group (info active &optional update) (when (and info active) ;; Allow the backend to update the info in the group. @@ -1493,92 +1580,7 @@ gnus-get-unread-articles-in-group info (inline (gnus-find-method-for-group (gnus-info-group info))))) (gnus-activate-group (gnus-info-group info) nil t)) - - (let* ((range (gnus-info-read info)) - (num 0)) - - ;; These checks are present in gnus-activate-group but skipped - ;; due to setting dont-check in the preceding call. - - ;; If a cache is present, we may have to alter the active info. - (when (and gnus-use-cache info) - (inline (gnus-cache-possibly-alter-active - (gnus-info-group info) active))) - - ;; If the agent is enabled, we may have to alter the active info. - (when (and gnus-agent info) - (gnus-agent-possibly-alter-active (gnus-info-group info) active info)) - - ;; Modify the list of read articles according to what articles - ;; are available; then tally the unread articles and add the - ;; number to the group hash table entry. - (cond - ((zerop (cdr active)) - (setq num 0)) - ((not range) - (setq num (- (1+ (cdr active)) (car active)))) - ((not (listp (cdr range))) - ;; Fix a single (num . num) range according to the - ;; active hash table. - ;; Fix by Carsten Bormann . - (and (< (cdr range) (car active)) (setcdr range (1- (car active)))) - (and (> (cdr range) (cdr active)) (setcdr range (cdr active))) - ;; Compute number of unread articles. - (setq num (max 0 (- (cdr active) (- (1+ (cdr range)) (car range)))))) - (t - ;; The read list is a list of ranges. Fix them according to - ;; the active hash table. - ;; First peel off any elements that are below the lower - ;; active limit. - (while (and (cdr range) - (>= (car active) - (or (and (atom (cadr range)) (cadr range)) - (caadr range)))) - (if (numberp (car range)) - (setcar range - (cons (car range) - (or (and (numberp (cadr range)) - (cadr range)) - (cdadr range)))) - (setcdr (car range) - (or (and (numberp (nth 1 range)) (nth 1 range)) - (cdadr range)))) - (setcdr range (cddr range))) - ;; Adjust the first element to be the same as the lower limit. - (when (and (not (atom (car range))) - (< (cdar range) (car active))) - (setcdr (car range) (1- (car active)))) - ;; Then we want to peel off any elements that are higher - ;; than the upper active limit. - (let ((srange range)) - ;; Go past all valid elements. - (while (and (cdr srange) - (<= (or (and (atom (cadr srange)) - (cadr srange)) - (caadr srange)) - (cdr active))) - (setq srange (cdr srange))) - (when (cdr srange) - ;; Nuke all remaining invalid elements. - (setcdr srange nil)) - - ;; Adjust the final element. - (when (and (not (atom (car srange))) - (> (cdar srange) (cdr active))) - (setcdr (car srange) (cdr active)))) - ;; Compute the number of unread articles. - (while range - (setq num (+ num (- (1+ (or (and (atom (car range)) (car range)) - (cdar range))) - (or (and (atom (car range)) (car range)) - (caar range))))) - (setq range (cdr range))) - (setq num (max 0 (- (cdr active) num))))) - ;; Set the number of unread articles. - (when (and info - (gnus-group-entry (gnus-info-group info))) - (setcar (gnus-group-entry (gnus-info-group info)) num)) - num))) + (gnus-update-unread-group info active))) ;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb' ;; and compute how many unread articles there are in each group. -- 2.35.1 --=-=-= Content-Type: text/plain In GNU Emacs 29.0.50 (build 1, x86_64-unknown-openbsd7.0, X toolkit, cairo version 1.17.4, Xaw scroll bars) of 2022-02-08 built on elite.giraud Repository revision: 798555baaa3f4afca663a6ac29bc42bf313144bc Repository branch: mgi-gnus2 Windowing system distributor 'The X.Org Foundation', version 11.0.12101001 System Description: OpenBSD elite.giraud 7.0 GENERIC.MP#314 amd64 Configured using: 'configure --prefix=/home/manuel/emacs --bindir=/home/manuel/bin --with-x-toolkit=athena --without-sound --without-compress-install CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib' Configured features: CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBXML2 M17N_FLT MODULES NOTIFY KQUEUE PDUMPER PNG RSVG SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XPM LUCID ZLIB Important settings: value of $LC_ALL: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Magit Minor modes in effect: global-git-commit-mode: t magit-auto-revert-mode: t icomplete-mode: t display-time-mode: t shell-dirtrack-mode: t repeat-mode: t global-eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t buffer-read-only: t line-number-mode: t indent-tabs-mode: t transient-mark-mode: t Load-path shadows: /home/manuel/.el/google-maps.el/google-maps hides /home/manuel/.el/google-maps /home/manuel/.emacs.d/elpa/transient-20220130.1941/transient hides /home/manuel/emacs/share/emacs/29.0.50/lisp/transient ~/emacs-repo/lisp/gnus/gnus-uu hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-uu ~/emacs-repo/lisp/gnus/gnus-fun hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-fun ~/emacs-repo/lisp/gnus/spam hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/spam ~/emacs-repo/lisp/gnus/spam-wash hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/spam-wash ~/emacs-repo/lisp/gnus/spam-stat hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/spam-stat ~/emacs-repo/lisp/gnus/spam-report hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/spam-report ~/emacs-repo/lisp/gnus/smime hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/smime ~/emacs-repo/lisp/gnus/smiley hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/smiley ~/emacs-repo/lisp/gnus/score-mode hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/score-mode ~/emacs-repo/lisp/gnus/nnweb hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnweb ~/emacs-repo/lisp/gnus/gnus-rmail hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-rmail ~/emacs-repo/lisp/gnus/nnvirtual hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnvirtual ~/emacs-repo/lisp/gnus/nntp hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nntp ~/emacs-repo/lisp/gnus/nnspool hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnspool ~/emacs-repo/lisp/gnus/nnselect hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnselect ~/emacs-repo/lisp/gnus/nnrss hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnrss ~/emacs-repo/lisp/gnus/nnregistry hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnregistry ~/emacs-repo/lisp/gnus/nnoo hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnoo ~/emacs-repo/lisp/gnus/nnnil hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnnil ~/emacs-repo/lisp/gnus/nnml hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnml ~/emacs-repo/lisp/gnus/nnmh hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnmh ~/emacs-repo/lisp/gnus/nnmbox hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnmbox ~/emacs-repo/lisp/gnus/nnmairix hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnmairix ~/emacs-repo/lisp/gnus/gnus-delay hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-delay ~/emacs-repo/lisp/gnus/nnmaildir hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnmaildir ~/emacs-repo/lisp/gnus/nndoc hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nndoc ~/emacs-repo/lisp/gnus/mml1991 hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mml1991 ~/emacs-repo/lisp/gnus/mml-smime hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mml-smime ~/emacs-repo/lisp/gnus/gnus-win hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-win ~/emacs-repo/lisp/gnus/gnus-topic hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-topic ~/emacs-repo/lisp/gnus/nngateway hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nngateway ~/emacs-repo/lisp/gnus/nndraft hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nndraft ~/emacs-repo/lisp/gnus/nndir hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nndir ~/emacs-repo/lisp/gnus/nndiary hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nndiary ~/emacs-repo/lisp/gnus/mm-util hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-util ~/emacs-repo/lisp/gnus/mm-extern hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-extern ~/emacs-repo/lisp/gnus/mm-partial hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-partial ~/emacs-repo/lisp/gnus/mm-encode hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-encode ~/emacs-repo/lisp/gnus/mm-bodies hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-bodies ~/emacs-repo/lisp/gnus/gnus-vm hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-vm ~/emacs-repo/lisp/gnus/gnus-undo hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-undo ~/emacs-repo/lisp/gnus/gnus-spec hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-spec ~/emacs-repo/lisp/gnus/gnus-salt hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-salt ~/emacs-repo/lisp/gnus/gnus-rfc1843 hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-rfc1843 ~/emacs-repo/lisp/gnus/gnus-range hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-range ~/emacs-repo/lisp/gnus/gnus-picon hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-picon ~/emacs-repo/lisp/gnus/gnus-notifications hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-notifications ~/emacs-repo/lisp/gnus/gnus-group hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-group ~/emacs-repo/lisp/gnus/deuglify hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/deuglify ~/emacs-repo/lisp/gnus/canlock hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/canlock ~/emacs-repo/lisp/gnus/gnus-util hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-util ~/emacs-repo/lisp/gnus/gnus-mlspl hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-mlspl ~/emacs-repo/lisp/gnus/gnus-ml hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-ml ~/emacs-repo/lisp/gnus/gnus-mh hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-mh ~/emacs-repo/lisp/gnus/gnus-logic hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-logic ~/emacs-repo/lisp/gnus/gnus-html hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-html ~/emacs-repo/lisp/gnus/gnus-dup hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-dup ~/emacs-repo/lisp/gnus/gnus-eform hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-eform ~/emacs-repo/lisp/gnus/gnus-diary hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-diary ~/emacs-repo/lisp/gnus/gnus-demon hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-demon ~/emacs-repo/lisp/gnus/gnus-cus hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-cus ~/emacs-repo/lisp/gnus/gnus-cite hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-cite ~/emacs-repo/lisp/gnus/gnus-bcklg hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-bcklg ~/emacs-repo/lisp/gnus/gnus-score hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-score ~/emacs-repo/lisp/gnus/gnus-msg hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-msg ~/emacs-repo/lisp/gnus/gnus hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus ~/emacs-repo/lisp/gnus/gnus-dired hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-dired ~/emacs-repo/lisp/gnus/gnus-bookmark hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-bookmark ~/emacs-repo/lisp/gnus/gnus-agent hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-agent ~/emacs-repo/lisp/gnus/mml hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mml ~/emacs-repo/lisp/gnus/nneething hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nneething ~/emacs-repo/lisp/gnus/mml-sec hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mml-sec ~/emacs-repo/lisp/gnus/mm-url hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-url ~/emacs-repo/lisp/gnus/mail-source hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mail-source ~/emacs-repo/lisp/gnus/gnus-sieve hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-sieve ~/emacs-repo/lisp/gnus/nnfolder hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnfolder ~/emacs-repo/lisp/gnus/mm-decode hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-decode ~/emacs-repo/lisp/gnus/gnus-srvr hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-srvr ~/emacs-repo/lisp/gnus/gnus-start hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-start ~/emacs-repo/lisp/gnus/gnus-draft hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-draft ~/emacs-repo/lisp/gnus/gnus-cloud hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-cloud ~/emacs-repo/lisp/gnus/gnus-cache hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-cache ~/emacs-repo/lisp/gnus/nnbabyl hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnbabyl ~/emacs-repo/lisp/gnus/gnus-registry hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-registry ~/emacs-repo/lisp/gnus/mm-view hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-view ~/emacs-repo/lisp/gnus/message hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/message ~/emacs-repo/lisp/gnus/nnmail hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnmail ~/emacs-repo/lisp/gnus/nnimap hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnimap ~/emacs-repo/lisp/gnus/nnheader hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnheader ~/emacs-repo/lisp/gnus/nnagent hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/nnagent ~/emacs-repo/lisp/gnus/gnus-search hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-search ~/emacs-repo/lisp/gnus/gnus-art hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-art ~/emacs-repo/lisp/gnus/gnus-dbus hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-dbus ~/emacs-repo/lisp/gnus/gnus-sum hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-sum ~/emacs-repo/lisp/gnus/gnus-async hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-async ~/emacs-repo/lisp/gnus/mml2015 hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mml2015 ~/emacs-repo/lisp/gnus/mm-uu hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-uu ~/emacs-repo/lisp/gnus/mm-archive hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/mm-archive ~/emacs-repo/lisp/gnus/legacy-gnus-agent hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/legacy-gnus-agent ~/emacs-repo/lisp/gnus/gnus-icalendar hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-icalendar ~/emacs-repo/lisp/gnus/gssapi hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gssapi ~/emacs-repo/lisp/gnus/gnus-int hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-int ~/emacs-repo/lisp/gnus/gnus-kill hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-kill ~/emacs-repo/lisp/gnus/gnus-gravatar hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gnus-gravatar ~/emacs-repo/lisp/gnus/gmm-utils hides /home/manuel/emacs/share/emacs/29.0.50/lisp/gnus/gmm-utils Features: (goto-addr view cal-china lunar solar cal-dst cal-bahai cal-islam cal-hebrew holidays hol-loaddefs cal-iso org-element avl-tree ol-eww eww xdg url-queue ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect gnus-search eieio-opt speedbar ezimage dframe ol-docview ol-bibtex ol-bbdb ol-w3m ol-doi org-link-doi org-agenda org-refile shadow shortdoc emacsbug whitespace magit-patch gnus-dired cl-print dabbrev rmail magit-extras face-remap magit-submodule magit-obsolete magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode diff git-commit log-edit pcvs-util add-log magit-core magit-autorevert autorevert filenotify magit-margin magit-transient magit-process with-editor magit-mode transient magit-git magit-section magit-utils dash pulse help-fns radix-tree misearch multi-isearch vc-git diff-mode bug-reference executable mailalias bbdb-message vc-dispatcher vc-svn sort gnus-cite mail-extr textsec uni-scripts idna-mapping ucs-normalize uni-confusable textsec-check gnus-async gnus-bcklg gnus-ml gnus-topic mm-archive url-http url-gw url-auth qp utf-7 imap rfc2104 nnrss mm-url nndoc nndraft nnmh gnutls network-stream nsm nnfolder bbdb-gnus nnml gnus-agent gnus-srvr gnus-score score-mode nnvirtual gnus-msg nntp gnus-cache w3m w3m-hist w3m-fb bookmark-w3m w3m-ems w3m-favicon w3m-image tab-line w3m-proc w3m-util cl-extra help-mode paredit edmacro icomplete time battery cus-load exwm-randr xcb-randr exwm-config exwm exwm-input xcb-keysyms exwm-manage exwm-floating xcb-cursor xcb-render exwm-layout exwm-workspace exwm-core xcb-ewmh xcb-icccm xcb xcb-xkb xcb-xproto xcb-types xcb-debug kmacro server modus-operandi-theme modus-themes pcase google-maps google-maps-static google-maps-geocode google-maps-base osm-mode url-cache mingus libmpdee gnuplot info-look transmission color calc-bin calc-ext calc calc-loaddefs rect calc-macs w3m-load mu4e mu4e-org mu4e-main mu4e-view mu4e-view-gnus gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum gnus-group gnus-undo gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7 netrc nnoo gnus-spec gnus-int gnus-range gnus-win gnus nnheader range wid-edit mu4e-view-common mu4e-headers mu4e-compose mu4e-context mu4e-draft mu4e-actions ido rfc2368 smtpmail sendmail mu4e-mark mu4e-proc mu4e-utils doc-view jka-compr image-mode exif mu4e-lists mu4e-message shr pixel-fill kinsoku svg dom flow-fill mule-util hl-line mu4e-vars message yank-media rmc puny rfc822 mml mml-sec epa derived epg rfc6068 epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mail-utils gmm-utils mailheader mu4e-meta supercite regi bbdb-anniv diary-lib diary-loaddefs bbdb-mua bbdb-com crm mailabbrev bbdb bbdb-site timezone org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-footnote org-src ob-comint org-pcomplete org-list org-faces org-entities org-version ob-emacs-lisp ob-core ob-eval org-table oc-basic bibtex ol rx org-keys oc org-compat org-macs org-loaddefs find-func cal-menu calendar cal-loaddefs visual-basic-mode web-mode disp-table erlang-start smart-tabs-mode skeleton cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs movitz-slime cl slime-asdf grep slime-tramp tramp tramp-loaddefs trampver tramp-integration files-x tramp-compat shell pcomplete parse-time iso8601 time-date ls-lisp format-spec slime-fancy slime-indentation slime-cl-indent cl-indent slime-trace-dialog slime-fontifying-fu slime-package-fu slime-references slime-compiler-notes-tree advice slime-scratch slime-presentations bridge slime-macrostep macrostep slime-mdot-fu slime-enclosing-context slime-fuzzy slime-fancy-trace slime-fancy-inspector slime-c-p-c slime-editing-commands slime-autodoc slime-repl slime-parse slime compile text-property-search etags fileloop generator xref project arc-mode archive-mode noutline outline pp comint ansi-color ring hyperspec thingatpt slime-autoloads dired-aux dired-x dired dired-loaddefs notifications dbus xml repeat easy-mmode tex-site info package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs password-cache json map url-vars seq gv subr-x byte-opt bytecomp byte-compile cconv cl-loaddefs cl-lib iso-transl tooltip eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind kqueue lcms2 dynamic-setting system-font-setting font-render-setting cairo x-toolkit x multi-tty make-network-process emacs) Memory information: ((conses 16 868893 102442) (symbols 48 59739 8) (strings 32 276306 16458) (string-bytes 1 8495369) (vectors 16 147772) (vector-slots 8 2714405 148428) (floats 8 1138 546) (intervals 56 12268 4311) (buffers 992 47)) -- Manuel Giraud --=-=-=--