summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lisp/gnus/auth-source.el34
-rw-r--r--lisp/gnus/earcon.el6
-rw-r--r--lisp/gnus/flow-fill.el3
-rw-r--r--lisp/gnus/gnus-agent.el24
-rw-r--r--lisp/gnus/gnus-async.el6
-rw-r--r--lisp/gnus/gnus-bcklg.el18
-rw-r--r--lisp/gnus/gnus-cache.el9
-rw-r--r--lisp/gnus/gnus-demon.el8
-rw-r--r--lisp/gnus/gnus-int.el31
-rw-r--r--lisp/gnus/gnus-kill.el12
-rw-r--r--lisp/gnus/gnus-logic.el3
-rw-r--r--lisp/gnus/gnus-range.el30
-rw-r--r--lisp/gnus/gnus-registry.el6
-rw-r--r--lisp/gnus/gnus-score.el30
-rw-r--r--lisp/gnus/gnus-start.el93
-rw-r--r--lisp/gnus/gnus-sum.el27
-rw-r--r--lisp/gnus/gnus-topic.el6
-rw-r--r--lisp/gnus/gnus-util.el9
-rw-r--r--lisp/gnus/gnus-uu.el66
-rw-r--r--lisp/gnus/gnus.el2
-rw-r--r--lisp/gnus/mm-decode.el6
-rw-r--r--lisp/gnus/mm-partial.el6
-rw-r--r--lisp/gnus/nnagent.el3
-rw-r--r--lisp/gnus/nnbabyl.el35
-rw-r--r--lisp/gnus/nndiary.el38
-rw-r--r--lisp/gnus/nndoc.el21
-rw-r--r--lisp/gnus/nndraft.el9
-rw-r--r--lisp/gnus/nneething.el12
-rw-r--r--lisp/gnus/nnfolder.el39
-rw-r--r--lisp/gnus/nnheader.el3
-rw-r--r--lisp/gnus/nnimap.el2651
-rw-r--r--lisp/gnus/nnir.el3
-rw-r--r--lisp/gnus/nnmail.el53
-rw-r--r--lisp/gnus/nnmaildir.el18
-rw-r--r--lisp/gnus/nnmairix.el46
-rw-r--r--lisp/gnus/nnmbox.el27
-rw-r--r--lisp/gnus/nnml.el42
-rw-r--r--lisp/gnus/nnnil.el3
-rw-r--r--lisp/gnus/nnspool.el15
-rw-r--r--lisp/gnus/nntp.el3
-rw-r--r--lisp/gnus/nnvirtual.el12
-rw-r--r--lisp/gnus/nnweb.el21
-rw-r--r--lisp/gnus/pop3.el21
-rw-r--r--lisp/gnus/smime.el3
-rw-r--r--lisp/gnus/spam-report.el6
-rw-r--r--lisp/gnus/spam.el29
-rw-r--r--lisp/gnus/starttls.el3
-rw-r--r--lisp/gnus/utf7.el1
-rw-r--r--lisp/net/netrc.el1
49 files changed, 1289 insertions, 2264 deletions
diff --git a/lisp/gnus/auth-source.el b/lisp/gnus/auth-source.el
index 5b44c0b993..a0be0ca8ba 100644
--- a/lisp/gnus/auth-source.el
+++ b/lisp/gnus/auth-source.el
@@ -107,7 +107,8 @@ Only relevant if `auth-source-debug' is not nil."
:version "23.2" ;; No Gnus
:type `boolean)
-(defcustom auth-sources '((:source "~/.authinfo.gpg"))
+(defcustom auth-sources '((:source "~/.authinfo.gpg")
+ (:source "~/.authinfo"))
"List of authentication sources.
The default will get login and password information from a .gpg
@@ -311,20 +312,23 @@ Return structure as specified by MODE."
(setq result
(mapcar
(lambda (m)
- (if (equal "password" m)
- (let ((passwd (read-passwd "Password: ")))
- (cond
- ;; Secret Service API.
- ((consp source)
- (apply
- 'secrets-create-item
- (auth-get-source entry) name passwd spec))
- (t)) ;; netrc not implemented yes.
- passwd)
- (or
- ;; the originally requested :user
- user
- "unknown-user")))
+ (cond
+ ((equal "password" m)
+ (let ((passwd (read-passwd
+ (format "Password for %s on %s: " prot host))))
+ (cond
+ ;; Secret Service API.
+ ((consp source)
+ (apply
+ 'secrets-create-item
+ (auth-get-source entry) name passwd spec))
+ (t)) ;; netrc not implemented yes.
+ passwd))
+ ((equal "login" m)
+ (or user
+ (read-string (format "User name for %s on %s: " prot host))))
+ (t
+ "unknownuser")))
(if (consp mode) mode (list mode))))
(if (consp mode) result (car result))))
diff --git a/lisp/gnus/earcon.el b/lisp/gnus/earcon.el
index 2578abc073..2086f86c41 100644
--- a/lisp/gnus/earcon.el
+++ b/lisp/gnus/earcon.el
@@ -151,8 +151,7 @@ If N is negative, move backward instead."
(defun earcon-button-push (marker)
;; Push button starting at MARKER.
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(goto-char marker)
(let* ((entry (earcon-button-entry))
(inhibit-point-motion-hooks t)
@@ -214,8 +213,7 @@ If N is negative, move backward instead."
(defun gnus-earcon-display ()
"Play sounds in message buffers."
(interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(goto-char (point-min))
;; Skip headers
(unless (search-forward "\n\n" nil t)
diff --git a/lisp/gnus/flow-fill.el b/lisp/gnus/flow-fill.el
index c4c64db7ed..2420577ea4 100644
--- a/lisp/gnus/flow-fill.el
+++ b/lisp/gnus/flow-fill.el
@@ -97,8 +97,7 @@ RFC 2646 suggests 66 characters for readability."
;;;###autoload
(defun fill-flowed (&optional buffer delete-space)
- (save-excursion
- (set-buffer (or (current-buffer) buffer))
+ (with-current-buffer (or (current-buffer) buffer)
(goto-char (point-min))
;; Remove space stuffing.
(while (re-search-forward "^\\( \\|>+ $\\)" nil t)
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index bbfdc66af9..6dcc77cdfb 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -305,8 +305,7 @@ buffer. Automatically blocks multiple updates due to recursion."
`(prog1 (let ((gnus-agent-inhibit-update-total-fetched-for t)) ,@body)
(when (and gnus-agent-need-update-total-fetched-for
(not gnus-agent-inhibit-update-total-fetched-for))
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(setq gnus-agent-need-update-total-fetched-for nil)
(gnus-group-update-group ,group t)))))
@@ -474,8 +473,7 @@ manipulated as follows:
(defun gnus-agent-stop-fetch ()
"Save all data structures and clean up."
(setq gnus-agent-spam-hashtb nil)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(widen)))
(defmacro gnus-agent-with-fetch (&rest forms)
@@ -1608,8 +1606,7 @@ downloaded into the agent."
nntp-server-buffer (point-min) (point-max))
(setq pos (nreverse pos)))))
;; Then save these articles into the Agent.
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(while pos
(narrow-to-region (cdar pos) (or (cdadr pos) (point-max)))
(goto-char (point-min))
@@ -1693,8 +1690,7 @@ downloaded into the agent."
(setq date (or date t))
(let (gnus-agent-article-alist group alist beg end)
- (save-excursion
- (set-buffer gnus-agent-overview-buffer)
+ (with-current-buffer gnus-agent-overview-buffer
(when (nnheader-find-nov-line article)
(forward-word 1)
(setq beg (point))
@@ -1705,9 +1701,8 @@ downloaded into the agent."
(push (setq alist (list group (gnus-agent-load-alist (caar crosses))))
gnus-agent-group-alist))
(setcdr alist (cons (cons (cdar crosses) date) (cdr alist)))
- (save-excursion
- (set-buffer (gnus-get-buffer-create (format " *Gnus agent overview %s*"
- group)))
+ (with-current-buffer (gnus-get-buffer-create
+ (format " *Gnus agent overview %s*"group))
(when (= (point-max) (point-min))
(push (cons group (current-buffer)) gnus-agent-buffer-alist)
(ignore-errors
@@ -1939,9 +1934,7 @@ article numbers will be returned."
10 "gnus-agent-fetch-headers: undownloaded articles are '%s'"
(gnus-compress-sequence articles t))
- (save-excursion
- (set-buffer nntp-server-buffer)
-
+ (with-current-buffer nntp-server-buffer
(if articles
(progn
(gnus-message 7 "Fetching headers for %s..."
@@ -2767,8 +2760,7 @@ The following commands are available:
(defun gnus-category-setup-buffer ()
(unless (get-buffer gnus-category-buffer)
- (save-excursion
- (set-buffer (gnus-get-buffer-create gnus-category-buffer))
+ (with-current-buffer (gnus-get-buffer-create gnus-category-buffer)
(gnus-category-mode))))
(defun gnus-category-prepare ()
diff --git a/lisp/gnus/gnus-async.el b/lisp/gnus/gnus-async.el
index 979e67120d..a2ab54bea8 100644
--- a/lisp/gnus/gnus-async.el
+++ b/lisp/gnus/gnus-async.el
@@ -145,8 +145,7 @@ that was fetched."
(when (and (gnus-buffer-live-p summary)
gnus-asynchronous
(gnus-group-asynchronous-p group))
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(let ((next (caadr (gnus-data-find-list article))))
(when next
(if (not (fboundp 'run-with-idle-timer))
@@ -205,8 +204,7 @@ that was fetched."
(when (and do-fetch article)
;; We want to fetch some more articles.
- (save-excursion
- (set-buffer summary)
+ (with-current-buffer summary
(let (mark)
(gnus-async-set-buffer)
(goto-char (point-max))
diff --git a/lisp/gnus/gnus-bcklg.el b/lisp/gnus/gnus-bcklg.el
index b385185851..6823332880 100644
--- a/lisp/gnus/gnus-bcklg.el
+++ b/lisp/gnus/gnus-bcklg.el
@@ -40,8 +40,7 @@
(defun gnus-backlog-buffer ()
"Return the backlog buffer."
(or (get-buffer gnus-backlog-buffer)
- (save-excursion
- (set-buffer (gnus-get-buffer-create gnus-backlog-buffer))
+ (with-current-buffer (gnus-get-buffer-create gnus-backlog-buffer)
(buffer-disable-undo)
(setq buffer-read-only t)
(get-buffer gnus-backlog-buffer))))
@@ -76,8 +75,7 @@
(gnus-backlog-remove-oldest-article))
(push ident gnus-backlog-articles)
;; Insert the new article.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
+ (with-current-buffer (gnus-backlog-buffer)
(let (buffer-read-only)
(goto-char (point-max))
(unless (bolp)
@@ -90,8 +88,7 @@
(gnus-error 3 "Article %d is blank" number))))))))
(defun gnus-backlog-remove-oldest-article ()
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
+ (with-current-buffer (gnus-backlog-buffer)
(goto-char (point-min))
(if (zerop (buffer-size))
() ; The buffer is empty.
@@ -114,8 +111,7 @@
beg end)
(when (memq ident gnus-backlog-articles)
;; It was in the backlog.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
+ (with-current-buffer (gnus-backlog-buffer)
(let (buffer-read-only)
(when (setq beg (text-property-any
(point-min) (point-max) 'gnus-backlog
@@ -138,8 +134,7 @@
beg end)
(when (memq ident gnus-backlog-articles)
;; It was in the backlog.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
+ (with-current-buffer (gnus-backlog-buffer)
(if (not (setq beg (text-property-any
(point-min) (point-max) 'gnus-backlog
ident)))
@@ -150,8 +145,7 @@
(setq end
(next-single-property-change
(1+ beg) 'gnus-backlog (current-buffer) (point-max)))))
- (save-excursion
- (and buffer (set-buffer buffer))
+ (with-current-buffer (or (current-buffer) buffer)
(let ((buffer-read-only nil))
(erase-buffer)
(insert-buffer-substring gnus-backlog-buffer beg end)))
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index e3f33be881..4b2d670570 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -180,8 +180,7 @@ it's not cached."
;; Save the article in the cache.
(if (file-exists-p file)
t ; The article already is saved.
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(require 'gnus-art)
(let ((gnus-use-cache nil)
(gnus-article-decode-hook nil))
@@ -554,8 +553,7 @@ system for example was used.")
(let ((cache-buf (gnus-get-buffer-create " *gnus-cache*"))
beg end)
(gnus-cache-save-buffers)
- (save-excursion
- (set-buffer cache-buf)
+ (with-current-buffer cache-buf
(erase-buffer)
(let ((coding-system-for-read gnus-cache-overview-coding-system)
(file-name-coding-system nnmail-pathname-coding-system))
@@ -844,8 +842,7 @@ supported."
,@body)
(when (and gnus-cache-need-update-total-fetched-for
(not gnus-cache-inhibit-update-total-fetched-for))
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(setq gnus-cache-need-update-total-fetched-for nil)
(gnus-group-update-group ,group t)))))
diff --git a/lisp/gnus/gnus-demon.el b/lisp/gnus/gnus-demon.el
index caf9f8784b..67c1c8ba3b 100644
--- a/lisp/gnus/gnus-demon.el
+++ b/lisp/gnus/gnus-demon.el
@@ -291,11 +291,9 @@ minutes, the connection is closed."
(let ((win (current-window-configuration)))
(unwind-protect
(save-window-excursion
- (save-excursion
- (when (gnus-alive-p)
- (save-excursion
- (set-buffer gnus-group-buffer)
- (gnus-group-get-new-news)))))
+ (when (gnus-alive-p)
+ (with-current-buffer gnus-group-buffer
+ (gnus-group-get-new-news))))
(set-window-configuration win))))
(defun gnus-demon-add-scan-timestamps ()
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index d805f3104d..389b1a22a8 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -179,10 +179,7 @@ If it is down, start it up (again)."
(format " on %s" (nth 1 method)))))
(gnus-run-hooks 'gnus-open-server-hook)
(prog1
- (condition-case ()
- (setq result (gnus-open-server method))
- (quit (message "Quit gnus-check-server")
- nil))
+ (setq result (gnus-open-server method))
(unless silent
(gnus-message 5 "Opening %s server%s...%s" (car method)
(if (equal (nth 1 method) "") ""
@@ -225,6 +222,10 @@ If it is down, start it up (again)."
;;; Interface functions to the backends.
;;;
+(defun gnus-method-denied-p (method)
+ (eq (nth 1 (assoc method gnus-opened-servers))
+ 'denied))
+
(defun gnus-open-server (gnus-command-method)
"Open a connection to GNUS-COMMAND-METHOD."
(when (stringp gnus-command-method)
@@ -319,6 +320,22 @@ If it is down, start it up (again)."
(funcall (gnus-get-function gnus-command-method 'request-list)
(nth 1 gnus-command-method)))
+(defun gnus-finish-retrieve-group-infos (gnus-command-method infos data)
+ "Read and update infos from GNUS-COMMAND-METHOD."
+ (when (stringp gnus-command-method)
+ (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
+ (funcall (gnus-get-function gnus-command-method 'finish-retrieve-group-infos)
+ (nth 1 gnus-command-method)
+ infos data))
+
+(defun gnus-retrieve-group-data-early (gnus-command-method infos)
+ "Start early async retrival of data from GNUS-COMMAND-METHOD."
+ (when (stringp gnus-command-method)
+ (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
+ (funcall (gnus-get-function gnus-command-method 'retrieve-group-data-early)
+ (nth 1 gnus-command-method)
+ infos))
+
(defun gnus-request-list-newsgroups (gnus-command-method)
"Request the newsgroups file from GNUS-COMMAND-METHOD."
(when (stringp gnus-command-method)
@@ -490,8 +507,7 @@ If BUFFER, insert the article in that group."
(setq res (gnus-request-article article group)
clean-up t)))
(when clean-up
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
(delete-region (1- (point)) (point-max)))
@@ -523,8 +539,7 @@ If BUFFER, insert the article in that group."
(setq res (gnus-request-article article group)
clean-up t)))
(when clean-up
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
(delete-region (point-min) (1- (point))))))
diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el
index fc564490fc..5483a741f2 100644
--- a/lisp/gnus/gnus-kill.el
+++ b/lisp/gnus/gnus-kill.el
@@ -349,8 +349,7 @@ If NEWSGROUP is nil, return the global kill file instead."
(defun gnus-expunge (marks)
"Remove lines marked with MARKS."
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-summary-limit-to-marks marks 'reverse)))
(defun gnus-apply-kill-file-unless-scored ()
@@ -442,8 +441,7 @@ Returns the number of articles marked as read."
(progn
(delete-region beg (point))
(insert (or (eval form) "")))
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(ignore-errors (eval form)))))
(and (buffer-modified-p)
gnus-kill-save-kill-file
@@ -555,8 +553,7 @@ COMMAND must be a Lisp expression or a string representing a key sequence."
(and (eq 'quote (car (nth 2 object)))
(not (consp (cdadr (nth 2 object))))))
(concat "\n" (gnus-prin1-to-string object))
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*Gnus PP*"))
+ (with-current-buffer (gnus-get-buffer-create "*Gnus PP*")
(buffer-disable-undo)
(erase-buffer)
(insert (format "\n(%S %S\n '(" (nth 0 object) (nth 1 object)))
@@ -610,8 +607,7 @@ COMMAND must be a Lisp expression or a string representing a key sequence."
6 "Searching for article: %d..." (mail-header-number header))
(gnus-article-setup-buffer)
(gnus-article-prepare (mail-header-number header) t)
- (when (save-excursion
- (set-buffer gnus-article-buffer)
+ (when (with-current-buffer gnus-article-buffer
(goto-char (point-min))
(setq did-kill (re-search-forward regexp nil t)))
(cond ((stringp form) ;Keyboard macro.
diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el
index e6d28ae26a..9637ebfb38 100644
--- a/lisp/gnus/gnus-logic.el
+++ b/lisp/gnus/gnus-logic.el
@@ -179,8 +179,7 @@
(defun gnus-advanced-body (header match type)
(when (string= header "all")
(setq header "article"))
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(let* ((request-func (cond ((string= "head" header)
'gnus-request-head)
((string= "body" header)
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index 5eb8080ac0..a4262df532 100644
--- a/lisp/gnus/gnus-range.el
+++ b/lisp/gnus/gnus-range.el
@@ -59,6 +59,36 @@ If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
(setq list2 (cdr list2)))
list1))
+(defun gnus-range-nconcat (&rest ranges)
+ "Return a range comprising all the RANGES, which are pre-sorted.
+RANGES will be destructively altered."
+ (setq ranges (delete nil ranges))
+ (let* ((result (gnus-range-normalize (pop ranges)))
+ (last (last result)))
+ (dolist (range ranges)
+ (setq range (gnus-range-normalize range))
+ ;; Normalize the single-number case, so that we don't need to
+ ;; special-case that so much.
+ (when (numberp (car last))
+ (setcar last (cons (car last) (car last))))
+ (when (numberp (car range))
+ (setcar range (cons (car range) (car range))))
+ (if (= (1+ (cdar last)) (caar range))
+ (progn
+ (setcdr (car last) (cdar range))
+ (setcdr last (cdr range)))
+ (setcdr last range)
+ ;; Denormalize back, since we couldn't join the ranges up.
+ (when (= (caar range) (cdar range))
+ (setcar range (caar range)))
+ (when (= (caar last) (cdar last))
+ (setcar last (caar last))))
+ (setq last (last last)))
+ (if (and (consp (car result))
+ (= (length result) 1))
+ (car result)
+ result)))
+
(defun gnus-range-difference (range1 range2)
"Return the range of elements in RANGE1 that do not appear in RANGE2.
Both ranges must be in ascending order."
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index 8ba6c169bc..a30847b0e2 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -241,8 +241,7 @@ considered precious) will not be trimmed."
"Save the registry cache file."
(interactive)
(let ((file gnus-registry-cache-file))
- (save-excursion
- (set-buffer (gnus-get-buffer-create " *Gnus-registry-cache*"))
+ (with-current-buffer (gnus-get-buffer-create " *Gnus-registry-cache*")
(make-local-variable 'version-control)
(setq version-control gnus-backup-startup-file)
(setq buffer-file-name file)
@@ -674,8 +673,7 @@ Consults `gnus-registry-unfollowed-groups' and
word words)
(if (or (not (gnus-registry-fetch-extra id 'keywords))
force)
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(article-goto-body)
(save-window-excursion
(save-restriction
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index bd4a39eb7b..5cd60ddaab 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -708,8 +708,7 @@ file for the command instead of the current score file."
;; Change score file to the "all.SCORE" file.
(when (eq symp 'a)
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-score-load-file
;; This is a kludge; yes...
(cond
@@ -735,14 +734,12 @@ file for the command instead of the current score file."
(when (eq symp 'a)
;; We change the score file back to the previous one.
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-score-load-file current-score-file)))))
(defun gnus-score-insert-help (string alist idx)
(setq gnus-score-help-winconf (current-window-configuration))
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*Score Help*"))
+ (with-current-buffer (gnus-get-buffer-create "*Score Help*")
(buffer-disable-undo)
(delete-windows-on (current-buffer))
(erase-buffer)
@@ -1270,8 +1267,7 @@ If FORMAT, also format the current score file."
exclude-files))
gnus-scores-exclude-files))
(when local
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(while local
(and (consp (car local))
(symbolp (caar local))
@@ -1528,8 +1524,7 @@ If FORMAT, also format the current score file."
(cons (cons header (or gnus-summary-default-score 0))
gnus-scores-articles))))
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*Headers*"))
+ (with-current-buffer (gnus-get-buffer-create "*Headers*")
(buffer-disable-undo)
(when (gnus-buffer-live-p gnus-summary-buffer)
(message-clone-locals gnus-summary-buffer))
@@ -1854,8 +1849,7 @@ score in `gnus-newsgroup-scored' by SCORE."
;; Change score file to the adaptive score file. All entries that
;; this function makes will be put into this file.
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-score-load-file
(or gnus-newsgroup-adaptive-score-file
(gnus-score-file-name
@@ -1946,15 +1940,13 @@ score in `gnus-newsgroup-scored' by SCORE."
(setq rest entries)))
(setq entries rest))))
;; We change the score file back to the previous one.
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-score-load-file current-score-file))
(list (cons "references" news)))))
(defun gnus-score-add-followups (header score scores &optional thread)
"Add a score entry to the adapt file."
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(let* ((id (mail-header-id header))
(scores (car scores))
entry dont)
@@ -2282,8 +2274,7 @@ score in `gnus-newsgroup-scored' by SCORE."
"Create adaptive score rules for this newsgroup."
(when gnus-newsgroup-adaptive
;; We change the score file to the adaptive score file.
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-score-load-file
(or gnus-newsgroup-adaptive-score-file
(gnus-home-score-file gnus-newsgroup-name t)
@@ -2697,8 +2688,7 @@ GROUP using BNews sys file syntax."
(trans (cdr (assq ?: nnheader-file-name-translation-alist)))
(group-trans (nnheader-translate-file-chars group t))
ofiles not-match regexp)
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*gnus score files*"))
+ (with-current-buffer (gnus-get-buffer-create "*gnus score files*")
(buffer-disable-undo)
;; Go through all score file names and create regexp with them
;; as the source.
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 1c06a77420..e25d31ec87 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -594,8 +594,7 @@ Can be used to turn version control on or off."
(defun gnus-subscribe-hierarchically (newgroup)
"Subscribe new NEWGROUP and insert it in hierarchical newsgroup order."
;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
- (save-excursion
- (set-buffer (nnheader-find-file-noselect gnus-current-startup-file))
+ (with-current-buffer (nnheader-find-file-noselect gnus-current-startup-file)
(prog1
(let ((groupkey newgroup) before)
(while (and (not before) groupkey)
@@ -857,8 +856,7 @@ prompt the user for the name of an NNTP server to use."
;; it's not needed).
;; (set-window-point (get-buffer-window (current-buffer)) (point-max))
(bury-buffer gnus-dribble-buffer)
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(gnus-group-set-mode-line))
(set-buffer obuf))))
@@ -871,10 +869,9 @@ prompt the user for the name of an NNTP server to use."
(let ((dribble-file (gnus-dribble-file-name)))
(unless (file-exists-p (file-name-directory dribble-file))
(make-directory (file-name-directory dribble-file) t))
- (save-excursion
- (set-buffer (setq gnus-dribble-buffer
- (gnus-get-buffer-create
- (file-name-nondirectory dribble-file))))
+ (with-current-buffer (setq gnus-dribble-buffer
+ (gnus-get-buffer-create
+ (file-name-nondirectory dribble-file)))
(set (make-local-variable 'file-precious-flag) t)
(erase-buffer)
(setq buffer-file-name dribble-file)
@@ -923,8 +920,7 @@ prompt the user for the name of an NNTP server to use."
(when (file-exists-p (gnus-dribble-file-name))
(delete-file (gnus-dribble-file-name)))
(when gnus-dribble-buffer
- (save-excursion
- (set-buffer gnus-dribble-buffer)
+ (with-current-buffer gnus-dribble-buffer
(let ((auto (make-auto-save-file-name)))
(when (file-exists-p auto)
(delete-file auto))
@@ -934,14 +930,12 @@ prompt the user for the name of an NNTP server to use."
(defun gnus-dribble-save ()
(when (and gnus-dribble-buffer
(buffer-name gnus-dribble-buffer))
- (save-excursion
- (set-buffer gnus-dribble-buffer)
+ (with-current-buffer gnus-dribble-buffer
(save-buffer))))
(defun gnus-dribble-clear ()
(when (gnus-buffer-exists-p gnus-dribble-buffer)
- (save-excursion
- (set-buffer gnus-dribble-buffer)
+ (with-current-buffer gnus-dribble-buffer
(erase-buffer)
(set-buffer-modified-p nil)
(setq buffer-saved-size (buffer-size)))))
@@ -1302,8 +1296,7 @@ for new groups, and subscribe the new groups as zombies."
(when (gnus-active group)
(gnus-group-change-level
group gnus-level-default-subscribed gnus-level-killed)))
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
;; Don't error if the group already exists. This happens when a
;; first-time user types 'F'. -- didier
(gnus-group-make-help-group t))
@@ -1734,7 +1727,7 @@ If SCAN, request a scan of that group as well."
'primary)
(t
'foreign)))
- (push (setq method-group-list (list method method-type nil))
+ (push (setq method-group-list (list method method-type nil nil))
type-cache))
;; Only add groups that need updating.
(if (<= (gnus-info-level info)
@@ -1760,19 +1753,28 @@ If SCAN, request a scan of that group as well."
(< (gnus-method-rank (cadr c1) (car c1))
(gnus-method-rank (cadr c2) (car c2))))))
- (while type-cache
- (setq method (nth 0 (car type-cache))
- method-type (nth 1 (car type-cache))
- infos (nth 2 (car type-cache)))
- (pop type-cache)
-
- (when (and method
- infos)
- ;; See if any of the groups from this method require updating.
- (gnus-read-active-for-groups method infos)
- (dolist (info infos)
- (inline (gnus-get-unread-articles-in-group
- info (gnus-active (gnus-info-group info)))))))
+ ;; Start early async retrieval of data.
+ (dolist (elem type-cache)
+ (destructuring-bind (method method-type infos dummy) elem
+ (when (and method infos
+ (not (gnus-method-denied-p method))
+ (gnus-check-backend-function
+ 'retrieve-group-data-early (car method)))
+ (when (gnus-check-backend-function 'request-scan (car method))
+ (dolist (info infos)
+ (gnus-request-scan (gnus-info-group info) method)))
+ (setcar (nthcdr 3 elem)
+ (gnus-retrieve-group-data-early method infos)))))
+
+ ;; Do the rest of the retrieval.
+ (dolist (elem type-cache)
+ (destructuring-bind (method method-type infos early-data) elem
+ (when (and method infos)
+ ;; See if any of the groups from this method require updating.
+ (gnus-read-active-for-groups method infos early-data)
+ (dolist (info infos)
+ (inline (gnus-get-unread-articles-in-group
+ info (gnus-active (gnus-info-group info))))))))
(gnus-message 6 "Checking new news...done")))
(defun gnus-method-rank (type method)
@@ -1796,9 +1798,14 @@ If SCAN, request a scan of that group as well."
(t
100)))
-(defun gnus-read-active-for-groups (method infos)
+(defun gnus-read-active-for-groups (method infos early-data)
(with-current-buffer nntp-server-buffer
(cond
+ ((and
+ (gnus-check-backend-function 'finish-retrieve-group-infos (car method))
+ (or (not (gnus-agent-method-p method))
+ (gnus-online method)))
+ (gnus-finish-retrieve-group-infos method infos early-data))
((gnus-check-backend-function 'retrieve-groups (car method))
(when (gnus-check-backend-function 'request-scan (car method))
(dolist (info infos)
@@ -1867,8 +1874,7 @@ If SCAN, request a scan of that group as well."
(defun gnus-parse-active ()
"Parse active info in the nntp server buffer."
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
;; Parse the result we got from `gnus-request-group'.
(when (looking-at "[0-9]+ [0-9]+ \\([0-9]+\\) [0-9]+")
@@ -2022,8 +2028,7 @@ If SCAN, request a scan of that group as well."
(list "archive")))))
method)
(setq gnus-have-read-active-file nil)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(while (setq method (pop methods))
;; Only do each method once, in case the methods appear more
;; than once in this list.
@@ -2089,8 +2094,7 @@ If SCAN, request a scan of that group as well."
(defun gnus-read-active-file-2 (groups method)
"Read an active file for GROUPS in METHOD using `gnus-retrieve-groups'."
(when groups
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(gnus-check-server method)
(let ((list-type (gnus-retrieve-groups groups method)))
(cond ((not list-type)
@@ -2771,8 +2775,7 @@ If FORCE is non-nil, the .newsrc file is read."
(not force)
(or (not gnus-dribble-buffer)
(not (buffer-name gnus-dribble-buffer))
- (zerop (save-excursion
- (set-buffer gnus-dribble-buffer)
+ (zerop (with-current-buffer gnus-dribble-buffer
(buffer-size)))))
(gnus-message 4 "(No changes need to be saved)")
(gnus-run-hooks 'gnus-save-newsrc-hook)
@@ -2906,8 +2909,7 @@ If FORCE is non-nil, the .newsrc file is read."
(defun gnus-gnus-to-newsrc-format ()
;; Generate and save the .newsrc file.
- (save-excursion
- (set-buffer (create-file-buffer gnus-current-startup-file))
+ (with-current-buffer (create-file-buffer gnus-current-startup-file)
(let ((newsrc (cdr gnus-newsrc-alist))
(standard-output (current-buffer))
info ranges range method)
@@ -2980,8 +2982,7 @@ If FORCE is non-nil, the .newsrc file is read."
(gnus-run-hooks 'gnus-slave-mode-hook))
(defun gnus-slave-save-newsrc ()
- (save-excursion
- (set-buffer gnus-dribble-buffer)
+ (with-current-buffer gnus-dribble-buffer
(let ((slave-name
(mm-make-temp-file (concat gnus-current-startup-file "-slave-")))
(modes (ignore-errors
@@ -3005,8 +3006,7 @@ If FORCE is non-nil, the .newsrc file is read."
(if (not slave-files)
() ; There are no slave files to read.
(gnus-message 7 "Reading slave newsrcs...")
- (save-excursion
- (set-buffer (gnus-get-buffer-create " *gnus slave*"))
+ (with-current-buffer (gnus-get-buffer-create " *gnus slave*")
(setq slave-files
(sort (mapcar (lambda (file)
(list (nth 5 (file-attributes file)) file))
@@ -3126,8 +3126,7 @@ If FORCE is non-nil, the .newsrc file is read."
(defun gnus-group-get-description (group)
"Get the description of a group by sending XGTITLE to the server."
(when (gnus-request-group-description group)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(when (looking-at "[^ \t]+[ \t]+\\(.*\\)")
(match-string 1)))))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index df20456b27..3c3a059053 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -5504,11 +5504,11 @@ If SELECT-ARTICLES, only select those articles from GROUP."
(mm-decode-coding-string (gnus-status-message group) charset))))
(unless (gnus-request-group group t)
- (when (equal major-mode 'gnus-summary-mode)
- (gnus-kill-buffer (current-buffer)))
- (error "Couldn't request group %s: %s"
- (mm-decode-coding-string group charset)
- (mm-decode-coding-string (gnus-status-message group) charset)))
+ (when (equal major-mode 'gnus-summary-mode)
+ (gnus-kill-buffer (current-buffer)))
+ (error "Couldn't request group %s: %s"
+ (mm-decode-coding-string group charset)
+ (mm-decode-coding-string (gnus-status-message group) charset)))
(when gnus-agent
(gnus-agent-possibly-alter-active group (gnus-active group) info)
@@ -7394,7 +7394,7 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
"Go to the first subject satisfying any non-nil constraint.
If UNREAD is non-nil, the article should be unread.
If UNDOWNLOADED is non-nil, the article should be undownloaded.
-If UNSEEN is non-nil, the article should be unseen.
+If UNSEEN is non-nil, the article should be unseen as well as unread.
Returns the article selected or nil if there are no matching articles."
(interactive "P")
(cond
@@ -7417,7 +7417,8 @@ Returns the article selected or nil if there are no matching articles."
(and undownloaded
(memq num gnus-newsgroup-undownloaded))
(and unseen
- (memq num gnus-newsgroup-unseen)))))))
+ (memq num gnus-newsgroup-unseen)
+ (memq num gnus-newsgroup-unreads)))))))
(setq data (cdr data)))
(prog1
(if data
@@ -7908,8 +7909,8 @@ Return nil if there are no unseen articles."
(gnus-summary-position-point)))
(defun gnus-summary-first-unseen-or-unread-subject ()
- "Place the point on the subject line of the first unseen article or,
-if all article have been seen, on the subject line of the first unread
+ "Place the point on the subject line of the first unseen and unread article.
+If all article have been seen, on the subject line of the first unread
article."
(interactive)
(prog1
@@ -9690,7 +9691,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
to-newsgroup (list 'quote select-method)
(not articles) t) ; Accept form
(not articles) ; Only save nov last time
- move-is-internal))) ; is this move internal?
+ (and move-is-internal
+ (gnus-group-real-name to-newsgroup))))) ; is this move internal?
;; Copy the article.
((eq action 'copy)
(with-current-buffer copy-buf
@@ -9821,8 +9823,9 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
(gnus-add-marked-articles
to-group 'expire (list to-article) info))
- (gnus-request-set-mark
- to-group (list (list (list to-article) 'add to-marks))))
+ (when to-marks
+ (gnus-request-set-mark
+ to-group (list (list (list to-article) 'add to-marks)))))
(gnus-dribble-enter
(concat "(gnus-group-set-info '"
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index 89e61bcb59..7c710357b9 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -148,8 +148,7 @@ See Info node `(gnus)Formatting Variables'."
(defun gnus-group-parent-topic (group)
"Return the topic GROUP is member of by looking at the group buffer."
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(if (gnus-group-goto-group group)
(gnus-current-topic)
(gnus-group-topic group))))
@@ -912,8 +911,7 @@ articles in the topic and its subtopics."
(defun gnus-topic-change-level (group level oldlevel &optional previous)
"Run when changing levels to enter/remove groups from topics."
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(let ((buffer-read-only nil))
(unless gnus-topic-inhibit-change-level
(gnus-group-goto-group (or (car (nth 2 previous)) group))
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 7cdb70a358..334f0eea7d 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1115,8 +1115,7 @@ FILENAME exists and is Babyl format."
(gnus-yes-or-no-p
(concat "\"" filename "\" does not exist, create it? ")))
(let ((file-buffer (create-file-buffer filename)))
- (save-excursion
- (set-buffer file-buffer)
+ (with-current-buffer file-buffer
(if (fboundp 'rmail-insert-rmail-file-header)
(rmail-insert-rmail-file-header))
(let ((require-final-newline nil)
@@ -1194,8 +1193,7 @@ FILENAME exists and is Babyl format."
(gnus-y-or-n-p
(concat "\"" filename "\" does not exist, create it? ")))
(let ((file-buffer (create-file-buffer filename)))
- (save-excursion
- (set-buffer file-buffer)
+ (with-current-buffer file-buffer
(let ((require-final-newline nil)
(coding-system-for-write mm-text-coding-system))
(gnus-write-buffer filename)))
@@ -1274,8 +1272,7 @@ This function saves the current buffer."
"Say whether Gnus is running or not."
(and (boundp 'gnus-group-buffer)
(get-buffer gnus-group-buffer)
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(eq major-mode 'gnus-group-mode))))
(defun gnus-remove-if (predicate list)
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index 35120eae76..614a52c176 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -827,8 +827,7 @@ When called interactively, prompt for REGEXP."
(defun gnus-uu-save-article (buffer in-state)
(cond
(gnus-uu-save-separate-articles
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(let ((coding-system-for-write mm-text-coding-system))
(gnus-write-buffer
(concat gnus-uu-saved-article-name gnus-current-article)))
@@ -838,8 +837,7 @@ When called interactively, prompt for REGEXP."
((eq in-state 'last) (list 'end))
(t (list 'middle)))))
((not gnus-uu-save-in-digest)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(write-region (point-min) (point-max) gnus-uu-saved-article-name t)
(cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
@@ -857,11 +855,9 @@ When called interactively, prompt for REGEXP."
(eq in-state 'first-and-last))
(progn
(setq state (list 'begin))
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*gnus-uu-body*"))
+ (with-current-buffer (gnus-get-buffer-create "*gnus-uu-body*")
(erase-buffer))
- (save-excursion
- (set-buffer (gnus-get-buffer-create "*gnus-uu-pre*"))
+ (with-current-buffer (gnus-get-buffer-create "*gnus-uu-pre*")
(erase-buffer)
(insert (format
"Date: %s\nFrom: %s\nSubject: %s Digest\n\n"
@@ -873,8 +869,7 @@ When called interactively, prompt for REGEXP."
(insert "Topics:\n")))
(when (not (eq in-state 'end))
(setq state (list 'middle))))
- (save-excursion
- (set-buffer "*gnus-uu-body*")
+ (with-current-buffer "*gnus-uu-body*"
(goto-char (setq beg (point-max)))
(save-excursion
(save-restriction
@@ -940,8 +935,7 @@ When called interactively, prompt for REGEXP."
(when (re-search-forward "^Subject: \\(.*\\)$" nil t)
(setq subj (buffer-substring (match-beginning 1) (match-end 1))))
(when subj
- (save-excursion
- (set-buffer "*gnus-uu-pre*")
+ (with-current-buffer "*gnus-uu-pre*"
(insert (format " %s\n" subj)))))
(when (or (eq in-state 'last)
(eq in-state 'first-and-last))
@@ -951,8 +945,7 @@ When called interactively, prompt for REGEXP."
(insert-buffer-substring "*gnus-uu-pre*")
(goto-char (point-max))
(insert-buffer-substring "*gnus-uu-body*"))
- (save-excursion
- (set-buffer "*gnus-uu-pre*")
+ (with-current-buffer "*gnus-uu-pre*"
(insert (format "\n\n%s\n\n" (make-string 70 ?-)))
(if gnus-uu-digest-buffer
(with-current-buffer gnus-uu-digest-buffer
@@ -960,8 +953,7 @@ When called interactively, prompt for REGEXP."
(insert-buffer-substring "*gnus-uu-pre*"))
(let ((coding-system-for-write mm-text-coding-system))
(gnus-write-buffer gnus-uu-saved-article-name))))
- (save-excursion
- (set-buffer "*gnus-uu-body*")
+ (with-current-buffer "*gnus-uu-body*"
(goto-char (point-max))
(insert
(concat (setq end-string (format "End of %s Digest" name))
@@ -993,8 +985,7 @@ When called interactively, prompt for REGEXP."
(defun gnus-uu-binhex-article (buffer in-state)
(let (state start-char)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(widen)
(goto-char (point-min))
(when (not (re-search-forward gnus-uu-binhex-begin-line nil t))
@@ -1030,8 +1021,7 @@ When called interactively, prompt for REGEXP."
;; yEnc
(defun gnus-uu-yenc-article (buffer in-state)
- (save-excursion
- (set-buffer gnus-original-article-buffer)
+ (with-current-buffer gnus-original-article-buffer
(widen)
(let ((file-name (yenc-extract-filename))
state start-char)
@@ -1065,8 +1055,7 @@ When called interactively, prompt for REGEXP."
(defun gnus-uu-decode-postscript-article (process-buffer in-state)
(let ((state (list 'ok))
start-char end-char file-name)
- (save-excursion
- (set-buffer process-buffer)
+ (with-current-buffer process-buffer
(goto-char (point-min))
(if (not (re-search-forward gnus-uu-postscript-begin-string nil t))
(setq state (list 'wrong-type))
@@ -1128,8 +1117,7 @@ When called interactively, prompt for REGEXP."
;; replaces the last thing that looks like "2/3" with "[0-9]+/3"
;; or, if it can't find something like that, tries "2 of 3", then
;; finally just replaces the next to last number with "[0-9]+".
- (save-excursion
- (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
+ (with-current-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name)
(buffer-disable-undo)
(erase-buffer)
(insert (regexp-quote string))
@@ -1228,8 +1216,7 @@ When called interactively, prompt for REGEXP."
;; decoded in. Returns the list of expanded strings.
(let ((out-list string-list)
string)
- (save-excursion
- (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
+ (with-current-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name)
(buffer-disable-undo)
(while string-list
(erase-buffer)
@@ -1332,11 +1319,9 @@ When called interactively, prompt for REGEXP."
(gnus-summary-display-article article)
;; Push the article to the processing function.
- (save-excursion
- (set-buffer gnus-original-article-buffer)
+ (with-current-buffer gnus-original-article-buffer
(let ((buffer-read-only nil))
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(setq process-state
(funcall process-function
gnus-original-article-buffer state)))))
@@ -1477,8 +1462,7 @@ When called interactively, prompt for REGEXP."
(defun gnus-uu-uustrip-article (process-buffer in-state)
;; Uudecodes a file asynchronously.
- (save-excursion
- (set-buffer process-buffer)
+ (with-current-buffer process-buffer
(let ((state (list 'wrong-type))
process-connection-type case-fold-search buffer-read-only
files start-char)
@@ -1600,8 +1584,7 @@ Gnus might fail to display all of it.")
(defun gnus-uu-unshar-article (process-buffer in-state)
(let ((state (list 'ok))
start-char)
- (save-excursion
- (set-buffer process-buffer)
+ (with-current-buffer process-buffer
(goto-char (point-min))
(if (not (re-search-forward gnus-uu-shar-begin-string nil t))
(setq state (list 'wrong-type))
@@ -1688,8 +1671,7 @@ Gnus might fail to display all of it.")
(setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path)))
- (save-excursion
- (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
+ (with-current-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name)
(erase-buffer))
(gnus-message 5 "Unpacking: %s..." (gnus-uu-command action file-path))
@@ -2039,9 +2021,8 @@ If no file has been included, the user will be asked for a file."
(setq file-name file-path))
(unwind-protect
- (if (save-excursion
- (set-buffer (setq uubuf
- (gnus-get-buffer-create uuencode-buffer-name)))
+ (if (with-current-buffer
+ (setq uubuf (gnus-get-buffer-create uuencode-buffer-name))
(erase-buffer)
(funcall gnus-uu-post-encode-method file-path file-name))
(insert-buffer-substring uubuf)
@@ -2073,8 +2054,8 @@ If no file has been included, the user will be asked for a file."
(setq beg-binary (point))
(setq end-binary (point-max))
- (save-excursion
- (set-buffer (setq uubuf (gnus-get-buffer-create encoded-buffer-name)))
+ (with-current-buffer
+ (setq uubuf (gnus-get-buffer-create encoded-buffer-name))
(erase-buffer)
(insert-buffer-substring post-buf beg-binary end-binary)
(goto-char (point-min))
@@ -2129,8 +2110,7 @@ If no file has been included, the user will be asked for a file."
(insert (format " (%d/%d)" i parts)))
(goto-char (point-max))
- (save-excursion
- (set-buffer uubuf)
+ (with-current-buffer uubuf
(goto-char beg)
(if (= i parts)
(goto-char (point-max))
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 797f8a44bd..2173d713d1 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -2743,6 +2743,8 @@ a string, be sure to use a valid format, see RFC 2616."
'((seen range)
(killed range)
(bookmark tuple)
+ (uid tuple)
+ (active tuple)
(score tuple)))
;; Propagate flags to server, with the following exceptions:
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index c4cbce4aba..948fc08135 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -114,6 +114,7 @@
"Render of HTML contents.
It is one of defined renderer types, or a rendering function.
The defined renderer types are:
+`gnus-article-html' : use Gnus renderer based on w3m;
`w3m' : use emacs-w3m;
`w3m-standalone': use w3m;
`links': use links;
@@ -122,8 +123,9 @@ The defined renderer types are:
`html2text' : use html2text;
nil : use external viewer (default web browser)."
:version "24.1"
- :type '(choice (const w3)
- (const w3m :tag "emacs-w3m")
+ :type '(choice (const gnus-article-html)
+ (const w3)
+ (const w3m :tag "emacs-w3m")
(const w3m-standalone :tag "standalone w3m" )
(const links)
(const lynx)
diff --git a/lisp/gnus/mm-partial.el b/lisp/gnus/mm-partial.el
index 3fec4a2a97..6509b648fe 100644
--- a/lisp/gnus/mm-partial.el
+++ b/lisp/gnus/mm-partial.el
@@ -70,8 +70,7 @@ If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing."
(sort (cons handle
(mm-partial-find-parts
id
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-summary-article-number))))
#'(lambda (a b)
(let ((anumber (string-to-number
@@ -83,8 +82,7 @@ If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing."
(< anumber bnumber)))))
(setq gnus-article-mime-handles
(mm-merge-handles gnus-article-mime-handles phandles))
- (save-excursion
- (set-buffer (generate-new-buffer " *mm*"))
+ (with-current-buffer (generate-new-buffer " *mm*")
(while (setq phandle (pop phandles))
(setq nn (string-to-number
(cdr (assq 'number
diff --git a/lisp/gnus/nnagent.el b/lisp/gnus/nnagent.el
index 263d721dad..ccd4e890da 100644
--- a/lisp/gnus/nnagent.el
+++ b/lisp/gnus/nnagent.el
@@ -252,6 +252,9 @@
(nnoo-parent-function 'nnagent 'nnml-request-regenerate
(list (nnagent-server server))))
+(deffoo nnagent-retrieve-group-data-early (server infos)
+ nil)
+
;; Use nnml functions for just about everything.
(nnoo-import nnagent
(nnml))
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index 58e848bcb5..512de38559 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -75,8 +75,7 @@
(nnoo-define-basics nnbabyl)
(deffoo nnbabyl-retrieve-headers (articles &optional group server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let ((number (length articles))
(count 0)
@@ -136,8 +135,7 @@
;; Restore buffer mode.
(when (and (nnbabyl-server-opened)
nnbabyl-previous-buffer-mode)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(narrow-to-region
(caar nnbabyl-previous-buffer-mode)
(cdar nnbabyl-previous-buffer-mode))
@@ -155,8 +153,7 @@
(deffoo nnbabyl-request-article (article &optional newsgroup server buffer)
(nnbabyl-possibly-change-newsgroup newsgroup server)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(goto-char (point-min))
(when (search-forward (nnbabyl-article-string article) nil t)
(let (start stop summary-line)
@@ -216,8 +213,7 @@
(nnmail-get-new-mail
'nnbabyl
(lambda ()
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(save-buffer)))
(file-name-directory nnbabyl-mbox-file)
group
@@ -264,8 +260,7 @@
rest)
(nnmail-activate 'nnbabyl)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(set-text-properties (point-min) (point-max) nil)
(while (and articles is-old)
(goto-char (point-min))
@@ -308,8 +303,7 @@
result)
(and
(nnbabyl-request-article article group server)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(insert-buffer-substring nntp-server-buffer)
(goto-char (point-min))
(while (re-search-forward
@@ -373,8 +367,7 @@
(deffoo nnbabyl-request-replace-article (article group buffer)
(nnbabyl-possibly-change-newsgroup group)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(goto-char (point-min))
(if (not (search-forward (nnbabyl-article-string article) nil t))
nil
@@ -388,8 +381,7 @@
;; Delete all articles in GROUP.
(if (not force)
() ; Don't delete the articles.
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(goto-char (point-min))
;; Delete all articles in this group.
(let ((ident (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":"))
@@ -409,8 +401,7 @@
(deffoo nnbabyl-request-rename-group (group new-name &optional server)
(nnbabyl-possibly-change-newsgroup group server)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(goto-char (point-min))
(let ((ident (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":"))
(new-ident (concat "\nX-Gnus-Newsgroup: " new-name ":"))
@@ -558,9 +549,8 @@
(defun nnbabyl-create-mbox ()
(unless (file-exists-p nnbabyl-mbox-file)
;; Create a new, empty RMAIL mbox file.
- (save-excursion
- (set-buffer (setq nnbabyl-mbox-buffer
- (create-file-buffer nnbabyl-mbox-file)))
+ (with-current-buffer (setq nnbabyl-mbox-buffer
+ (create-file-buffer nnbabyl-mbox-file))
(setq buffer-file-name nnbabyl-mbox-file)
(insert "BABYL OPTIONS:\n\n\^_")
(nnmail-write-region
@@ -572,8 +562,7 @@
(unless (and nnbabyl-mbox-buffer
(buffer-name nnbabyl-mbox-buffer)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
+ (with-current-buffer nnbabyl-mbox-buffer
(= (buffer-size) (nnheader-file-size nnbabyl-mbox-file))))
;; This buffer has changed since we read it last. Possibly.
(save-excursion
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 3189d33dd5..790e390424 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -380,8 +380,7 @@ all. This may very well take some time.")
(deffoo nndiary-retrieve-headers (sequence &optional group server fetch-old)
(when (nndiary-possibly-change-directory group server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let* ((file nil)
(number (length sequence))
@@ -615,8 +614,7 @@ all. This may very well take some time.")
(let (nndiary-current-directory
nndiary-current-group
nndiary-article-file-alist)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(insert-buffer-substring nntp-server-buffer)
(setq result (eval accept-form))
(kill-buffer (current-buffer))
@@ -672,8 +670,7 @@ all. This may very well take some time.")
(deffoo nndiary-request-replace-article (article group buffer)
(nndiary-possibly-change-directory group)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(nndiary-possibly-create-directory group)
(let ((chars (nnmail-insert-lines))
(art (concat (int-to-string article) "\t"))
@@ -688,8 +685,7 @@ all. This may very well take some time.")
t)
(setq headers (nndiary-parse-head chars article))
;; Replace the NOV line in the NOV file.
- (save-excursion
- (set-buffer (nndiary-open-nov group))
+ (with-current-buffer (nndiary-open-nov group)
(goto-char (point-min))
(if (or (looking-at art)
(search-forward (concat "\n" art) nil t))
@@ -842,8 +838,7 @@ all. This may very well take some time.")
;; Find an article number in the current group given the Message-ID.
(defun nndiary-find-group-number (id)
- (save-excursion
- (set-buffer (get-buffer-create " *nndiary id*"))
+ (with-current-buffer (get-buffer-create " *nndiary id*")
(let ((alist nndiary-group-alist)
number)
;; We want to look through all .overview files, but we want to
@@ -888,8 +883,7 @@ all. This may very well take some time.")
(let ((nov (expand-file-name nndiary-nov-file-name
nndiary-current-directory)))
(when (file-exists-p nov)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(nnheader-insert-file-contents nov)
(if (and fetch-old
@@ -989,8 +983,7 @@ all. This may very well take some time.")
(defun nndiary-add-nov (group article headers)
"Add a nov line for the GROUP base."
- (save-excursion
- (set-buffer (nndiary-open-nov group))
+ (with-current-buffer (nndiary-open-nov group)
(goto-char (point-max))
(mail-header-set-number headers article)
(nnheader-insert-nov headers)))
@@ -1015,8 +1008,7 @@ all. This may very well take some time.")
(or (cdr (assoc group nndiary-nov-buffer-alist))
(let ((buffer (get-buffer-create (format " *nndiary overview %s*"
group))))
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(set (make-local-variable 'nndiary-nov-buffer-file-name)
(expand-file-name
nndiary-nov-file-name
@@ -1103,9 +1095,8 @@ all. This may very well take some time.")
(nov (concat dir nndiary-nov-file-name))
(nov-buffer (get-buffer-create " *nov*"))
chars file headers)
- (save-excursion
- ;; Init the nov buffer.
- (set-buffer nov-buffer)
+ ;; Init the nov buffer.
+ (with-current-buffer nov-buffer
(buffer-disable-undo)
(erase-buffer)
(set-buffer nntp-server-buffer)
@@ -1125,20 +1116,17 @@ all. This may very well take some time.")
(unless (zerop (buffer-size))
(goto-char (point-min))
(setq headers (nndiary-parse-head chars (caar files)))
- (save-excursion
- (set-buffer nov-buffer)
+ (with-current-buffer nov-buffer
(goto-char (point-max))
(nnheader-insert-nov headers)))
(widen))
(setq files (cdr files)))
- (save-excursion
- (set-buffer nov-buffer)
+ (with-current-buffer nov-buffer
(nnmail-write-region 1 (point-max) nov nil 'nomesg)
(kill-buffer (current-buffer))))))
(defun nndiary-nov-delete-article (group article)
- (save-excursion
- (set-buffer (nndiary-open-nov group))
+ (with-current-buffer (nndiary-open-nov group)
(when (nnheader-find-nov-line article)
(delete-region (point) (progn (forward-line 1) (point)))
(when (bobp)
diff --git a/lisp/gnus/nndoc.el b/lisp/gnus/nndoc.el
index ddeac7f952..2e49205700 100644
--- a/lisp/gnus/nndoc.el
+++ b/lisp/gnus/nndoc.el
@@ -215,8 +215,7 @@ from the document.")
(deffoo nndoc-retrieve-headers (articles &optional newsgroup server fetch-old)
(when (nndoc-possibly-change-buffer newsgroup server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let (article entry)
(if (stringp (car articles))
@@ -333,8 +332,7 @@ from the document.")
(concat " *nndoc " group "*"))))
nndoc-group-alist)
(setq nndoc-dissection-alist nil)
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(erase-buffer)
(if (and (stringp nndoc-address)
(string-match nndoc-binary-file-names nndoc-address))
@@ -347,8 +345,7 @@ from the document.")
;; Initialize the nndoc structures according to this new document.
(when (and nndoc-current-buffer
(not nndoc-dissection-alist))
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(nndoc-set-delims)
(if (eq nndoc-article-type 'mime-parts)
(nndoc-dissect-mime-parts)
@@ -588,8 +585,7 @@ from the document.")
(defun nndoc-generate-clari-briefs-head (article)
(let ((entry (cdr (assq article nndoc-dissection-alist)))
subject from)
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(save-restriction
(narrow-to-region (car entry) (nth 3 entry))
(goto-char (point-min))
@@ -677,8 +673,7 @@ from the document.")
(let ((entry (cdr (assq article nndoc-dissection-alist)))
(from "<no address given>")
subject date)
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(save-restriction
(narrow-to-region (car entry) (nth 1 entry))
(goto-char (point-min))
@@ -829,8 +824,7 @@ from the document.")
(first t)
art-begin head-begin head-end body-begin body-end)
(setq nndoc-dissection-alist nil)
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(goto-char (point-min))
;; Remove blank lines.
(while (eq (following-char) ?\n)
@@ -902,8 +896,7 @@ When a MIME entity contains sub-entities, dissection produces one article for
the header of this entity, and one article per sub-entity."
(setq nndoc-dissection-alist nil
nndoc-mime-split-ordinal 0)
- (save-excursion
- (set-buffer nndoc-current-buffer)
+ (with-current-buffer nndoc-current-buffer
(nndoc-dissect-mime-parts-sub (point-min) (point-max) nil nil nil)))
(defun nndoc-dissect-mime-parts-sub (head-begin body-end article-insert
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index dd2b8a6b48..e92e00efe6 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -77,8 +77,7 @@ are generated if and only if they are also in `message-draft-headers'.")
(deffoo nndraft-retrieve-headers (articles &optional group server fetch-old)
(nndraft-possibly-change-group group)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let* (article)
;; We don't support fetching by Message-ID.
@@ -119,8 +118,7 @@ are generated if and only if they are also in `message-draft-headers'.")
mm-text-coding-system)
mm-auto-save-coding-system)))
(nnmail-find-file newest)))
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
;; If there's a mail header separator in this file,
;; we remove it.
@@ -209,8 +207,7 @@ are generated if and only if they are also in `message-draft-headers'.")
result)
(and
(nndraft-request-article article group server)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(erase-buffer)
(insert-buffer-substring nntp-server-buffer)
(setq result (eval accept-form))
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index 2f05c7e790..bd5bfba046 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -81,8 +81,7 @@ included.")
(deffoo nneething-retrieve-headers (articles &optional group server fetch-old)
(nneething-possibly-change-directory group)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let* ((number (length articles))
(count 0)
@@ -323,8 +322,7 @@ included.")
(if (equal '(0 0) (nth 5 atts)) ""
(concat "Date: " (current-time-string (nth 5 atts)) "\n"))
(or (when buffer
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(when (re-search-forward "<[a-zA-Z0-9_]@[-a-zA-Z0-9_]>" 1000 t)
(concat "From: " (match-string 0) "\n"))))
(nneething-from-line (nth 2 atts) file))
@@ -332,8 +330,7 @@ included.")
(concat "Chars: " (int-to-string (nth 7 atts)) "\n")
"")
(if buffer
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(concat "Lines: " (int-to-string
(count-lines (point-min) (point-max)))
"\n"))
@@ -382,8 +379,7 @@ included.")
(defun nneething-get-head (file)
"Either find the head in FILE or make a head for FILE."
- (save-excursion
- (set-buffer (get-buffer-create nneething-work-buffer))
+ (with-current-buffer (get-buffer-create nneething-work-buffer)
(setq case-fold-search nil)
(buffer-disable-undo)
(erase-buffer)
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 6413e98cc1..5cebcb0e5f 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -157,8 +157,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(nnoo-define-basics nnfolder)
(deffoo nnfolder-retrieve-headers (articles &optional group server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let (article start stop num)
(nnfolder-possibly-change-group group server)
@@ -261,8 +260,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(deffoo nnfolder-request-article (article &optional group server buffer)
(nnfolder-possibly-change-group group server)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
+ (with-current-buffer nnfolder-current-buffer
(goto-char (point-min))
(when (nnfolder-goto-article article)
(let (start stop)
@@ -360,8 +358,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
nnfolder-current-group (car inf))))
(when (and nnfolder-current-buffer
(buffer-name nnfolder-current-buffer))
- (save-excursion
- (set-buffer nnfolder-current-buffer)
+ (with-current-buffer nnfolder-current-buffer
;; If the buffer was modified, write the file out now.
(nnfolder-save-buffer)
;; If we're shutting the server down, we need to kill the
@@ -447,8 +444,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
target)
(nnmail-activate 'nnfolder)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
+ (with-current-buffer nnfolder-current-buffer
;; Since messages are sorted in arrival order and expired in the
;; same order, we can stop as soon as we find a message that is
;; too old.
@@ -501,8 +497,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
result)
(and
(nnfolder-request-article article group server)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(erase-buffer)
(insert-buffer-substring nntp-server-buffer)
(goto-char (point-min))
@@ -578,8 +573,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(deffoo nnfolder-request-replace-article (article group buffer)
(nnfolder-possibly-change-group group)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(goto-char (point-min))
(if (not (looking-at "X-From-Line: "))
(insert "From nobody " (current-time-string) "\n")
@@ -596,8 +590,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(nnfolder-delete-mail)
(insert-buffer-substring buffer)
(unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(let ((headers (nnfolder-parse-head article
(point-min) (point-max))))
(with-current-buffer (nnfolder-open-nov group)
@@ -630,8 +623,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(deffoo nnfolder-request-rename-group (group new-name &optional server)
(nnfolder-possibly-change-group group server)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
+ (with-current-buffer nnfolder-current-buffer
(and (file-writable-p buffer-file-name)
(ignore-errors
(let ((new-file (nnfolder-group-pathname new-name)))
@@ -671,8 +663,7 @@ the group. Then the marks file will be regenerated properly by Gnus.")
(marker (concat "\n" nnfolder-article-marker))
(number "[0-9]+")
(activemin (cdr active)))
- (save-excursion
- (set-buffer nnfolder-current-buffer)
+ (with-current-buffer nnfolder-current-buffer
(goto-char (point-min))
(while (and (search-forward marker nil t)
(re-search-forward number nil t))
@@ -1114,8 +1105,7 @@ This command does not work if you use short group names."
(defun nnfolder-open-nov (group)
(or (cdr (assoc group nnfolder-nov-buffer-alist))
(let ((buffer (get-buffer-create (format " *nnfolder overview %s*" group))))
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(set (make-local-variable 'nnfolder-nov-buffer-file-name)
(nnfolder-group-nov-pathname group))
(erase-buffer)
@@ -1139,8 +1129,7 @@ This command does not work if you use short group names."
(setq nnfolder-nov-buffer-alist (cdr nnfolder-nov-buffer-alist)))))
(defun nnfolder-nov-delete-article (group article)
- (save-excursion
- (set-buffer (nnfolder-open-nov group))
+ (with-current-buffer (nnfolder-open-nov group)
(when (nnheader-find-nov-line article)
(delete-region (point) (progn (forward-line 1) (point))))
t))
@@ -1150,8 +1139,7 @@ This command does not work if you use short group names."
nil
(let ((nov (nnfolder-group-nov-pathname nnfolder-current-group)))
(when (file-exists-p nov)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(nnheader-insert-file-contents nov)
(if (and fetch-old
@@ -1187,8 +1175,7 @@ This command does not work if you use short group names."
(defun nnfolder-add-nov (group article headers)
"Add a nov line for the GROUP base."
- (save-excursion
- (set-buffer (nnfolder-open-nov group))
+ (with-current-buffer (nnfolder-open-nov group)
(goto-char (point-max))
(mail-header-set-number headers article)
(nnheader-insert-nov headers)))
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index 9a90a76f7a..1bfdbeab9c 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -835,8 +835,7 @@ The first string in ARGS can be a format string."
"Clear the communication buffer and insert FORMAT and ARGS into the buffer.
If FORMAT isn't a format string, it and all ARGS will be inserted
without formatting."
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(if (string-match "%" format)
(insert (apply 'format format args))
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index d412af46d0..e7bf0f376a 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1,11 +1,9 @@
-;;; nnimap.el --- imap backend for Gnus
+;;; nnimap.el --- IMAP interface for Gnus
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
-;; Author: Simon Josefsson <simon@josefsson.org>
-;; Jim Radford <radford@robby.caltech.edu>
-;; Keywords: mail
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Simon Josefsson <simon@josefsson.org>
;; This file is part of GNU Emacs.
@@ -24,1791 +22,942 @@
;;; Commentary:
-;; Todo, major things:
-;;
-;; o Fix Gnus to view correct number of unread/total articles in group buffer
-;; o Fix Gnus to handle leading '.' in group names (fixed?)
-;; o Finish disconnected mode (moving articles between mailboxes unplugged)
-;; o Sieve
-;; o MIME (partial article fetches)
-;; o Split to other backends, different split rules for different
-;; servers/inboxes
-;;
-;; Todo, minor things:
-;;
-;; o Don't require half of Gnus -- backends should be standalone
-;; o Verify that we don't use IMAP4rev1 specific things (RFC2060 App B)
-;; o Dont uid fetch 1,* in nnimap-retrive-groups (slow)
-;; o Split up big fetches (1,* header especially) in smaller chunks
-;; o What do I do with gnus-newsgroup-*?
-;; o Tell Gnus about new groups (how can we tell?)
-;; o Respooling (fix Gnus?) (unnecessary?)
-;; o Add support for the following: (if applicable)
-;; request-list-newsgroups, request-regenerate
-;; list-active-group,
-;; request-associate-buffer, request-restore-buffer,
-;; o Do The Right Thing when UIDVALIDITY changes (what's the right thing?)
-;; o Support RFC2221 (Login referrals)
-;; o IMAP2BIS compatibility? (RFC2061)
-;; o ACAP stuff (perhaps a different project, would be nice to ACAPify
-;; .newsrc.eld)
-;; o What about Gnus's article editing, can we support it? NO!
-;; o Use \Draft to support the draft group??
-;; o Duplicate suppression
-;; o Rewrite UID SEARCH UID X as UID FETCH X (UID) for those with slow servers
+;; nnimap interfaces Gnus with IMAP servers.
;;; Code:
-;; For Emacs < 22.2.
(eval-and-compile
- (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
+ (require 'nnheader))
-(require 'imap)
-(require 'nnoo)
-(require 'nnmail)
-(require 'nnheader)
-(require 'mm-util)
-(require 'gnus)
-(require 'gnus-range)
-(require 'gnus-start)
-(require 'gnus-int)
+(eval-when-compile
+ (require 'cl))
-(eval-when-compile (require 'cl))
-
-(autoload 'auth-source-user-or-password "auth-source")
+(require 'netrc)
(nnoo-declare nnimap)
-(defconst nnimap-version "nnimap 1.0")
-
-(defgroup nnimap nil
- "Reading IMAP mail with Gnus."
- :group 'gnus)
-
(defvoo nnimap-address nil
- "Address of physical IMAP server. If nil, use the virtual server's name.")
+ "The address of the IMAP server.")
(defvoo nnimap-server-port nil
- "Port number on physical IMAP server.
-If nil, defaults to 993 for TLS/SSL connections and 143 otherwise.")
-
-;; Splitting variables
-
-(defcustom nnimap-split-crosspost t
- "If non-nil, do crossposting if several split methods match the mail.
-If nil, the first match found will be used."
- :group 'nnimap
- :type 'boolean)
-
-(defcustom nnimap-split-inbox nil
- "Name of mailbox to split mail from.
-
-Mail is read from this mailbox and split according to rules in
-`nnimap-split-rule'.
-
-This can be a string or a list of strings."
- :group 'nnimap
- :type '(choice (string)
- (repeat string)))
-
-(define-widget 'nnimap-strict-function 'function
- "This widget only matches values that are functionp.
-
-Warning: This means that a value that is the symbol of a not yet
-loaded function will not match. Use with care."
- :match 'nnimap-strict-function-match)
-
-(defun nnimap-strict-function-match (widget value)
- "Ignoring WIDGET, match if VALUE is a function."
- (functionp value))
-
-(defcustom nnimap-split-rule nil
- "Mail will be split according to these rules.
-
-Mail is read from mailbox(es) specified in `nnimap-split-inbox'.
-
-If you'd like, for instance, one mail group for mail from the
-\"gnus-imap\" mailing list, one group for junk mail and leave
-everything else in the incoming mailbox, you could do something like
-this:
-
-\(setq nnimap-split-rule '((\"INBOX.gnus-imap\" \"From:.*gnus-imap\")
- (\"INBOX.junk\" \"Subject:.*buy\")))
-
-As you can see, `nnimap-split-rule' is a list of lists, where the
-first element in each \"rule\" is the name of the IMAP mailbox (or the
-symbol `junk' if you want to remove the mail), and the second is a
-regexp that nnimap will try to match on the header to find a fit.
-
-The second element can also be a function. In that case, it will be
-called narrowed to the headers with the first element of the rule as
-the argument. It should return a non-nil value if it thinks that the
-mail belongs in that group.
-
-This variable can also have a function as its value, the function will
-be called with the headers narrowed and should return a group where it
-thinks the article should be splitted to. See `nnimap-split-fancy'.
-
-To allow for different split rules on different virtual servers, and
-even different split rules in different inboxes on the same server,
-the syntax of this variable have been extended along the lines of:
-
-\(setq nnimap-split-rule
- '((\"my1server\" (\".*\" ((\"ding\" \"ding@gnus.org\")
- (\"junk\" \"From:.*Simon\")))
- (\"my2server\" (\"INBOX\" nnimap-split-fancy))
- (\"my[34]server\" (\".*\" ((\"private\" \"To:.*Simon\")
- (\"junk\" my-junk-func)))))
-
-The virtual server name is in fact a regexp, so that the same rules
-may apply to several servers. In the example, the servers
-\"my3server\" and \"my4server\" both use the same rules. Similarly,
-the inbox string is also a regexp. The actual splitting rules are as
-before, either a function, or a list with group/regexp or
-group/function elements."
- :group 'nnimap
- ;; FIXME: Doesn't allow `("my2server" ("INBOX" nnimap-split-fancy))'
- ;; per example above. -- fx
- :type '(choice :tag "Rule type"
- (repeat :menu-tag "Single-server"
- :tag "Single-server list"
- (list (string :tag "Mailbox")
- (choice :tag "Predicate"
- (regexp :tag "A regexp")
- (nnimap-strict-function :tag "A function"))))
- (choice :menu-tag "A function"
- :tag "A function"
- (function-item nnimap-split-fancy)
- (function-item nnmail-split-fancy)
- (nnimap-strict-function :tag "User-defined function"))
- (repeat :menu-tag "Multi-server (extended)"
- :tag "Multi-server list"
- (list (regexp :tag "Server regexp")
- (list (regexp :tag "Incoming Mailbox regexp")
- (repeat :tag "Rules for matching server(s) and mailbox(es)"
- (list (string :tag "Destination mailbox")
- (choice :tag "Predicate"
- (regexp :tag "A Regexp")
- (nnimap-strict-function :tag "A Function")))))))))
-
-(defcustom nnimap-split-predicate "UNSEEN UNDELETED"
- "The predicate used to find articles to split.
-If you use another IMAP client to peek on articles but always would
-like nnimap to split them once it's started, you could change this to
-\"UNDELETED\". Other available predicates are available in
-RFC2060 section 6.4.4."
- :group 'nnimap
- :type 'string)
-
-(defcustom nnimap-split-fancy nil
- "Like the variable `nnmail-split-fancy'."
- :group 'nnimap
- :type 'sexp)
+ "The IMAP port used.
+If nnimap-stream is `ssl', this will default to `imaps'. If not,
+it will default to `imap'.")
+
+(defvoo nnimap-stream 'ssl
+ "How nnimap will talk to the IMAP server.
+Values are `ssl' and `network'.")
+
+(defvoo nnimap-shell-program (if (boundp 'imap-shell-program)
+ (if (listp imap-shell-program)
+ (car imap-shell-program)
+ imap-shell-program)
+ "ssh %s imapd"))
+
+(defvoo nnimap-inbox nil
+ "The mail box where incoming mail arrives and should be split out of.")
+
+(defvoo nnimap-expunge-inbox nil
+ "If non-nil, expunge the inbox after fetching mail.
+This is always done if the server supports UID EXPUNGE, but it's
+not done by default on servers that doesn't support that command.")
+
+(defvoo nnimap-connection-alist nil)
+(defvar nnimap-process nil)
+
+(defvar nnimap-status-string "")
(defvar nnimap-split-download-body-default nil
"Internal variable with default value for `nnimap-split-download-body'.")
-(defcustom nnimap-split-download-body 'default
- "Whether to download entire articles during splitting.
-This is generally not required, and will slow things down considerably.
-You may need it if you want to use an advanced splitting function that
-analyzes the body before splitting the article.
-If this variable is nil, bodies will not be downloaded; if this
-variable is the symbol `default' the default behavior is
-used (which currently is nil, unless you use a statistical
-spam.el test); if this variable is another non-nil value bodies
-will be downloaded."
- :version "22.1"
- :group 'nnimap
- :type '(choice (const :tag "Let system decide" deault)
- boolean))
-
-;; Performance / bug workaround variables
-
-(defcustom nnimap-close-asynchronous t
- "Close mailboxes asynchronously in `nnimap-close-group'.
-This means that errors caught by nnimap when closing the mailbox will
-not prevent Gnus from updating the group status, which may be harmful.
-However, it increases speed."
- :version "22.1"
- :type 'boolean
- :group 'nnimap)
-
-(defcustom nnimap-dont-close t
- "Never close mailboxes.
-This increases the speed of closing mailboxes (quiting group) but may
-decrease the speed of selecting another mailbox later. Re-selecting
-the same mailbox will be faster though."
- :version "22.1"
- :type 'boolean
- :group 'nnimap)
-
-(defcustom nnimap-retrieve-groups-asynchronous t
- "Send asynchronous STATUS commands for each mailbox before checking mail.
-If you have mailboxes that rarely receives mail, this speeds up new
-mail checking. It works by first sending STATUS commands for each
-mailbox, and then only checking groups which has a modified UIDNEXT
-more carefully for new mail.
-
-In summary, the default is O((1-p)*k+p*n) and changing it to nil makes
-it O(n). If p is small, then the default is probably faster."
- :version "22.1"
- :type 'boolean
- :group 'nnimap)
-
-(defvoo nnimap-need-unselect-to-notice-new-mail t
- "Unselect mailboxes before looking for new mail in them.
-Some servers seem to need this under some circumstances.")
-
-(defvoo nnimap-logout-timeout nil
- "Close server immediately if it can't logout in this number of seconds.
-If it is nil, never close server until logout completes. This variable
-overrides `imap-logout-timeout' on a per-server basis.")
-
-;; Authorization / Privacy variables
-
-(defvoo nnimap-auth-method nil
- "Obsolete.")
-
-(defvoo nnimap-stream nil
- "How nnimap will connect to the server.
-
-The default, nil, will try to use the \"best\" method the server can
-handle.
-
-Change this if
-
-1) you want to connect with TLS/SSL. The TLS/SSL integration
- with IMAP is suboptimal so you'll have to tell it
- specifically.
-
-2) your server is more capable than your environment -- i.e. your
- server accept Kerberos login's but you haven't installed the
- `imtest' program or your machine isn't configured for Kerberos.
-
-Possible choices: gssapi, kerberos4, starttls, tls, ssl, network, shell.
-See also `imap-streams' and `imap-stream-alist'.")
-
-(defvoo nnimap-authenticator nil
- "How nnimap authenticate itself to the server.
-
-The default, nil, will try to use the \"best\" method the server can
-handle.
-
-There is only one reason for fiddling with this variable, and that is
-if your server is more capable than your environment -- i.e. you
-connect to a server that accept Kerberos login's but you haven't
-installed the `imtest' program or your machine isn't configured for
-Kerberos.
-
-Possible choices: gssapi, kerberos4, digest-md5, cram-md5, login, anonymous.
-See also `imap-authenticators' and `imap-authenticator-alist'")
-
-(defvoo nnimap-directory (nnheader-concat gnus-directory "overview/")
- "Directory to keep NOV cache files for nnimap groups.
-See also `nnimap-nov-file-name'.")
-
-(defvoo nnimap-nov-file-name "nnimap."
- "NOV cache base filename.
-The group name and `nnimap-nov-file-name-suffix' will be appended. A
-typical complete file name would be
-~/News/overview/nnimap.pdc.INBOX.ding.nov, or
-~/News/overview/nnimap/pdc/INBOX/ding/nov if
-`nnmail-use-long-file-names' is nil")
-
-(defvoo nnimap-nov-file-name-suffix ".novcache"
- "Suffix for NOV cache base filename.")
-
-(defvoo nnimap-nov-is-evil gnus-agent
- "If non-nil, never generate or use a local nov database for this backend.
-Using nov databases should speed up header fetching considerably.
-However, it will invoke a UID SEARCH UID command on the server, and
-some servers implement this command inefficiently by opening each and
-every message in the group, thus making it quite slow.
-Unlike other backends, you do not need to take special care if you
-flip this variable.")
-
-(defvoo nnimap-search-uids-not-since-is-evil nil
- "If non-nil, avoid \"UID SEARCH UID ... NOT SINCE\" queries when expiring.
-Instead, use \"UID SEARCH SINCE\" to prune the list of expirable
-articles within Gnus. This seems to be faster on Courier in some cases.")
-
-(defvoo nnimap-expunge-on-close 'always ; 'ask, 'never
- "Whether to expunge a group when it is closed.
-When a IMAP group with articles marked for deletion is closed, this
-variable determine if nnimap should actually remove the articles or
-not.
-
-If always, nnimap always perform a expunge when closing the group.
-If never, nnimap never expunges articles marked for deletion.
-If ask, nnimap will ask you if you wish to expunge marked articles.
-
-When setting this variable to `never', you can only expunge articles
-by using `G x' (gnus-group-nnimap-expunge) from the Group buffer.")
-
-(defvoo nnimap-list-pattern "*"
- "A string LIMIT or list of strings with mailbox wildcards used to limit available groups.
-See below for available wildcards.
-
-The LIMIT string can be a cons cell (REFERENCE . LIMIT), where
-REFERENCE will be passed as the first parameter to LIST/LSUB. The
-semantics of this are server specific, on the University of Washington
-server you can specify a directory.
-
-Example:
- '(\"INBOX\" \"mail/*\" (\"~friend/mail/\" . \"list/*\"))
-
-There are two wildcards * and %. * matches everything, % matches
-everything in the current hierarchy.")
-
-(defvoo nnimap-news-groups nil
- "IMAP support a news-like mode, also known as bulletin board mode,
-where replies is sent via IMAP instead of SMTP.
-
-This variable should contain a regexp matching groups where you wish
-replies to be stored to the mailbox directly.
-
-Example:
- '(\"^[^I][^N][^B][^O][^X].*$\")
-
-This will match all groups not beginning with \"INBOX\".
-
-Note that there is nothing technically different between mail-like and
-news-like mailboxes. If you wish to have a group with todo items or
-similar which you wouldn't want to set up a mailing list for, you can
-use this to make replies go directly to the group.")
-
-(defvoo nnimap-expunge-search-string "UID %s NOT SINCE %s"
- "IMAP search command to use for articles that are to be expired.
-The first %s is replaced by a UID set of articles to search on,
-and the second %s is replaced by a date criterium.
-
-One useful (and perhaps the only useful) value to change this to would
-be `UID %s NOT SENTSINCE %s' to make nnimap use the Date: header
-instead of the internal date of messages. See section 6.4.4 of RFC
-2060 for more information on valid strings.
-
-However, if `nnimap-search-uids-not-since-is-evil' is true, this
-variable has no effect since the search logic is reversed.")
-
-(defvoo nnimap-importantize-dormant t
- "If non-nil, mark \"dormant\" articles as \"ticked\" for other IMAP clients.
-Note that within Gnus, dormant articles will still (only) be
-marked as ticked. This is to make \"dormant\" articles stand out,
-just like \"ticked\" articles, in other IMAP clients.")
-
-(defvoo nnimap-server-address nil
- "Obsolete. Use `nnimap-address'.")
-
-(defcustom nnimap-authinfo-file "~/.authinfo"
- "Authorization information for IMAP servers. In .netrc format."
- :type
- '(choice file
- (repeat :tag "Entries"
- :menu-tag "Inline"
- (list :format "%v"
- :value ("" ("login" . "") ("password" . ""))
- (string :tag "Host")
- (checklist :inline t
- (cons :format "%v"
- (const :format "" "login")
- (string :format "Login: %v"))
- (cons :format "%v"
- (const :format "" "password")
- (string :format "Password: %v"))))))
- :group 'nnimap)
-
-(defcustom nnimap-prune-cache t
- "If non-nil, nnimap check whether articles still exist on server before using data stored in NOV cache."
- :type 'boolean
- :group 'nnimap)
-
-(defvar nnimap-request-list-method 'imap-mailbox-list
- "Method to use to request a list of all folders from the server.
-If this is 'imap-mailbox-lsub, then use a server-side subscription list to
-restrict visible folders.")
-
-(defcustom nnimap-id nil
- "Plist with client identity to send to server upon login.
-A nil value means no information is sent, symbol `no' to disable ID query
-altogether, or plist with identifier-value pairs to send to
-server. RFC 2971 describes the list as follows:
-
- Any string may be sent as a field, but the following are defined to
- describe certain values that might be sent. Implementations are free
- to send none, any, or all of these. Strings are not case-sensitive.
- Field strings MUST NOT be longer than 30 octets. Value strings MUST
- NOT be longer than 1024 octets. Implementations MUST NOT send more
- than 30 field-value pairs.
-
- name Name of the program
- version Version number of the program
- os Name of the operating system
- os-version Version of the operating system
- vendor Vendor of the client/server
- support-url URL to contact for support
- address Postal address of contact/vendor
- date Date program was released, specified as a date-time
- in IMAP4rev1
- command Command used to start the program
- arguments Arguments supplied on the command line, if any
- if any
- environment Description of environment, i.e., UNIX environment
- variables or Windows registry settings
-
- Implementations MUST NOT send the same field name more than once.
-
-An example plist would be '(\"name\" \"Gnus\" \"version\" gnus-version-number
-\"os\" system-configuration \"vendor\" \"GNU\")."
- :group 'nnimap
- :type '(choice (const :tag "No information" nil)
- (const :tag "Disable ID query" no)
- (plist :key-type string :value-type string)))
-
-(defcustom nnimap-debug nil
- "If non-nil, trace nnimap- functions into `nnimap-debug-buffer'.
-Uses `trace-function-background', so you can turn it off with,
-say, `untrace-all'.
-
-Note that username, passwords and other privacy sensitive
-information (such as e-mail) may be stored in the buffer.
-It is not written to disk, however. Do not enable this
-variable unless you are comfortable with that.
-
-This variable only takes effect when loading the `nnimap' library.
-See also `nnimap-log'."
- :group 'nnimap
- :type 'boolean)
-
-;; Internal variables:
-
-(defvar nnimap-debug-buffer "*nnimap-debug*")
-(defvar nnimap-mailbox-info (gnus-make-hashtable 997))
-(defvar nnimap-current-move-server nil)
-(defvar nnimap-current-move-group nil)
-(defvar nnimap-current-move-article nil)
-(defvar nnimap-length)
-(defvar nnimap-progress-chars '(?| ?/ ?- ?\\))
-(defvar nnimap-progress-how-often 20)
-(defvar nnimap-counter)
-(defvar nnimap-server-buffer-alist nil) ;; Map server name to buffers.
-(defvar nnimap-current-server nil) ;; Current server
-(defvar nnimap-server-buffer nil) ;; Current servers' buffer
-
-
-
-(nnoo-define-basics nnimap)
-
-;; Utility functions:
-
-(defsubst nnimap-decode-group-name (group)
- (and group
- (gnus-group-decoded-name group)))
-
-(defsubst nnimap-encode-group-name (group)
- (and group
- (mm-encode-coding-string group (gnus-group-name-charset nil group))))
-
-(defun nnimap-group-prefixed-name (group &optional server)
- (gnus-group-prefixed-name group
- (gnus-server-to-method
- (format "nnimap:%s"
- (or server nnimap-current-server)))))
-
-(defsubst nnimap-get-server-buffer (server)
- "Return buffer for SERVER, if nil use current server."
- (cadr (assoc (or server nnimap-current-server) nnimap-server-buffer-alist)))
-
-(defun nnimap-remove-server-from-buffer-alist (server list)
- "Remove SERVER from LIST."
- (let (l)
- (dolist (e list)
- (unless (equal server (car-safe e))
- (push e l)))
- l))
-
-(defun nnimap-possibly-change-server (server)
- "Return buffer for SERVER, changing the current server as a side-effect.
-If SERVER is nil, uses the current server."
- (setq nnimap-current-server (or server nnimap-current-server)
- nnimap-server-buffer (nnimap-get-server-buffer nnimap-current-server)))
-
-(defun nnimap-verify-uidvalidity (group server)
- "Verify stored uidvalidity match current one in GROUP on SERVER."
- (let* ((gnusgroup (nnimap-group-prefixed-name group server))
- (new-uidvalidity (imap-mailbox-get 'uidvalidity))
- (old-uidvalidity (gnus-group-get-parameter gnusgroup 'uidvalidity))
- (dir (file-name-as-directory (expand-file-name nnimap-directory)))
- (nameuid (nnheader-translate-file-chars
- (concat nnimap-nov-file-name
- (if (equal server "")
- "unnamed"
- server) "." group "." old-uidvalidity
- nnimap-nov-file-name-suffix) t))
- (file (if (or nnmail-use-long-file-names
- (file-exists-p (expand-file-name nameuid dir)))
- (expand-file-name nameuid dir)
- (expand-file-name
- (mm-encode-coding-string
- (nnheader-replace-chars-in-string nameuid ?. ?/)
- nnmail-pathname-coding-system)
- dir))))
- (if old-uidvalidity
- (if (not (equal old-uidvalidity new-uidvalidity))
- ;; uidvalidity clash
- (progn
- (gnus-group-set-parameter gnusgroup 'uidvalidity new-uidvalidity)
- (gnus-group-remove-parameter gnusgroup 'imap-status)
- (gnus-sethash (gnus-group-prefixed-name group server)
- nil nnimap-mailbox-info)
- (gnus-delete-file file))
- t)
- (gnus-group-add-parameter gnusgroup (cons 'uidvalidity new-uidvalidity))
- (gnus-group-remove-parameter gnusgroup 'imap-status)
- (gnus-sethash ; Maybe not necessary here.
- (gnus-group-prefixed-name group server)
- nil nnimap-mailbox-info)
- t)))
+(defstruct nnimap
+ group process commands capabilities)
-(defun nnimap-before-find-minmax-bugworkaround ()
- "Function called before iterating through mailboxes with
-`nnimap-find-minmax-uid'."
- (when nnimap-need-unselect-to-notice-new-mail
- ;; XXX this is for UoW imapd problem, it doesn't notice new mail in
- ;; currently selected mailbox without a re-select/examine.
- (or (null (imap-current-mailbox nnimap-server-buffer))
- (imap-mailbox-unselect nnimap-server-buffer))))
-
-(defun nnimap-find-minmax-uid (group &optional examine)
- "Find lowest and highest active article number in GROUP.
-If EXAMINE is non-nil the group is selected read-only."
- (with-current-buffer nnimap-server-buffer
- (let ((decoded-group (nnimap-decode-group-name group)))
- (when (or (string= decoded-group (imap-current-mailbox))
- (imap-mailbox-select decoded-group examine))
- (let (minuid maxuid)
- (when (> (imap-mailbox-get 'exists) 0)
- (imap-fetch "1:*" "UID" nil 'nouidfetch)
- (imap-message-map
- (lambda (uid Uid)
- (setq minuid (if minuid (min minuid uid) uid)
- maxuid (if maxuid (max maxuid uid) uid)))
- 'UID))
- (list (imap-mailbox-get 'exists) minuid maxuid))))))
-
-(defun nnimap-possibly-change-group (group &optional server)
- "Make GROUP the current group, and SERVER the current server."
- (when (nnimap-possibly-change-server server)
- (let ((decoded-group (nnimap-decode-group-name group)))
- (with-current-buffer nnimap-server-buffer
- (if (or (null group) (imap-current-mailbox-p decoded-group))
- imap-current-mailbox ; Note: utf-7 encoded.
- (if (imap-mailbox-select decoded-group)
- (if (or (nnimap-verify-uidvalidity
- group (or server nnimap-current-server))
- (zerop (imap-mailbox-get 'exists decoded-group))
- t ;; for OGnus to see if ignoring uidvalidity
- ;; changes has any bad effects.
- (yes-or-no-p
- (format
- "nnimap: Group %s is not uidvalid. Continue? "
- decoded-group)))
- imap-current-mailbox ; Note: utf-7 encoded.
- (imap-mailbox-unselect)
- (error "nnimap: Group %s is not uid-valid" decoded-group))
- (nnheader-report 'nnimap (imap-error-text))))))))
-
-(defun nnimap-replace-whitespace (string)
- "Return STRING with all whitespace replaced with space."
- (when string
- (while (string-match "[\r\n\t]+" string)
- (setq string (replace-match " " t t string)))
- string))
-
-;; Required backend functions
-
-(defun nnimap-retrieve-headers-progress ()
- "Hook to insert NOV line for current article into `nntp-server-buffer'."
- (and (numberp nnmail-large-newsgroup)
- (zerop (% (incf nnimap-counter) nnimap-progress-how-often))
- (> nnimap-length nnmail-large-newsgroup)
- (nnheader-message 6 "nnimap: Retrieving headers... %c"
- (nth (/ (% nnimap-counter
- (* (length nnimap-progress-chars)
- nnimap-progress-how-often))
- nnimap-progress-how-often)
- nnimap-progress-chars)))
- (with-current-buffer nntp-server-buffer
- (let (headers lines chars uid mbx)
- (with-current-buffer nnimap-server-buffer
- (setq uid imap-current-message
- mbx (nnimap-encode-group-name (imap-current-mailbox))
- headers (if (imap-capability 'IMAP4rev1)
- ;; xxx don't just use car? alist doesn't contain
- ;; anything else now, but it might...
- (nth 2 (car (imap-message-get uid 'BODYDETAIL)))
- (imap-message-get uid 'RFC822.HEADER))
- lines (imap-body-lines (imap-message-body imap-current-message))
- chars (imap-message-get imap-current-message 'RFC822.SIZE)))
- (nnheader-insert-nov
- ;; At this stage, we only have bytes, so let's use unibyte buffers
- ;; to make it more clear.
- (mm-with-unibyte-buffer
- (buffer-disable-undo)
- ;; headers can be nil if article is write-only
- (when headers (insert headers))
- (let ((head (nnheader-parse-naked-head uid)))
- (mail-header-set-number head uid)
- (mail-header-set-chars head chars)
- (mail-header-set-lines head lines)
- (mail-header-set-xref
- head (format "%s %s:%d" (system-name) mbx uid))
- head))))))
-
-(defun nnimap-retrieve-which-headers (articles fetch-old)
- "Get a range of articles to fetch based on ARTICLES and FETCH-OLD."
- (with-current-buffer nnimap-server-buffer
- (if (numberp (car-safe articles))
- (imap-search
- (concat "UID "
- (imap-range-to-message-set
- (gnus-compress-sequence
- (append (gnus-uncompress-sequence
- (and fetch-old
- (cons (if (numberp fetch-old)
- (max 1 (- (car articles) fetch-old))
- 1)
- (1- (car articles)))))
- articles)))))
- (mapcar (lambda (msgid)
- (imap-search
- (format "HEADER Message-Id \"%s\"" msgid)))
- articles))))
-
-(defun nnimap-group-overview-filename (group server)
- "Make file name for GROUP on SERVER."
- (let* ((dir (file-name-as-directory (expand-file-name nnimap-directory)))
- (uidvalidity (gnus-group-get-parameter
- (nnimap-group-prefixed-name group server)
- 'uidvalidity))
- (name (nnheader-translate-file-chars
- (concat nnimap-nov-file-name
- (if (equal server "")
- "unnamed"
- server) "." group nnimap-nov-file-name-suffix) t))
- (nameuid (nnheader-translate-file-chars
- (concat nnimap-nov-file-name
- (if (equal server "")
- "unnamed"
- server) "." group "." uidvalidity
- nnimap-nov-file-name-suffix) t))
- (oldfile (if (or nnmail-use-long-file-names
- (file-exists-p (expand-file-name name dir)))
- (expand-file-name name dir)
- (expand-file-name
- (mm-encode-coding-string
- (nnheader-replace-chars-in-string name ?. ?/)
- nnmail-pathname-coding-system)
- dir)))
- (newfile (if (or nnmail-use-long-file-names
- (file-exists-p (expand-file-name nameuid dir)))
- (expand-file-name nameuid dir)
- (expand-file-name
- (mm-encode-coding-string
- (nnheader-replace-chars-in-string nameuid ?. ?/)
- nnmail-pathname-coding-system)
- dir))))
- (when (and (file-exists-p oldfile) (not (file-exists-p newfile)))
- (message "nnimap: Upgrading novcache filename...")
- (sit-for 1)
- (gnus-make-directory (file-name-directory newfile))
- (unless (ignore-errors (rename-file oldfile newfile) t)
- (if (ignore-errors (copy-file oldfile newfile) t)
- (delete-file oldfile)
- (error "Can't rename `%s' to `%s'" oldfile newfile))))
- newfile))
-
-(defun nnimap-retrieve-headers-from-file (group server)
+(defvar nnimap-object nil)
+
+(defvar nnimap-mark-alist
+ '((read "\\Seen")
+ (tick "\\Flagged")
+ (reply "\\Answered")
+ (expire "gnus-expire")
+ (dormant "gnus-dormant")
+ (score "gnus-score")
+ (save "gnus-save")
+ (download "gnus-download")
+ (forward "gnus-forward")))
+
+(defvar nnimap-split-methods nil)
+
+(defun nnimap-buffer ()
+ (nnimap-find-process-buffer nntp-server-buffer))
+
+(defun nnimap-retrieve-headers (articles &optional group server fetch-old)
(with-current-buffer nntp-server-buffer
- (let ((nov (nnimap-group-overview-filename group server)))
- (when (file-exists-p nov)
- (mm-insert-file-contents nov)
- (set-buffer-modified-p nil)
- (let ((min (ignore-errors (goto-char (point-min))
- (read (current-buffer))))
- (max (ignore-errors (goto-char (point-max))
- (forward-line -1)
- (read (current-buffer)))))
- (if (and (numberp min) (numberp max))
- (cons min max)
- ;; junk, remove it, it's saved later
- (erase-buffer)
- nil))))))
-
-(defun nnimap-retrieve-headers-from-server (articles group server)
- (with-current-buffer nnimap-server-buffer
- (let ((imap-fetch-data-hook '(nnimap-retrieve-headers-progress))
- (nnimap-length (gnus-range-length articles))
- (nnimap-counter 0))
- (imap-fetch (imap-range-to-message-set articles)
- (concat "(UID RFC822.SIZE BODY "
- (let ((headers
- (append '(Subject From Date Message-Id
- References In-Reply-To Xref)
- (copy-sequence
- nnmail-extra-headers))))
- (if (imap-capability 'IMAP4rev1)
- (format "BODY.PEEK[HEADER.FIELDS %s])" headers)
- (format "RFC822.HEADER.LINES %s)" headers)))))
- (with-current-buffer nntp-server-buffer
- (sort-numeric-fields 1 (point-min) (point-max)))
- (and (numberp nnmail-large-newsgroup)
- (> nnimap-length nnmail-large-newsgroup)
- (nnheader-message 6 "nnimap: Retrieving headers...done")))))
-
-(defun nnimap-dont-use-nov-p (group server)
- (or gnus-nov-is-evil nnimap-nov-is-evil
- (unless (and (gnus-make-directory
- (file-name-directory
- (nnimap-group-overview-filename group server)))
- (file-writable-p
- (nnimap-group-overview-filename group server)))
- (message "nnimap: Nov cache not writable, %s"
- (nnimap-group-overview-filename group server)))))
-
-(deffoo nnimap-retrieve-headers (articles &optional group server fetch-old)
- (when (nnimap-possibly-change-group group server)
- (with-current-buffer nntp-server-buffer
- (erase-buffer)
- (if (nnimap-dont-use-nov-p group server)
- (nnimap-retrieve-headers-from-server
- (gnus-compress-sequence articles) group server)
- (let (uids cached low high)
- (when (setq uids (nnimap-retrieve-which-headers articles fetch-old)
- low (car uids)
- high (car (last uids)))
- (if (setq cached (nnimap-retrieve-headers-from-file group server))
- (progn
- ;; fetch articles with uids before cache block
- (when (< low (car cached))
- (goto-char (point-min))
- (nnimap-retrieve-headers-from-server
- (cons low (1- (car cached))) group server))
- ;; fetch articles with uids after cache block
- (when (> high (cdr cached))
- (goto-char (point-max))
- (nnimap-retrieve-headers-from-server
- (cons (1+ (cdr cached)) high) group server))
- (when nnimap-prune-cache
- ;; remove nov's for articles which has expired on server
- (goto-char (point-min))
- (dolist (uid (gnus-set-difference articles uids))
- (when (re-search-forward (format "^%d\t" uid) nil t)
- (gnus-delete-line)))))
- ;; nothing cached, fetch whole range from server
- (nnimap-retrieve-headers-from-server
- (cons low high) group server))
- (when (buffer-modified-p)
- (nnmail-write-region
- (point-min) (point-max)
- (nnimap-group-overview-filename group server) nil 'nomesg))
- (nnheader-nov-delete-outside-range low high))))
- 'nov)))
-
-(declare-function netrc-parse "netrc" (file))
-(declare-function netrc-machine-user-or-password "netrc"
- (mode authinfo-file-or-list machines ports defaults))
-
-(defun nnimap-open-connection (server)
- ;; Note: `nnimap-open-server' that calls this function binds
- ;; `imap-logout-timeout' to `nnimap-logout-timeout'.
- (if (not (imap-open nnimap-address nnimap-server-port nnimap-stream
- nnimap-authenticator nnimap-server-buffer))
- (nnheader-report 'nnimap "Can't open connection to server %s" server)
- (require 'netrc)
- (unless (or (imap-capability 'IMAP4 nnimap-server-buffer)
- (imap-capability 'IMAP4rev1 nnimap-server-buffer))
- (imap-close nnimap-server-buffer)
- (nnheader-report 'nnimap "Server %s is not IMAP4 compliant" server))
- (let* ((list (progn (gnus-message 7 "Parsing authinfo file `%s'."
- nnimap-authinfo-file)
- (netrc-parse nnimap-authinfo-file)))
- (port (if nnimap-server-port
- (int-to-string nnimap-server-port)
- "imap"))
- (auth-info
- (auth-source-user-or-password '("login" "password") server port))
- (auth-user (nth 0 auth-info))
- (auth-passwd (nth 1 auth-info))
- (user (or
- auth-user ; this is preferred to netrc-*
- (netrc-machine-user-or-password
- "login"
- list
- (list server
- (or nnimap-server-address
- nnimap-address))
- (list port)
- (list "imap" "imaps" "143" "993"))))
- (passwd (or
- auth-passwd ; this is preferred to netrc-*
- (netrc-machine-user-or-password
- "password"
- list
- (list server
- (or nnimap-server-address
- nnimap-address))
- (list port)
- (list "imap" "imaps" "143" "993")))))
- (if (imap-authenticate user passwd nnimap-server-buffer)
- (prog2
- (setq nnimap-server-buffer-alist
- (nnimap-remove-server-from-buffer-alist
- server
- nnimap-server-buffer-alist))
- (push (list server nnimap-server-buffer)
- nnimap-server-buffer-alist)
- (imap-id nnimap-id nnimap-server-buffer)
- (nnimap-possibly-change-server server))
- (imap-close nnimap-server-buffer)
- (kill-buffer nnimap-server-buffer)
- (nnheader-report 'nnimap "Could not authenticate to %s" server)))))
-
-(deffoo nnimap-open-server (server &optional defs)
- (nnheader-init-server-buffer)
+ (erase-buffer)
+ (when (nnimap-possibly-change-group group server)
+ (with-current-buffer (nnimap-buffer)
+ (nnimap-send-command "SELECT %S" (utf7-encode group t))
+ (erase-buffer)
+ (nnimap-wait-for-response
+ (nnimap-send-command
+ "UID FETCH %s %s"
+ (nnimap-article-ranges (gnus-compress-sequence articles))
+ (format "(UID RFC822.SIZE BODYSTRUCTURE %s)"
+ (format
+ (if (member "IMAP4REV1"
+ (nnimap-capabilities nnimap-object))
+ "BODY.PEEK[HEADER.FIELDS %s]"
+ "RFC822.HEADER.LINES %s")
+ (append '(Subject From Date Message-Id
+ References In-Reply-To Xref)
+ nnmail-extra-headers))))
+ t)
+ (nnimap-transform-headers))
+ (insert-buffer-substring
+ (nnimap-find-process-buffer (current-buffer))))
+ t))
+
+(defun nnimap-transform-headers ()
+ (goto-char (point-min))
+ (let (article bytes lines)
+ (block nil
+ (while (not (eobp))
+ (while (not (looking-at "^\\* [0-9]+ FETCH.*UID \\([0-9]+\\)"))
+ (delete-region (point) (progn (forward-line 1) (point)))
+ (when (eobp)
+ (return)))
+ (setq article (match-string 1)
+ bytes (nnimap-get-length)
+ lines nil)
+ (beginning-of-line)
+ (when (search-forward "BODYSTRUCTURE" (line-end-position) t)
+ (let ((structure (ignore-errors (read (current-buffer)))))
+ (while (and (consp structure)
+ (not (stringp (car structure))))
+ (setq structure (car structure)))
+ (setq lines (nth 7 structure))))
+ (delete-region (line-beginning-position) (line-end-position))
+ (insert (format "211 %s Article retrieved." article))
+ (forward-line 1)
+ (insert (format "Bytes: %d\n" bytes))
+ (when lines
+ (insert (format "Lines: %s\n" lines)))
+ (re-search-forward "^\r$")
+ (delete-region (line-beginning-position) (line-end-position))
+ (insert ".")
+ (forward-line 1)))))
+
+(defun nnimap-get-length ()
+ (and (re-search-forward "{\\([0-9]+\\)}" (line-end-position) t)
+ (string-to-number (match-string 1))))
+
+(defun nnimap-article-ranges (ranges)
+ (let (result)
+ (cond
+ ((numberp ranges)
+ (number-to-string ranges))
+ ((numberp (cdr ranges))
+ (format "%d:%d" (car ranges) (cdr ranges)))
+ (t
+ (dolist (elem ranges)
+ (push
+ (if (consp elem)
+ (format "%d:%d" (car elem) (cdr elem))
+ (number-to-string elem))
+ result))
+ (mapconcat #'identity (nreverse result) ",")))))
+
+(defun nnimap-open-server (server &optional defs)
(if (nnimap-server-opened server)
t
- (unless (assq 'nnimap-server-buffer defs)
- (push (list 'nnimap-server-buffer (concat " *nnimap* " server)) defs))
- ;; translate `nnimap-server-address' to `nnimap-address' in defs
- ;; for people that configured nnimap with a very old version
(unless (assq 'nnimap-address defs)
- (if (assq 'nnimap-server-address defs)
- (push (list 'nnimap-address
- (cadr (assq 'nnimap-server-address defs))) defs)
- (push (list 'nnimap-address server) defs)))
+ (setq defs (append defs (list (list 'nnimap-address server)))))
(nnoo-change-server 'nnimap server defs)
- (or nnimap-server-buffer
- (setq nnimap-server-buffer (cadr (assq 'nnimap-server-buffer defs))))
- (with-current-buffer (get-buffer-create nnimap-server-buffer)
- (nnoo-change-server 'nnimap server defs))
- (let ((imap-logout-timeout nnimap-logout-timeout))
- (or (and nnimap-server-buffer
- (imap-opened nnimap-server-buffer)
- (if (with-current-buffer nnimap-server-buffer
- (memq imap-state '(auth selected examine)))
- t
- (imap-close nnimap-server-buffer)
- (nnimap-open-connection server)))
- (nnimap-open-connection server)))))
-
-(deffoo nnimap-server-opened (&optional server)
- "Whether SERVER is opened.
-If SERVER is the current virtual server, and the connection to the
-physical server is alive, this function return a non-nil value. If
-SERVER is nil, it is treated as the current server."
- ;; clean up autologouts??
- (and (or server nnimap-current-server)
- (nnoo-server-opened 'nnimap (or server nnimap-current-server))
- (imap-opened (nnimap-get-server-buffer server))))
-
-(deffoo nnimap-close-server (&optional server)
- "Close connection to server and free all resources connected to it.
-Return nil if the server couldn't be closed for some reason."
- (let ((server (or server nnimap-current-server))
- (imap-logout-timeout nnimap-logout-timeout))
- (when (or (nnimap-server-opened server)
- (imap-opened (nnimap-get-server-buffer server)))
- (imap-close (nnimap-get-server-buffer server))
- (kill-buffer (nnimap-get-server-buffer server))
- (setq nnimap-server-buffer nil
- nnimap-current-server nil
- nnimap-server-buffer-alist
- (nnimap-remove-server-from-buffer-alist
- server
- nnimap-server-buffer-alist)))
- (nnoo-close-server 'nnimap server)))
-
-(deffoo nnimap-request-close ()
- "Close connection to all servers and free all resources that the backend have reserved.
-All buffers that have been created by that
-backend should be killed. (Not the nntp-server-buffer, though.) This
-function is generally only called when Gnus is shutting down."
- (mapc (lambda (server) (nnimap-close-server (car server)))
- nnimap-server-buffer-alist)
- (setq nnimap-server-buffer-alist nil))
-
-(deffoo nnimap-status-message (&optional server)
- "This function returns the last error message from server."
- (when (nnimap-possibly-change-server server)
- (nnoo-status-message 'nnimap server)))
-
-;; We used to use a string-as-multibyte here, but it is really incorrect.
-;; This function is used when we're about to insert a unibyte string
-;; into a potentially multibyte buffer. The string is either an article
-;; header or body (or both?), undecoded. When Emacs is asked to convert
-;; a unibyte string to multibyte, it may either use the equivalent of
-;; nothing (e.g. non-Mule XEmacs), string-make-unibyte (i.e. decode using
-;; locale), string-as-multibyte (decode using emacs-internal coding system)
-;; or string-to-multibyte (keep the data undecoded as a sequence of bytes).
-;; Only the last one preserves the data such that we can reliably later on
-;; decode the text using the mime info.
-(defalias 'nnimap-demule 'mm-string-to-multibyte)
-
-(defun nnimap-make-callback (article gnus-callback buffer)
- "Return a callback function."
- `(lambda ()
- (nnimap-callback ,article ,gnus-callback ,buffer)))
-
-(defun nnimap-callback (article gnus-callback buffer)
- (when (eq article (imap-current-message))
- (remove-hook 'imap-fetch-data-hook
- (nnimap-make-callback article gnus-callback buffer))
- (with-current-buffer buffer
- (insert
- (with-current-buffer nnimap-server-buffer
- (nnimap-demule
- (if (imap-capability 'IMAP4rev1)
- ;; xxx don't just use car? alist doesn't contain
- ;; anything else now, but it might...
- (nth 2 (car (imap-message-get article 'BODYDETAIL)))
- (imap-message-get article 'RFC822)))))
- (nnheader-ms-strip-cr)
- (funcall gnus-callback t))))
-
-(defun nnimap-request-article-part (article part prop &optional
- group server to-buffer detail)
- (when (nnimap-possibly-change-group group server)
- (let ((article (if (stringp article)
- (car-safe (imap-search
- (format "HEADER Message-Id \"%s\"" article)
- nnimap-server-buffer))
- article)))
- (when article
- (gnus-message 10 "nnimap: Fetching (part of) article %d from %s..."
- article (or (nnimap-decode-group-name group)
- (imap-current-mailbox)
- (nnimap-decode-group-name
- gnus-newsgroup-name)))
- (if (not nnheader-callback-function)
- (with-current-buffer (or to-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((data (imap-fetch article part prop nil
- nnimap-server-buffer)))
- ;; data can be nil if article is write-only
- (when data
- (insert (nnimap-demule (if detail
- (nth 2 (car data))
- data)))))
- (nnheader-ms-strip-cr)
- (gnus-message
- 10 "nnimap: Fetching (part of) article %d from %s...done"
- article (or (nnimap-decode-group-name group)
- (imap-current-mailbox)
- (nnimap-decode-group-name gnus-newsgroup-name)))
- (if (bobp)
- (nnheader-report 'nnimap "No such article %d in %s: %s"
- article (or (nnimap-decode-group-name group)
- (imap-current-mailbox)
- (nnimap-decode-group-name
- gnus-newsgroup-name))
- (imap-error-text nnimap-server-buffer))
- (cons group article)))
- (add-hook 'imap-fetch-data-hook
- (nnimap-make-callback article
- nnheader-callback-function
- nntp-server-buffer))
- (imap-fetch-asynch article part nil nnimap-server-buffer)
- (cons group article))))))
-
-(deffoo nnimap-asynchronous-p ()
+ (or (nnimap-find-connection nntp-server-buffer)
+ (nnimap-open-connection nntp-server-buffer))))
+
+(defun nnimap-make-process-buffer (buffer)
+ (with-current-buffer
+ (generate-new-buffer (format "*nnimap %s %s %s*"
+ nnimap-address nnimap-server-port
+ (gnus-buffer-exists-p buffer)))
+ (mm-disable-multibyte)
+ (buffer-disable-undo)
+ (gnus-add-buffer)
+ (set (make-local-variable 'after-change-functions) nil)
+ (set (make-local-variable 'nnimap-object) (make-nnimap))
+ (push (list buffer (current-buffer)) nnimap-connection-alist)
+ (current-buffer)))
+
+(defun nnimap-open-shell-stream (name buffer host port)
+ (let ((process (start-process name buffer shell-file-name
+ shell-command-switch
+ (format-spec
+ nnimap-shell-program
+ (format-spec-make
+ ?s host
+ ?p port)))))
+ process))
+
+(defun nnimap-open-connection (buffer)
+ (with-current-buffer (nnimap-make-process-buffer buffer)
+ (let* ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (credentials
+ (cond
+ ((eq nnimap-stream 'network)
+ (open-network-stream "*nnimap*" (current-buffer) nnimap-address
+ (or nnimap-server-port
+ (if (netrc-find-service-number "imap")
+ "imap"
+ "143")))
+ (auth-source-user-or-password
+ '("login" "password") nnimap-address "imap" nil t))
+ ((eq nnimap-stream 'stream)
+ (nnimap-open-shell-stream
+ "*nnimap*" (current-buffer) nnimap-address
+ (or nnimap-server-port "imap"))
+ (auth-source-user-or-password
+ '("login" "password") nnimap-address "imap" nil t))
+ ((eq nnimap-stream 'ssl)
+ (open-tls-stream "*nnimap*" (current-buffer) nnimap-address
+ (or nnimap-server-port
+ (if (netrc-find-service-number "imaps")
+ "imaps"
+ "993")))
+ (or
+ (auth-source-user-or-password
+ '("login" "password") nnimap-address "imap")
+ (auth-source-user-or-password
+ '("login" "password") nnimap-address "imaps" nil t))))))
+ (setf (nnimap-process nnimap-object)
+ (get-buffer-process (current-buffer)))
+ (unless credentials
+ (delete-process (nnimap-process nnimap-object)))
+ (when (and (nnimap-process nnimap-object)
+ (memq (process-status (nnimap-process nnimap-object))
+ '(open run)))
+ (gnus-set-process-query-on-exit-flag (nnimap-process nnimap-object) nil)
+ (let ((result (nnimap-command "LOGIN %S %S"
+ (car credentials) (cadr credentials))))
+ (if (not (car result))
+ (progn
+ (delete-process (nnimap-process nnimap-object))
+ nil)
+ (setf (nnimap-capabilities nnimap-object)
+ (mapcar
+ #'upcase
+ (or (nnimap-find-parameter "CAPABILITY" (cdr result))
+ (nnimap-find-parameter
+ "CAPABILITY" (cdr (nnimap-command "CAPABILITY"))))))
+ (when (member "QRESYNC" (nnimap-capabilities nnimap-object))
+ (nnimap-command "ENABLE QRESYNC"))
+ t))))))
+
+(defun nnimap-find-parameter (parameter elems)
+ (let (result)
+ (dolist (elem elems)
+ (cond
+ ((equal (car elem) parameter)
+ (setq result (cdr elem)))
+ ((and (equal (car elem) "OK")
+ (consp (cadr elem))
+ (equal (caadr elem) parameter))
+ (setq result (cdr (cadr elem))))))
+ result))
+
+(defun nnimap-close-server (&optional server)
t)
-(deffoo nnimap-request-article (article &optional group server to-buffer)
- (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
- (nnimap-request-article-part
- article "BODY.PEEK[]" 'BODYDETAIL group server to-buffer 'detail)
- (nnimap-request-article-part
- article "RFC822.PEEK" 'RFC822 group server to-buffer)))
-
-(deffoo nnimap-request-head (article &optional group server to-buffer)
- (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
- (nnimap-request-article-part
- article "BODY.PEEK[HEADER]" 'BODYDETAIL group server to-buffer 'detail)
- (nnimap-request-article-part
- article "RFC822.HEADER" 'RFC822.HEADER group server to-buffer)))
-
-(deffoo nnimap-request-body (article &optional group server to-buffer)
- (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
- (nnimap-request-article-part
- article "BODY.PEEK[TEXT]" 'BODYDETAIL group server to-buffer 'detail)
- (nnimap-request-article-part
- article "RFC822.TEXT.PEEK" 'RFC822.TEXT group server to-buffer)))
-
-(deffoo nnimap-request-group (group &optional server fast)
- (nnimap-request-update-info-internal
- group
- (gnus-get-info (nnimap-group-prefixed-name group server))
- server)
- (when (nnimap-possibly-change-group group server)
- (nnimap-before-find-minmax-bugworkaround)
- (let (info)
- (cond (fast group)
- ((null (setq info (nnimap-find-minmax-uid group t)))
- (nnheader-report 'nnimap "Could not get active info for %s"
- group))
- (t
- (nnheader-insert "211 %d %d %d %s\n" (or (nth 0 info) 0)
- (max 1 (or (nth 1 info) 1))
- (or (nth 2 info) 0) group)
- (nnheader-report 'nnimap "Group %s selected" group)
- t)))))
-
-(defun nnimap-update-unseen (group &optional server)
- "Update the unseen count in `nnimap-mailbox-info'."
- (gnus-sethash
- (gnus-group-prefixed-name group server)
- (let ((old (gnus-gethash-safe (gnus-group-prefixed-name group server)
- nnimap-mailbox-info)))
- (list (nth 0 old) (nth 1 old)
- (imap-mailbox-status (nnimap-decode-group-name group)
- 'unseen nnimap-server-buffer)))
- nnimap-mailbox-info))
+(defun nnimap-request-close ()
+ t)
-(defun nnimap-close-group (group &optional server)
- (with-current-buffer nnimap-server-buffer
- (when (and (imap-opened)
- (nnimap-possibly-change-group group server))
- (nnimap-update-unseen group server)
- (case nnimap-expunge-on-close
- (always (progn
- (imap-mailbox-expunge nnimap-close-asynchronous)
- (unless nnimap-dont-close
- (imap-mailbox-close nnimap-close-asynchronous))))
- (ask (if (and (imap-search "DELETED")
- (gnus-y-or-n-p (format "Expunge articles in group `%s'? "
- (imap-current-mailbox))))
- (progn
- (imap-mailbox-expunge nnimap-close-asynchronous)
- (unless nnimap-dont-close
- (imap-mailbox-close nnimap-close-asynchronous)))
- (imap-mailbox-unselect)))
- (t (imap-mailbox-unselect)))
- (not imap-current-mailbox))))
-
-(defun nnimap-pattern-to-list-arguments (pattern)
- (mapcar (lambda (p)
- (cons (car-safe p) (or (cdr-safe p) p)))
- (if (and (listp pattern)
- (listp (cdr pattern)))
- pattern
- (list pattern))))
-
-(deffoo nnimap-request-list (&optional server)
- (when (nnimap-possibly-change-server server)
- (with-current-buffer nntp-server-buffer
- (erase-buffer))
- (gnus-message 5 "nnimap: Generating active list%s..."
- (if (> (length server) 0) (concat " for " server) ""))
- (nnimap-before-find-minmax-bugworkaround)
- (with-current-buffer nnimap-server-buffer
- (dolist (pattern (nnimap-pattern-to-list-arguments nnimap-list-pattern))
- (dolist (mbx (funcall nnimap-request-list-method
- (cdr pattern) (car pattern)))
- (unless (member "\\noselect"
- (mapcar #'downcase
- (imap-mailbox-get 'list-flags mbx)))
- (let* ((encoded-mbx (nnimap-encode-group-name mbx))
- (info (nnimap-find-minmax-uid encoded-mbx 'examine)))
- (when info
- (with-current-buffer nntp-server-buffer
- (insert (format "\"%s\" %d %d y\n"
- encoded-mbx (or (nth 2 info) 0)
- (max 1 (or (nth 1 info) 1)))))))))))
- (gnus-message 5 "nnimap: Generating active list%s...done"
- (if (> (length server) 0) (concat " for " server) ""))
- t))
+(defun nnimap-server-opened (&optional server)
+ (and (nnoo-current-server-p 'nnimap server)
+ nntp-server-buffer
+ (gnus-buffer-live-p nntp-server-buffer)
+ (nnimap-find-connection nntp-server-buffer)))
-(deffoo nnimap-request-post (&optional server)
- (let ((success t))
- (dolist (mbx (message-unquote-tokens
- (message-tokenize-header
- (message-fetch-field "Newsgroups") ", ")) success)
- (let ((to-newsgroup (gnus-group-prefixed-name mbx gnus-command-method)))
- (or (gnus-active to-newsgroup)
- (gnus-activate-group to-newsgroup)
- (if (gnus-y-or-n-p (format "No such group: %s. Create it? "
- to-newsgroup))
- (or (and (gnus-request-create-group
- to-newsgroup gnus-command-method)
- (gnus-activate-group to-newsgroup nil nil
- gnus-command-method))
- (error "Couldn't create group %s" to-newsgroup)))
- (error "No such group: %s" to-newsgroup))
- (unless (nnimap-request-accept-article mbx (nth 1 gnus-command-method))
- (setq success nil))))))
-
-;; Optional backend functions
-
-(defun nnimap-string-lessp-numerical (s1 s2)
- "Return t if first arg string is less than second in numerical order."
- (cond ((string= s1 s2)
- nil)
- ((> (length s1) (length s2))
- nil)
- ((< (length s1) (length s2))
- t)
- ((< (string-to-number (substring s1 0 1))
- (string-to-number (substring s2 0 1)))
- t)
- ((> (string-to-number (substring s1 0 1))
- (string-to-number (substring s2 0 1)))
- nil)
- (t
- (nnimap-string-lessp-numerical (substring s1 1) (substring s2 1)))))
-
-(deffoo nnimap-retrieve-groups (groups &optional server)
- (when (nnimap-possibly-change-server server)
- (gnus-message 5 "nnimap: Checking mailboxes...")
- (with-current-buffer nntp-server-buffer
- (erase-buffer)
- (nnimap-before-find-minmax-bugworkaround)
- (let (asyncgroups slowgroups decoded-group)
- (if (null nnimap-retrieve-groups-asynchronous)
- (setq slowgroups groups)
- (dolist (group groups)
- (setq decoded-group (nnimap-decode-group-name group))
- (gnus-message 9 "nnimap: Quickly checking mailbox %s"
- decoded-group)
- (add-to-list (if (gnus-group-get-parameter
- (nnimap-group-prefixed-name group)
- 'imap-status)
- 'asyncgroups
- 'slowgroups)
- (list group (imap-mailbox-status-asynch
- decoded-group
- '(uidvalidity uidnext unseen)
- nnimap-server-buffer))))
- (dolist (asyncgroup asyncgroups)
- (let* ((group (nth 0 asyncgroup))
- (tag (nth 1 asyncgroup))
- (gnusgroup (nnimap-group-prefixed-name group))
- (saved-uidvalidity (gnus-group-get-parameter gnusgroup
- 'uidvalidity))
- (saved-imap-status (gnus-group-get-parameter gnusgroup
- 'imap-status))
- (saved-info (and saved-imap-status
- (split-string saved-imap-status " "))))
- (setq decoded-group (nnimap-decode-group-name group))
- (when (imap-ok-p (imap-wait-for-tag tag nnimap-server-buffer))
- (if (or (not (equal
- saved-uidvalidity
- (imap-mailbox-get 'uidvalidity decoded-group
- nnimap-server-buffer)))
- (not (equal
- (nth 0 saved-info)
- (imap-mailbox-get 'uidnext decoded-group
- nnimap-server-buffer))))
- (push (list group) slowgroups)
- (gnus-sethash
- (gnus-group-prefixed-name group server)
- (list (imap-mailbox-get 'uidvalidity
- decoded-group nnimap-server-buffer)
- (imap-mailbox-get 'uidnext
- decoded-group nnimap-server-buffer)
- (imap-mailbox-get 'unseen
- decoded-group nnimap-server-buffer))
- nnimap-mailbox-info)
- (insert (format "\"%s\" %s %s y\n" group
- (nth 2 saved-info)
- (nth 1 saved-info))))))))
- (dolist (group slowgroups)
- (if nnimap-retrieve-groups-asynchronous
- (setq group (car group)))
- (setq decoded-group (nnimap-decode-group-name group))
- (gnus-message 7 "nnimap: Mailbox %s modified" decoded-group)
- (or (member "\\NoSelect" (imap-mailbox-get 'list-flags decoded-group
- nnimap-server-buffer))
- (let* ((gnusgroup (nnimap-group-prefixed-name group))
- (status (imap-mailbox-status
- decoded-group '(uidvalidity uidnext unseen)
- nnimap-server-buffer))
- (info (nnimap-find-minmax-uid group 'examine))
- (min-uid (max 1 (or (nth 1 info) 1)))
- (max-uid (or (nth 2 info) 0)))
- (when (> (or (imap-mailbox-get 'recent decoded-group
- nnimap-server-buffer) 0)
- 0)
- (push (list (cons decoded-group 0)) nnmail-split-history))
- (insert (format "\"%s\" %d %d y\n" group max-uid min-uid))
- (gnus-sethash
- (gnus-group-prefixed-name group server)
- status
- nnimap-mailbox-info)
- (if (not (equal (nth 0 status)
- (gnus-group-get-parameter gnusgroup
- 'uidvalidity)))
- (nnimap-verify-uidvalidity group nnimap-current-server))
- ;; The imap-status parameter is a string on the form
- ;; "<uidnext> <min-uid> <max-uid>".
- (gnus-group-add-parameter
- gnusgroup
- (cons 'imap-status
- (format "%s %s %s" (nth 1 status) min-uid max-uid))))))))
- (gnus-message 5 "nnimap: Checking mailboxes...done")
- 'active))
-
-(deffoo nnimap-request-update-info-internal (group info &optional server)
- (when (nnimap-possibly-change-group group server)
- (when info ;; xxx what does this mean? should we create a info?
- (with-current-buffer nnimap-server-buffer
- (gnus-message 5 "nnimap: Updating info for %s..."
- (nnimap-decode-group-name (gnus-info-group info)))
-
- (when (nnimap-mark-permanent-p 'read)
- (let (seen unseen)
- ;; read info could contain articles marked unread by other
- ;; imap clients! we correct this
- (setq unseen (gnus-compress-sequence
- (imap-search "UNSEEN UNDELETED"))
- seen (gnus-range-difference (gnus-info-read info) unseen)
- seen (gnus-range-add seen
- (gnus-compress-sequence
- (imap-search "SEEN")))
- seen (if (and (integerp (car seen))
- (null (cdr seen)))
- (list (cons (car seen) (car seen)))
- seen))
- (gnus-info-set-read info seen)))
-
- (dolist (pred gnus-article-mark-lists)
- (when (or (eq (cdr pred) 'recent)
- (and (nnimap-mark-permanent-p (cdr pred))
- (member (nnimap-mark-to-flag (cdr pred))
- (imap-mailbox-get 'flags))))
- (gnus-info-set-marks
- info
- (gnus-update-alist-soft
- (cdr pred)
- (gnus-compress-sequence
- (imap-search (nnimap-mark-to-predicate (cdr pred))))
- (gnus-info-marks info))
- t)))
-
- (when nnimap-importantize-dormant
- ;; nnimap mark dormant article as ticked too (for other clients)
- ;; so we remove that mark for gnus since we support dormant
- (gnus-info-set-marks
- info
- (gnus-update-alist-soft
- 'tick
- (gnus-remove-from-range
- (cdr-safe (assoc 'tick (gnus-info-marks info)))
- (cdr-safe (assoc 'dormant (gnus-info-marks info))))
- (gnus-info-marks info))
- t))
-
- (gnus-message 5 "nnimap: Updating info for %s...done"
- (nnimap-decode-group-name (gnus-info-group info)))
-
- info))))
-
-(deffoo nnimap-request-type (group &optional article)
- (if (and nnimap-news-groups (string-match nnimap-news-groups group))
- 'news
- 'mail))
-
-(deffoo nnimap-request-set-mark (group actions &optional server)
- (when (nnimap-possibly-change-group group server)
- (with-current-buffer nnimap-server-buffer
- (let (action)
- (gnus-message 7 "nnimap: Setting marks in %s..."
- (nnimap-decode-group-name group))
- (while (setq action (pop actions))
- (let ((range (nth 0 action))
- (what (nth 1 action))
- (cmdmarks (nth 2 action))
- marks)
- ;; bookmark can't be stored (not list/range
- (setq cmdmarks (delq 'bookmark cmdmarks))
- ;; killed can't be stored (not list/range
- (setq cmdmarks (delq 'killed cmdmarks))
- ;; unsent are for nndraft groups only
- (setq cmdmarks (delq 'unsent cmdmarks))
- ;; cache flags are pointless on the server
- (setq cmdmarks (delq 'cache cmdmarks))
- ;; seen flags are local to each gnus
- (setq cmdmarks (delq 'seen cmdmarks))
- ;; recent marks can't be set
- (setq cmdmarks (delq 'recent cmdmarks))
- (when nnimap-importantize-dormant
- ;; flag dormant articles as ticked
- (if (memq 'dormant cmdmarks)
- (setq cmdmarks (cons 'tick cmdmarks))))
- ;; remove stuff we are forbidden to store
- (mapc (lambda (mark)
- (if (imap-message-flag-permanent-p
- (nnimap-mark-to-flag mark))
- (setq marks (cons mark marks))))
- cmdmarks)
- (when (and range marks)
- (cond ((eq what 'del)
- (imap-message-flags-del
- (imap-range-to-message-set range)
- (nnimap-mark-to-flag marks nil t)))
- ((eq what 'add)
- (imap-message-flags-add
- (imap-range-to-message-set range)
- (nnimap-mark-to-flag marks nil t)))
- ((eq what 'set)
- (imap-message-flags-set
- (imap-range-to-message-set range)
- (nnimap-mark-to-flag marks nil t)))))))
- (gnus-message 7 "nnimap: Setting marks in %s...done"
- (nnimap-decode-group-name group)))))
- nil)
+(defun nnimap-status-message (&optional server)
+ nnimap-status-string)
-(defun nnimap-split-fancy ()
- "Like the function `nnmail-split-fancy', but uses `nnimap-split-fancy'."
- (let ((nnmail-split-fancy nnimap-split-fancy))
- (nnmail-split-fancy)))
-
-(defun nnimap-split-to-groups (rules)
- ;; tries to match all rules in nnimap-split-rule against content of
- ;; nntp-server-buffer, returns a list of groups that matched.
- ;; Note: This function takes and returns decoded group names.
+(defun nnimap-request-article (article &optional group server to-buffer)
(with-current-buffer nntp-server-buffer
- ;; Fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- (if (functionp rules)
- (funcall rules)
- (let (to-groups regrepp)
- (catch 'split-done
- (dolist (rule rules to-groups)
- (let ((group (car rule))
- (regexp (cadr rule)))
+ (let ((result (nnimap-possibly-change-group group server)))
+ (when (stringp article)
+ (setq article (nnimap-find-article-by-message-id group article)))
+ (when (and result
+ article)
+ (erase-buffer)
+ (with-current-buffer (nnimap-buffer)
+ (erase-buffer)
+ (setq result
+ (nnimap-command
+ (if (member "IMAP4REV1" (nnimap-capabilities nnimap-object))
+ "UID FETCH %d BODY.PEEK[]"
+ "UID FETCH %d RFC822.PEEK")
+ article)))
+ (let ((buffer (nnimap-find-process-buffer (current-buffer))))
+ (when (car result)
+ (with-current-buffer to-buffer
+ (insert-buffer-substring buffer)
(goto-char (point-min))
- (when (and (if (stringp regexp)
- (progn
- (if (not (stringp group))
- (setq group (eval group))
- (setq regrepp
- (string-match "\\\\[0-9&]" group)))
- (re-search-forward regexp nil t))
- (funcall regexp group))
- ;; Don't enter the article into the same group twice.
- (not (assoc group to-groups)))
- (push (if regrepp
- (nnmail-expand-newtext group)
- group)
- to-groups)
- (or nnimap-split-crosspost
- (throw 'split-done to-groups))))))))))
-
-(defun nnimap-assoc-match (key alist)
- (let (element)
- (while (and alist (not element))
- (if (string-match (car (car alist)) key)
- (setq element (car alist)))
- (setq alist (cdr alist)))
- element))
-
-(defun nnimap-split-find-rule (server inbox)
- (if (and (listp nnimap-split-rule) (listp (car nnimap-split-rule))
- (list (cdar nnimap-split-rule)) (listp (cadar nnimap-split-rule)))
- ;; extended format
- (cadr (nnimap-assoc-match inbox (cdr (nnimap-assoc-match
- server nnimap-split-rule))))
- nnimap-split-rule))
-
-(defun nnimap-split-find-inbox (server)
- (if (listp nnimap-split-inbox)
- nnimap-split-inbox
- (list nnimap-split-inbox)))
-
-(defun nnimap-split-articles (&optional group server)
- ;; Note: Assumes decoded group names in nnimap-split-inbox,
- ;; nnimap-split-rule, nnimap-split-fancy, and nnmail-split-history.
- (when (nnimap-possibly-change-server server)
- (with-current-buffer nnimap-server-buffer
- (let (rule inbox removeorig
- (inboxes (nnimap-split-find-inbox server)))
- ;; iterate over inboxes
- (while (and (setq inbox (pop inboxes))
- (nnimap-possibly-change-group
- (nnimap-encode-group-name inbox))) ;; SELECT
- ;; find split rule for this server / inbox
- (when (setq rule (nnimap-split-find-rule server inbox))
- ;; iterate over articles
- (dolist (article (imap-search nnimap-split-predicate))
- (when (if (if (eq nnimap-split-download-body 'default)
- nnimap-split-download-body-default
- nnimap-split-download-body)
- (and (nnimap-request-article article)
- (with-current-buffer nntp-server-buffer (mail-narrow-to-head)))
- (nnimap-request-head article))
- ;; copy article to right group(s)
- (setq removeorig nil)
- (dolist (to-group (nnimap-split-to-groups rule))
- (cond ((eq to-group 'junk)
- (message "IMAP split removed %s:%s:%d" server inbox
- article)
- (setq removeorig t))
- ((imap-message-copy (number-to-string article)
- to-group nil 'nocopyuid)
- (message "IMAP split moved %s:%s:%d to %s" server
- inbox article to-group)
- (setq removeorig t)
- (when nnmail-cache-accepted-message-ids
- (with-current-buffer nntp-server-buffer
- (let (msgid)
- (and (setq msgid
- (nnmail-fetch-field "message-id"))
- (nnmail-cache-insert msgid
- (nnimap-encode-group-name to-group)
- (nnmail-fetch-field "subject"))))))
- ;; Add the group-art list to the history list.
- (push (list (cons to-group 0)) nnmail-split-history))
- (t
- (message "IMAP split failed to move %s:%s:%d to %s"
- server inbox article to-group))))
- (if (if (eq nnimap-split-download-body 'default)
- nnimap-split-download-body-default
- nnimap-split-download-body)
- (widen))
- ;; remove article if it was successfully copied somewhere
- (and removeorig
- (imap-message-flags-add (format "%d" article)
- "\\Seen \\Deleted")))))
- (when (imap-mailbox-select inbox) ;; just in case
- ;; todo: UID EXPUNGE (if available) to remove splitted articles
- (imap-mailbox-expunge)
- (imap-mailbox-close)))
- (when nnmail-cache-accepted-message-ids
- (nnmail-cache-close))
+ (let ((bytes (nnimap-get-length)))
+ (delete-region (line-beginning-position)
+ (progn (forward-line 1) (point)))
+ (goto-char (+ (point) bytes))
+ (delete-region (point) (point-max))
+ (nnheader-ms-strip-cr))
+ t)))))))
+
+(defun nnimap-request-group (group &optional server dont-check)
+ (with-current-buffer nntp-server-buffer
+ (let ((result (nnimap-possibly-change-group group server))
+ articles)
+ (when result
+ (setq articles (nnimap-get-flags "1:*"))
+ (erase-buffer)
+ (insert
+ (format
+ "211 %d %d %d %S\n"
+ (length articles)
+ (or (caar articles) 0)
+ (or (caar (last articles)) 0)
+ group))
t))))
-(deffoo nnimap-request-scan (&optional group server)
- (nnimap-split-articles group server))
-
-(deffoo nnimap-request-newgroups (date &optional server)
- (when (nnimap-possibly-change-server server)
- (with-current-buffer nntp-server-buffer
- (gnus-message 5 "nnimap: Listing subscribed mailboxes%s%s..."
- (if (> (length server) 0) " on " "") server)
+(defun nnimap-get-flags (spec)
+ (let ((articles nil)
+ elems)
+ (with-current-buffer (nnimap-buffer)
(erase-buffer)
- (nnimap-before-find-minmax-bugworkaround)
- (dolist (pattern (nnimap-pattern-to-list-arguments
- nnimap-list-pattern))
- (dolist (mbx (funcall nnimap-request-list-method (cdr pattern) (car pattern) nil
- nnimap-server-buffer))
- (or (catch 'found
- (dolist (mailbox (imap-mailbox-get 'list-flags mbx
- nnimap-server-buffer))
- (if (string= (downcase mailbox) "\\noselect")
- (throw 'found t)))
- nil)
- (let* ((encoded-mbx (nnimap-encode-group-name mbx))
- (info (nnimap-find-minmax-uid encoded-mbx 'examine)))
- (when info
- (insert (format "\"%s\" %d %d y\n"
- encoded-mbx (or (nth 2 info) 0)
- (max 1 (or (nth 1 info) 1)))))))))
- (gnus-message 5 "nnimap: Listing subscribed mailboxes%s%s...done"
- (if (> (length server) 0) " on " "") server))
- t))
+ (nnimap-wait-for-response (nnimap-send-command
+ "UID FETCH %s FLAGS" spec))
+ (goto-char (point-min))
+ (while (re-search-forward "^\\* [0-9]+ FETCH (\\(.*\\))" nil t)
+ (setq elems (nnimap-parse-line (match-string 1)))
+ (push (cons (string-to-number (cadr (member "UID" elems)))
+ (cadr (member "FLAGS" elems)))
+ articles)))
+ (nreverse articles)))
-(deffoo nnimap-request-create-group (group &optional server args)
- (when (nnimap-possibly-change-server server)
- (let ((decoded-group (nnimap-decode-group-name group)))
- (or (imap-mailbox-status decoded-group 'uidvalidity nnimap-server-buffer)
- (imap-mailbox-create decoded-group nnimap-server-buffer)
- (nnheader-report 'nnimap "%S"
- (imap-error-text nnimap-server-buffer))))))
-
-(defun nnimap-time-substract (time1 time2)
- "Return TIME for TIME1 - TIME2."
- (let* ((ms (- (car time1) (car time2)))
- (ls (- (nth 1 time1) (nth 1 time2))))
- (if (< ls 0)
- (list (- ms 1) (+ (expt 2 16) ls))
- (list ms ls))))
-
-(eval-when-compile (require 'parse-time))
-(defun nnimap-date-days-ago (daysago)
- "Return date, in format \"3-Aug-1998\", for DAYSAGO days ago."
- (require 'parse-time)
- (let* ((time (nnimap-time-substract (current-time) (days-to-time daysago)))
- (date (format-time-string
- (format "%%d-%s-%%Y"
- (capitalize (car (rassoc (nth 4 (decode-time time))
- parse-time-months))))
- time)))
- (if (eq ?0 (string-to-char date))
- (substring date 1)
- date)))
-
-(defun nnimap-request-expire-articles-progress ()
- (gnus-message 5 "nnimap: Marking article %d for deletion..."
- imap-current-message))
-
-(defun nnimap-expiry-target (arts group server)
- (unless (eq nnmail-expiry-target 'delete)
- (with-temp-buffer
- (dolist (art arts)
- (nnimap-request-article art group server (current-buffer))
- ;; hints for optimization in `nnimap-request-accept-article'
- (let ((nnimap-current-move-article art)
- (nnimap-current-move-group group)
- (nnimap-current-move-server server))
- (nnmail-expiry-target-group nnmail-expiry-target group))))
- ;; It is not clear if `nnmail-expiry-target' somehow cause the
- ;; current group to be changed or not, so we make sure here.
- (nnimap-possibly-change-group group server)))
-
-;; Notice that we don't actually delete anything, we just mark them deleted.
-(deffoo nnimap-request-expire-articles (articles group &optional server force)
- (let ((artseq (gnus-compress-sequence articles)))
- (when (and artseq (nnimap-possibly-change-group group server))
- (with-current-buffer nnimap-server-buffer
- (let ((days (or (and nnmail-expiry-wait-function
- (funcall nnmail-expiry-wait-function group))
- nnmail-expiry-wait)))
- (cond ((or force (eq days 'immediate))
- (let ((oldarts (imap-search
- (concat "UID "
- (imap-range-to-message-set artseq)))))
- (when oldarts
- (nnimap-expiry-target oldarts group server)
- (when (imap-message-flags-add
- (imap-range-to-message-set
- (gnus-compress-sequence oldarts)) "\\Deleted")
- (setq articles (gnus-set-difference
- articles oldarts))))))
- ((and nnimap-search-uids-not-since-is-evil (numberp days))
- (let* ((all-new-articles
- (gnus-compress-sequence
- (imap-search (format "SINCE %s"
- (nnimap-date-days-ago days)))))
- (oldartseq
- (gnus-range-difference artseq all-new-articles))
- (oldarts (gnus-uncompress-range oldartseq)))
- (when oldarts
- (nnimap-expiry-target oldarts group server)
- (when (imap-message-flags-add
- (imap-range-to-message-set oldartseq)
- "\\Deleted")
- (setq articles (gnus-set-difference
- articles oldarts))))))
- ((numberp days)
- (let ((oldarts (imap-search
- (format nnimap-expunge-search-string
- (imap-range-to-message-set artseq)
- (nnimap-date-days-ago days))))
- (imap-fetch-data-hook
- '(nnimap-request-expire-articles-progress)))
- (when oldarts
- (nnimap-expiry-target oldarts group server)
- (when (imap-message-flags-add
- (imap-range-to-message-set
- (gnus-compress-sequence oldarts)) "\\Deleted")
- (setq articles (gnus-set-difference
- articles oldarts)))))))))))
- ;; return articles not deleted
- articles)
+(defun nnimap-close-group (group &optional server)
+ t)
(deffoo nnimap-request-move-article (article group server accept-form
- &optional last move-is-internal)
- (when (nnimap-possibly-change-server server)
- (save-excursion
- (let ((buf (get-buffer-create " *nnimap move*"))
- (nnimap-current-move-article article)
- (nnimap-current-move-group group)
- (nnimap-current-move-server nnimap-current-server)
- result)
- (gnus-message 10 "nnimap-request-move-article: this is an %s move"
- (if move-is-internal
- "internal"
- "external"))
- ;; request the article only when the move is NOT internal
- (and (or move-is-internal
- (nnimap-request-article article group server))
- (with-current-buffer buf
- (buffer-disable-undo (current-buffer))
- (insert-buffer-substring nntp-server-buffer)
- (setq result (eval accept-form))
- (kill-buffer buf)
- result)
- (nnimap-possibly-change-group group server)
- (imap-message-flags-add
- (imap-range-to-message-set (list article))
- "\\Deleted" 'silent nnimap-server-buffer))
- result))))
+ &optional last internal-move-group)
+ (when (nnimap-possibly-change-group group server)
+ ;; If the move is internal (on the same server), just do it the easy
+ ;; way.
+ (let ((message-id (message-field-value "message-id")))
+ (if internal-move-group
+ (let ((result
+ (with-current-buffer (nnimap-buffer)
+ (nnimap-command "UID COPY %d %S"
+ article
+ (utf7-encode internal-move-group t)))))
+ (when (car result)
+ (nnimap-delete-article article)
+ (cons internal-move-group
+ (nnimap-find-article-by-message-id
+ internal-move-group message-id))))
+ (with-temp-buffer
+ (let ((result (eval accept-form)))
+ (when result
+ (nnimap-delete-article article)
+ result)))))))
+
+(deffoo nnimap-request-expire-articles (articles group &optional server force)
+ (cond
+ ((not (nnimap-possibly-change-group group server))
+ articles)
+ (force
+ (unless (nnimap-delete-article articles)
+ (message "Article marked for deletion, but not expunged."))
+ nil)
+ (t
+ articles)))
+
+(defun nnimap-find-article-by-message-id (group message-id)
+ (when (nnimap-possibly-change-group group nil)
+ (with-current-buffer (nnimap-buffer)
+ (let ((result
+ (nnimap-command "UID SEARCH HEADER Message-Id %S" message-id))
+ article)
+ (when (car result)
+ ;; Select the last instance of the message in the group.
+ (and (setq article
+ (car (last (assoc "SEARCH" (cdr result)))))
+ (string-to-number article)))))))
+
+(defun nnimap-delete-article (articles)
+ (with-current-buffer (nnimap-buffer)
+ (nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)"
+ (nnimap-article-ranges articles))
+ (when (member "UIDPLUS" (nnimap-capabilities nnimap-object))
+ (nnimap-send-command "UID EXPUNGE %s"
+ (nnimap-article-ranges articles))
+ t)))
+
+(deffoo nnimap-request-scan (&optional group server)
+ (when (and (nnimap-possibly-change-group nil server)
+ (equal group nnimap-inbox)
+ nnimap-inbox
+ nnimap-split-methods)
+ (nnimap-split-incoming-mail)))
+
+(defun nnimap-marks-to-flags (marks)
+ (let (flags flag)
+ (dolist (mark marks)
+ (when (setq flag (cadr (assq mark nnimap-mark-alist)))
+ (push flag flags)))
+ flags))
+
+(defun nnimap-request-set-mark (group actions &optional server)
+ (when (nnimap-possibly-change-group group server)
+ (let (sequence)
+ (with-current-buffer (nnimap-buffer)
+ ;; Just send all the STORE commands without waiting for
+ ;; response. If they're successful, they're successful.
+ (dolist (action actions)
+ (destructuring-bind (range action marks) action
+ (let ((flags (nnimap-marks-to-flags marks)))
+ (when flags
+ (setq sequence (nnimap-send-command
+ "UID STORE %s %sFLAGS.SILENT (%s)"
+ (nnimap-article-ranges range)
+ (if (eq action 'del)
+ "-"
+ "+")
+ (mapconcat #'identity flags " ")))))))
+ ;; Wait for the last command to complete to avoid later
+ ;; syncronisation problems with the stream.
+ (nnimap-wait-for-response sequence)))))
(deffoo nnimap-request-accept-article (group &optional server last)
- (when (nnimap-possibly-change-server server)
- (let (uid)
- (if (setq uid
- (if (string= nnimap-current-server nnimap-current-move-server)
- ;; moving article within same server, speed it up...
- (and (nnimap-possibly-change-group
- nnimap-current-move-group)
- (imap-message-copy (number-to-string
- nnimap-current-move-article)
- (nnimap-decode-group-name group)
- 'dontcreate nil
- nnimap-server-buffer))
- (with-current-buffer (current-buffer)
- (goto-char (point-min))
- ;; remove any 'From blabla' lines, some IMAP servers
- ;; reject the entire message otherwise.
- (when (looking-at "^From[^:]")
- (delete-region (point) (progn (forward-line) (point))))
- ;; turn into rfc822 format (\r\n eol's)
- (while (search-forward "\n" nil t)
- (replace-match "\r\n"))
- (when nnmail-cache-accepted-message-ids
- (nnmail-cache-insert (nnmail-fetch-field "message-id")
- group
- (nnmail-fetch-field "subject"))))
- (when (and last nnmail-cache-accepted-message-ids)
- (nnmail-cache-close))
- ;; this 'or' is for Cyrus server bug
- (or (null (imap-current-mailbox nnimap-server-buffer))
- (imap-mailbox-unselect nnimap-server-buffer))
- (imap-message-append (nnimap-decode-group-name group)
- (current-buffer) nil nil
- nnimap-server-buffer)))
- (cons group (nth 1 uid))
- (nnheader-report 'nnimap (imap-error-text nnimap-server-buffer))))))
-
-(deffoo nnimap-request-delete-group (group force &optional server)
- (when (nnimap-possibly-change-server server)
- (setq group (nnimap-decode-group-name group))
- (when (string= group (imap-current-mailbox nnimap-server-buffer))
- (imap-mailbox-unselect nnimap-server-buffer))
- (with-current-buffer nnimap-server-buffer
- (if force
- (or (null (imap-mailbox-status group 'uidvalidity))
- (imap-mailbox-delete group))
- ;; UNSUBSCRIBE?
+ (when (nnimap-possibly-change-group nil server)
+ (nnmail-check-syntax)
+ (let ((message (buffer-string))
+ (message-id (message-field-value "message-id"))
+ sequence)
+ (with-current-buffer (nnimap-buffer)
+ (setq sequence (nnimap-send-command
+ "APPEND %S {%d}" (utf7-encode group t)
+ (length message)))
+ (process-send-string (get-buffer-process (current-buffer)) message)
+ (process-send-string (get-buffer-process (current-buffer)) "\r\n")
+ (let ((result (nnimap-get-response sequence)))
+ (when result
+ (cons group
+ (nnimap-find-article-by-message-id group message-id))))))))
+
+(defun nnimap-add-cr ()
+ (goto-char (point-min))
+ (while (re-search-forward "\r?\n" nil t)
+ (replace-match "\r\n" t t)))
+
+(defun nnimap-get-groups ()
+ (let ((result (nnimap-command "LIST \"\" \"*\""))
+ groups)
+ (when (car result)
+ (dolist (line (cdr result))
+ (when (and (equal (car line) "LIST")
+ (not (and (caadr line)
+ (string-match "noselect" (caadr line)))))
+ (push (car (last line)) groups)))
+ (nreverse groups))))
+
+(defun nnimap-request-list (&optional server)
+ (nnimap-possibly-change-group nil server)
+ (with-current-buffer nntp-server-buffer
+ (erase-buffer)
+ (let ((groups
+ (with-current-buffer (nnimap-buffer)
+ (nnimap-get-groups)))
+ sequences responses)
+ (when groups
+ (with-current-buffer (nnimap-buffer)
+ (dolist (group groups)
+ (push (list (nnimap-send-command "EXAMINE %S" (utf7-encode group t))
+ group)
+ sequences))
+ (nnimap-wait-for-response (caar sequences))
+ (setq responses
+ (nnimap-get-responses (mapcar #'car sequences))))
+ (dolist (response responses)
+ (let* ((sequence (car response))
+ (response (cadr response))
+ (group (cadr (assoc sequence sequences))))
+ (when (and group
+ (equal (caar response) "OK"))
+ (let ((uidnext (nnimap-find-parameter "UIDNEXT" response))
+ highest exists)
+ (dolist (elem response)
+ (when (equal (cadr elem) "EXISTS")
+ (setq exists (string-to-number (car elem)))))
+ (when uidnext
+ (setq highest (1- (string-to-number (car uidnext)))))
+ (cond
+ ((null highest)
+ (insert (format "%S 0 1 y\n" (utf7-decode group t))))
+ ((zerop exists)
+ ;; Empty group.
+ (insert (format "%S %d %d y\n"
+ (utf7-decode group t) highest (1+ highest))))
+ (t
+ ;; Return the widest possible range.
+ (insert (format "%S %d 1 y\n" (utf7-decode group t)
+ (or highest exists)))))))))
t))))
-(deffoo nnimap-request-rename-group (group new-name &optional server)
- (when (nnimap-possibly-change-server server)
- (imap-mailbox-rename (nnimap-decode-group-name group)
- (nnimap-decode-group-name new-name)
- nnimap-server-buffer)))
-
-(defun nnimap-expunge (mailbox server)
- (when (nnimap-possibly-change-group mailbox server)
- (imap-mailbox-expunge nil nnimap-server-buffer)))
-
-(defun nnimap-acl-get (mailbox server)
- (when (nnimap-possibly-change-server server)
- (and (imap-capability 'ACL nnimap-server-buffer)
- (imap-mailbox-acl-get (nnimap-decode-group-name mailbox)
- nnimap-server-buffer))))
-
-(defun nnimap-acl-edit (mailbox method old-acls new-acls)
- (when (nnimap-possibly-change-server (cadr method))
- (unless (imap-capability 'ACL nnimap-server-buffer)
- (error "Your server does not support ACL editing"))
- (with-current-buffer nnimap-server-buffer
- ;; delete all removed identifiers
- (mapc (lambda (old-acl)
- (unless (assoc (car old-acl) new-acls)
- (or (imap-mailbox-acl-delete (car old-acl)
- (nnimap-decode-group-name mailbox))
- (error "Can't delete ACL for %s" (car old-acl)))))
- old-acls)
- ;; set all changed acl's
- (mapc (lambda (new-acl)
- (let ((new-rights (cdr new-acl))
- (old-rights (cdr (assoc (car new-acl) old-acls))))
- (unless (and old-rights new-rights
- (string= old-rights new-rights))
- (or (imap-mailbox-acl-set (car new-acl) new-rights
- (nnimap-decode-group-name mailbox))
- (error "Can't set ACL for %s to %s" (car new-acl)
- new-rights)))))
- new-acls)
- t)))
+(defun nnimap-retrieve-group-data-early (server infos)
+ (when (nnimap-possibly-change-group nil server)
+ (with-current-buffer (nnimap-buffer)
+ ;; QRESYNC handling isn't implemented.
+ (let ((qresyncp (member "notQRESYNC" (nnimap-capabilities nnimap-object)))
+ marks groups sequences)
+ ;; Go through the infos and gather the data needed to know
+ ;; what and how to request the data.
+ (dolist (info infos)
+ (setq marks (gnus-info-marks info))
+ (push (list (gnus-group-real-name (gnus-info-group info))
+ (cdr (assq 'active marks))
+ (cdr (assq 'uid marks)))
+ groups))
+ ;; Then request the data.
+ (erase-buffer)
+ (dolist (elem groups)
+ (if (and qresyncp
+ (nth 2 elem))
+ (push
+ (list 'qresync
+ (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))"
+ (car elem)
+ (car (nth 2 elem))
+ (cdr (nth 2 elem)))
+ nil
+ (car elem))
+ sequences)
+ (let ((start
+ (if (nth 1 elem)
+ ;; Fetch the last 100 flags.
+ (max 1 (- (cdr (nth 1 elem)) 100))
+ 1)))
+ (push (list (nnimap-send-command "EXAMINE %S" (car elem))
+ (nnimap-send-command "UID FETCH %d:* FLAGS" start)
+ start
+ (car elem))
+ sequences))))
+ sequences))))
+
+(defun nnimap-finish-retrieve-group-infos (server infos sequences)
+ (when (and sequences
+ (nnimap-possibly-change-group nil server))
+ (with-current-buffer (nnimap-buffer)
+ ;; Wait for the final data to trickle in.
+ (nnimap-wait-for-response (cadar sequences))
+ ;; Now we should have all the data we need, no matter whether
+ ;; we're QRESYNCING, fetching all the flags from scratch, or
+ ;; just fetching the last 100 flags per group.
+ (nnimap-update-infos (nnimap-flags-to-marks
+ (nnimap-parse-flags
+ (nreverse sequences)))
+ infos))))
+
+(defun nnimap-update-infos (flags infos)
+ (dolist (info infos)
+ (let ((group (gnus-group-real-name (gnus-info-group info))))
+ (nnimap-update-info info (cdr (assoc group flags))))))
+
+(defun nnimap-update-info (info marks)
+ (when marks
+ (destructuring-bind (existing flags high low uidnext start-article) marks
+ (let ((group (gnus-info-group info))
+ (completep (and start-article
+ (= start-article 1))))
+ ;; First set the active ranges based on high/low.
+ (if (or completep
+ (not (gnus-active group)))
+ (gnus-set-active group
+ (if high
+ (cons low high)
+ ;; No articles in this group.
+ (cons (1- uidnext) uidnext)))
+ (setcdr (gnus-active group) high))
+ ;; Then update the list of read articles.
+ (let* ((unread
+ (gnus-compress-sequence
+ (gnus-set-difference
+ (gnus-set-difference
+ existing
+ (cdr (assoc "\\Seen" flags)))
+ (cdr (assoc "\\Flagged" flags)))))
+ (read (gnus-range-difference
+ (cons start-article high) unread)))
+ (when (> start-article 1)
+ (setq read
+ (gnus-range-nconcat
+ (gnus-sorted-range-intersection
+ (cons 1 start-article)
+ (gnus-info-read info))
+ read)))
+ (gnus-info-set-read info read)
+ ;; Update the marks.
+ (setq marks (gnus-info-marks info))
+ ;; Note the active level for the next run-through.
+ (let ((active (assq 'active marks)))
+ (if active
+ (setcdr active (gnus-active group))
+ (push (cons 'active (gnus-active group)) marks)))
+ (dolist (type (cdr nnimap-mark-alist))
+ (let ((old-marks (assoc (car type) marks))
+ (new-marks (gnus-compress-sequence
+ (cdr (assoc (cadr type) flags)))))
+ (setq marks (delq old-marks marks))
+ (pop old-marks)
+ (when (and old-marks
+ (> start-article 1))
+ (setq old-marks (gnus-range-difference
+ (cons start-article high)
+ old-marks))
+ (setq new-marks (gnus-range-nconcat old-marks new-marks)))
+ (when new-marks
+ (push (cons (car type) new-marks) marks)))
+ (gnus-info-set-marks info marks)))))))
+
+(defun nnimap-flags-to-marks (groups)
+ (let (data group totalp uidnext articles start-article mark)
+ (dolist (elem groups)
+ (setq group (car elem)
+ uidnext (cadr elem)
+ start-article (caddr elem)
+ articles (cdddr elem))
+ (let ((high (caar articles))
+ marks low existing)
+ (dolist (article articles)
+ (setq low (car article))
+ (push (car article) existing)
+ (dolist (flag (cdr article))
+ (setq mark (assoc flag marks))
+ (if (not mark)
+ (push (list flag (car article)) marks)
+ (setcdr mark (cons (car article) (cdr mark)))))
+ (push (list group existing marks high low uidnext start-article)
+ data))))
+ data))
+
+(defun nnimap-parse-flags (sequences)
+ (goto-char (point-min))
+ (let (start end articles groups uidnext elems)
+ (dolist (elem sequences)
+ (destructuring-bind (group-sequence flag-sequence totalp group) elem
+ ;; The EXAMINE was successful.
+ (when (and (search-forward (format "\n%d OK " group-sequence) nil t)
+ (progn
+ (forward-line 1)
+ (setq start (point))
+ (if (re-search-backward "UIDNEXT \\([0-9]+\\)"
+ (or end (point-min)) t)
+ (setq uidnext (string-to-number (match-string 1)))
+ (setq uidnext nil))
+ (goto-char start))
+ ;; The UID FETCH FLAGS was successful.
+ (search-forward (format "\n%d OK " flag-sequence) nil t))
+ (setq end (point))
+ (goto-char start)
+ (while (re-search-forward "^\\* [0-9]+ FETCH (\\(.*\\))" end t)
+ (setq elems (nnimap-parse-line (match-string 1)))
+ (push (cons (string-to-number (cadr (member "UID" elems)))
+ (cadr (member "FLAGS" elems)))
+ articles))
+ (push (nconc (list group uidnext totalp) articles) groups)
+ (setq articles nil))))
+ groups))
+
+(defun nnimap-find-process-buffer (buffer)
+ (cadr (assoc buffer nnimap-connection-alist)))
+
+(defun nnimap-request-post (&optional server)
+ (setq nnimap-status-string "Read-only server")
+ nil)
-
-;;; Internal functions
-
-;;
-;; This is confusing.
-;;
-;; mark => read, tick, draft, reply etc
-;; flag => "\\Seen", "\\Flagged", "\\Draft", "gnus-expire" etc
-;; predicate => "SEEN", "FLAGGED", "DRAFT", "KEYWORD gnus-expire" etc
-;;
-;; Mark should not really contain 'read since it's not a "mark" in the Gnus
-;; world, but we cheat. Mark == gnus-article-mark-lists + '(read . read).
-;;
-
-(defconst nnimap-mark-to-predicate-alist
- (mapcar
- (lambda (pair) ; cdr is the mark
- (or (assoc (cdr pair)
- '((read . "SEEN")
- (tick . "FLAGGED")
- (draft . "DRAFT")
- (recent . "RECENT")
- (reply . "ANSWERED")))
- (cons (cdr pair)
- (format "KEYWORD gnus-%s" (symbol-name (cdr pair))))))
- (cons '(read . read) gnus-article-mark-lists)))
-
-(defun nnimap-mark-to-predicate (pred)
- "Convert a Gnus mark (a symbol such as read, tick, expire) to a IMAP predicate.
-This is a string such as \"SEEN\", \"FLAGGED\", \"KEYWORD gnus-expire\",
-to be used within a IMAP SEARCH query."
- (cdr (assq pred nnimap-mark-to-predicate-alist)))
-
-(defconst nnimap-mark-to-flag-alist
- (mapcar
- (lambda (pair)
- (or (assoc (cdr pair)
- '((read . "\\Seen")
- (tick . "\\Flagged")
- (draft . "\\Draft")
- (recent . "\\Recent")
- (reply . "\\Answered")))
- (cons (cdr pair)
- (format "gnus-%s" (symbol-name (cdr pair))))))
- (cons '(read . read) gnus-article-mark-lists)))
-
-(defun nnimap-mark-to-flag-1 (preds)
- (if (and (not (null preds)) (listp preds))
- (cons (nnimap-mark-to-flag (car preds))
- (nnimap-mark-to-flag (cdr preds)))
- (cdr (assoc preds nnimap-mark-to-flag-alist))))
-
-(defun nnimap-mark-to-flag (preds &optional always-list make-string)
- "Convert a Gnus mark (a symbol such as read, tick, expire) to a IMAP flag.
-This is a string such as \"\\Seen\", \"\\Flagged\", \"gnus-expire\", to
-be used in a STORE FLAGS command."
- (let ((result (nnimap-mark-to-flag-1 preds)))
- (setq result (if (and (or make-string always-list)
- (not (listp result)))
- (list result)
- result))
- (if make-string
- (mapconcat (lambda (flag)
- (if (listp flag)
- (mapconcat 'identity flag " ")
- flag))
- result " ")
- result)))
-
-(defun nnimap-mark-permanent-p (mark &optional group)
- "Return t if MARK can be permanently (between IMAP sessions) saved on articles, in GROUP."
- (imap-message-flag-permanent-p (nnimap-mark-to-flag mark)))
+(defun nnimap-possibly-change-group (group server)
+ (let ((open-result t))
+ (when (and server
+ (not (nnimap-server-opened server)))
+ (setq open-result (nnimap-open-server server)))
+ (cond
+ ((not open-result)
+ nil)
+ ((not group)
+ t)
+ (t
+ (with-current-buffer (nnimap-buffer)
+ (if (equal group (nnimap-group nnimap-object))
+ t
+ (let ((result (nnimap-command "SELECT %S" (utf7-encode group t))))
+ (when (car result)
+ (setf (nnimap-group nnimap-object) group)
+ result))))))))
+
+(defun nnimap-find-connection (buffer)
+ "Find the connection delivering to BUFFER."
+ (let ((entry (assoc buffer nnimap-connection-alist)))
+ (when entry
+ (if (and (buffer-name (cadr entry))
+ (get-buffer-process (cadr entry))
+ (memq (process-status (get-buffer-process (cadr entry)))
+ '(open run)))
+ (get-buffer-process (cadr entry))
+ (setq nnimap-connection-alist (delq entry nnimap-connection-alist))
+ nil))))
+
+(defvar nnimap-sequence 0)
+
+(defun nnimap-send-command (&rest args)
+ (process-send-string
+ (get-buffer-process (current-buffer))
+ (nnimap-log-command
+ (format "%d %s\r\n"
+ (incf nnimap-sequence)
+ (apply #'format args))))
+ nnimap-sequence)
+
+(defun nnimap-log-command (command)
+ (with-current-buffer (get-buffer-create "*imap log*")
+ (goto-char (point-max))
+ (insert (format-time-string "%H:%M:%S") " " command))
+ command)
+
+(defun nnimap-command (&rest args)
+ (erase-buffer)
+ (let* ((sequence (apply #'nnimap-send-command args))
+ (response (nnimap-get-response sequence)))
+ (if (equal (caar response) "OK")
+ (cons t response)
+ (nnheader-report 'nnimap "%s"
+ (mapconcat #'identity (car response) " "))
+ nil)))
+
+(defun nnimap-get-response (sequence)
+ (nnimap-wait-for-response sequence)
+ (nnimap-parse-response))
+
+(defun nnimap-wait-for-response (sequence &optional messagep)
+ (goto-char (point-max))
+ (while (or (bobp)
+ (progn
+ (forward-line -1)
+ (not (looking-at (format "^%d .*\n" sequence)))))
+ (when messagep
+ (message "Read %dKB" (/ (buffer-size) 1000)))
+ (nnheader-accept-process-output (get-buffer-process (current-buffer)))
+ (goto-char (point-max))))
+
+(defun nnimap-parse-response ()
+ (let ((lines (split-string (nnimap-last-response-string) "\r\n" t))
+ result)
+ (dolist (line lines)
+ (push (cdr (nnimap-parse-line line)) result))
+ ;; Return the OK/error code first, and then all the "continuation
+ ;; lines" afterwards.
+ (cons (pop result)
+ (nreverse result))))
+
+;; Parse an IMAP response line lightly. They look like
+;; "* OK [UIDVALIDITY 1164213559] UIDs valid", typically, so parse
+;; the lines into a list of strings and lists of string.
+(defun nnimap-parse-line (line)
+ (let (char result)
+ (with-temp-buffer
+ (insert line)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (if (eql (setq char (following-char)) ? )
+ (forward-char 1)
+ (push
+ (cond
+ ((eql char ?\[)
+ (split-string (buffer-substring
+ (1+ (point)) (1- (search-forward "]")))))
+ ((eql char ?\()
+ (split-string (buffer-substring
+ (1+ (point)) (1- (search-forward ")")))))
+ ((eql char ?\")
+ (forward-char 1)
+ (buffer-substring (point) (1- (search-forward "\""))))
+ (t
+ (buffer-substring (point) (if (search-forward " " nil t)
+ (1- (point))
+ (goto-char (point-max))))))
+ result)))
+ (nreverse result))))
+
+(defun nnimap-last-response-string ()
+ (save-excursion
+ (forward-line 1)
+ (let ((end (point)))
+ (forward-line -1)
+ (when (not (bobp))
+ (forward-line -1)
+ (while (and (not (bobp))
+ (eql (following-char) ?*))
+ (forward-line -1))
+ (unless (eql (following-char) ?*)
+ (forward-line 1)))
+ (buffer-substring (point) end))))
+
+(defun nnimap-get-responses (sequences)
+ (let (responses)
+ (dolist (sequence sequences)
+ (goto-char (point-min))
+ (when (re-search-forward (format "^%d " sequence) nil t)
+ (push (list sequence (nnimap-parse-response))
+ responses)))
+ responses))
+
+(defvar nnimap-incoming-split-list nil)
+
+(defun nnimap-fetch-inbox (articles)
+ (erase-buffer)
+ (nnimap-wait-for-response
+ (nnimap-send-command
+ "UID FETCH %s %s"
+ (nnimap-article-ranges articles)
+ (format "(UID %s%s)"
+ (format
+ (if (member "IMAP4REV1"
+ (nnimap-capabilities nnimap-object))
+ "BODY.PEEK[HEADER] BODY.PEEK"
+ "RFC822.PEEK"))
+ (if nnimap-split-download-body-default
+ ""
+ "[1]")))
+ t))
+
+(defun nnimap-split-incoming-mail ()
+ (with-current-buffer (nnimap-buffer)
+ (let ((nnimap-incoming-split-list nil)
+ (nnmail-split-methods nnimap-split-methods)
+ (nnmail-inhibit-default-split-group t)
+ (groups (nnimap-get-groups))
+ new-articles)
+ (erase-buffer)
+ (nnimap-command "SELECT %S" nnimap-inbox)
+ (setq new-articles (nnimap-new-articles (nnimap-get-flags "1:*")))
+ (when new-articles
+ (nnimap-fetch-inbox new-articles)
+ (nnimap-transform-split-mail)
+ (nnheader-ms-strip-cr)
+ (nnmail-cache-open)
+ (nnmail-split-incoming (current-buffer)
+ #'nnimap-save-mail-spec
+ nil nil
+ #'nnimap-dummy-active-number)
+ (when nnimap-incoming-split-list
+ (let ((specs (nnimap-make-split-specs nnimap-incoming-split-list))
+ sequences)
+ ;; Create any groups that doesn't already exist on the
+ ;; server first.
+ (dolist (spec specs)
+ (unless (member (car spec) groups)
+ (nnimap-command "CREATE %S" (utf7-encode (car spec) t))))
+ ;; Then copy over all the messages.
+ (erase-buffer)
+ (dolist (spec specs)
+ (let ((group (car spec))
+ (ranges (cdr spec)))
+ (push (list (nnimap-send-command "UID COPY %s %S"
+ (nnimap-article-ranges ranges)
+ (utf7-encode group t))
+ ranges)
+ sequences)))
+ ;; Wait for the last COPY response...
+ (when sequences
+ (nnimap-wait-for-response (caar sequences))
+ ;; And then mark the successful copy actions as deleted,
+ ;; and possibly expunge them.
+ (nnimap-mark-and-expunge-incoming
+ (nnimap-parse-copied-articles sequences)))))))))
+
+(defun nnimap-mark-and-expunge-incoming (range)
+ (when range
+ (setq range (nnimap-article-ranges range))
+ (nnimap-send-command
+ "UID STORE %s +FLAGS.SILENT (\\Deleted)" range)
+ (cond
+ ;; If the server supports it, we now delete the message we have
+ ;; just copied over.
+ ((member "UIDPLUS" (nnimap-capabilities nnimap-object))
+ (nnimap-send-command "UID EXPUNGE %s" range))
+ ;; If it doesn't support UID EXPUNGE, then we only expunge if the
+ ;; user has configured it.
+ (nnimap-expunge-inbox
+ (nnimap-send-command "EXPUNGE")))))
+
+(defun nnimap-parse-copied-articles (sequences)
+ (let (sequence copied range)
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([0-9]+\\) OK " nil t)
+ (setq sequence (string-to-number (match-string 1)))
+ (when (setq range (cadr (assq sequence sequences)))
+ (push (gnus-uncompress-range range) copied)))
+ (gnus-compress-sequence (sort (apply #'nconc copied) #'<))))
+
+(defun nnimap-new-articles (flags)
+ (let (new)
+ (dolist (elem flags)
+ (when (or (null (cdr elem))
+ (and (not (member "\\Deleted" (cdr elem)))
+ (not (member "\\Seen" (cdr elem)))))
+ (push (car elem) new)))
+ (gnus-compress-sequence (nreverse new))))
+
+(defun nnimap-make-split-specs (list)
+ (let ((specs nil)
+ entry)
+ (dolist (elem list)
+ (destructuring-bind (article spec) elem
+ (dolist (group (delete nil (mapcar #'car spec)))
+ (unless (setq entry (assoc group specs))
+ (push (setq entry (list group)) specs))
+ (setcdr entry (cons article (cdr entry))))))
+ (dolist (entry specs)
+ (setcdr entry (gnus-compress-sequence (sort (cdr entry) #'<))))
+ specs))
+
+(defun nnimap-transform-split-mail ()
+ (goto-char (point-min))
+ (let (article bytes)
+ (block nil
+ (while (not (eobp))
+ (while (not (looking-at "^\\* [0-9]+ FETCH.*UID \\([0-9]+\\)"))
+ (delete-region (point) (progn (forward-line 1) (point)))
+ (when (eobp)
+ (return)))
+ (setq article (match-string 1)
+ bytes (nnimap-get-length))
+ (delete-region (line-beginning-position) (line-end-position))
+ ;; Insert MMDF separator, and a way to remember what this
+ ;; article UID is.
+ (insert (format "\^A\^A\^A\^A\n\nX-nnimap-article: %s" article))
+ (forward-char (1+ bytes))
+ (setq bytes (nnimap-get-length))
+ (delete-region (line-beginning-position) (line-end-position))
+ (forward-char (1+ bytes))
+ (delete-region (line-beginning-position) (line-end-position))))))
+
+(defun nnimap-dummy-active-number (group &optional server)
+ 1)
+
+(defun nnimap-save-mail-spec (group-art &optional server full-nov)
+ (let (article)
+ (goto-char (point-min))
+ (if (not (re-search-forward "X-nnimap-article: \\([0-9]+\\)" nil t))
+ (error "Invalid nnimap mail")
+ (setq article (string-to-number (match-string 1))))
+ (push (list article group-art)
+ nnimap-incoming-split-list)))
(provide 'nnimap)
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 6096c6fb37..27610e7aba 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -744,8 +744,7 @@ and show thread that contains this article."
nnir-artlist
;; Cache miss.
(setq nnir-artlist (nnir-run-query group)))
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(if (zerop (length nnir-artlist))
(progn
(setq nnir-current-query nil
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index b7d834ecd8..3e6cee8252 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -614,6 +614,7 @@ using different case (i.e. mailing-list@domain vs Mailing-List@Domain)."
(defvar nnmail-split-tracing nil)
(defvar nnmail-split-trace nil)
+(defvar nnmail-inhibit-default-split-group nil)
@@ -674,8 +675,7 @@ using different case (i.e. mailing-list@domain vs Mailing-List@Domain)."
"Returns an assoc of group names and active ranges.
nn*-request-list should have been called before calling this function."
;; Go through all groups from the active list.
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(nnmail-parse-active)))
(defun nnmail-parse-active ()
@@ -1058,7 +1058,9 @@ If SOURCE is a directory spec, try to return the group name component."
(defun nnmail-split-incoming (incoming func &optional exit-func
group artnum-func)
"Go through the entire INCOMING file and pick out each individual mail.
-FUNC will be called with the buffer narrowed to each mail."
+FUNC will be called with the buffer narrowed to each mail.
+INCOMING can also be a buffer object. In that case, the mail
+will be copied over from that buffer."
(let ( ;; If this is a group-specific split, we bind the split
;; methods to just this group.
(nnmail-split-methods (if (and group
@@ -1066,12 +1068,13 @@ FUNC will be called with the buffer narrowed to each mail."
(list (list group ""))
nnmail-split-methods))
(nnmail-group-names-not-encoded-p t))
- (save-excursion
- ;; Insert the incoming file.
- (set-buffer (get-buffer-create nnmail-article-buffer))
+ ;; Insert the incoming file.
+ (with-current-buffer (get-buffer-create nnmail-article-buffer)
(erase-buffer)
- (let ((coding-system-for-read nnmail-incoming-coding-system))
- (mm-insert-file-contents incoming))
+ (if (bufferp incoming)
+ (insert-buffer-substring incoming)
+ (let ((coding-system-for-read nnmail-incoming-coding-system))
+ (mm-insert-file-contents incoming)))
(prog1
(if (zerop (buffer-size))
0
@@ -1100,15 +1103,15 @@ FUNC will be called with the group name to determine the article number."
(obuf (current-buffer))
group-art method grp)
(if (and (sequencep methods)
- (= (length methods) 1))
+ (= (length methods) 1)
+ (not nnmail-inhibit-default-split-group))
;; If there is only just one group to put everything in, we
;; just return a list with just this one method in.
(setq group-art
(list (cons (caar methods) (funcall func (caar methods)))))
;; We do actual comparison.
- (save-excursion
- ;; Copy the article into the work buffer.
- (set-buffer nntp-server-buffer)
+ ;; Copy the article into the work buffer.
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(insert-buffer-substring obuf)
;; Narrow to headers.
@@ -1149,7 +1152,8 @@ FUNC will be called with the group name to determine the article number."
;; just call this function here and use the
;; result.
(or (funcall nnmail-split-methods)
- '("bogus"))
+ (and (not nnmail-inhibit-default-split-group)
+ '("bogus")))
(error
(nnheader-message
5 "Error in `nnmail-split-methods'; using `bogus' mail group: %S" error-info)
@@ -1194,12 +1198,14 @@ FUNC will be called with the group name to determine the article number."
group-art))
;; This is the final group, which is used as a
;; catch-all.
- (unless group-art
+ (when (and (not group-art)
+ (not nnmail-inhibit-default-split-group))
(setq group-art
(list (cons (car method)
(funcall func (car method))))))))
;; Fall back on "bogus" if all else fails.
- (unless group-art
+ (when (and (not group-art)
+ (not nnmail-inhibit-default-split-group))
(setq group-art (list (cons "bogus" (funcall func "bogus"))))))
;; Produce a trace if non-empty.
(when (and trace nnmail-split-trace)
@@ -1572,10 +1578,9 @@ See the documentation for the variable `nnmail-split-fancy' for details."
(and nnmail-cache-buffer
(buffer-name nnmail-cache-buffer)))
() ; The buffer is open.
- (save-excursion
- (set-buffer
+ (with-current-buffer
(setq nnmail-cache-buffer
- (get-buffer-create " *nnmail message-id cache*")))
+ (get-buffer-create " *nnmail message-id cache*"))
(gnus-add-buffer)
(when (file-exists-p nnmail-message-id-cache-file)
(nnheader-insert-file-contents nnmail-message-id-cache-file))
@@ -1587,8 +1592,7 @@ See the documentation for the variable `nnmail-split-fancy' for details."
nnmail-treat-duplicates
(buffer-name nnmail-cache-buffer)
(buffer-modified-p nnmail-cache-buffer))
- (save-excursion
- (set-buffer 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)
@@ -1623,8 +1627,7 @@ See the documentation for the variable `nnmail-split-fancy' for details."
;; pass the first (of possibly >1) group which matches. -Josh
(unless (gnus-buffer-live-p nnmail-cache-buffer)
(nnmail-cache-open))
- (save-excursion
- (set-buffer nnmail-cache-buffer)
+ (with-current-buffer nnmail-cache-buffer
(goto-char (point-max))
(if (and grp (not (string= "" grp))
(gnus-methods-equal-p gnus-command-method
@@ -1657,8 +1660,7 @@ See the documentation for the variable `nnmail-split-fancy' for details."
;; cache.
(defun nnmail-cache-fetch-group (id)
(when (and nnmail-treat-duplicates nnmail-cache-buffer)
- (save-excursion
- (set-buffer nnmail-cache-buffer)
+ (with-current-buffer nnmail-cache-buffer
(goto-char (point-max))
(when (search-backward id nil t)
(beginning-of-line)
@@ -1702,8 +1704,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
(defun nnmail-cache-id-exists-p (id)
(when nnmail-treat-duplicates
- (save-excursion
- (set-buffer nnmail-cache-buffer)
+ (with-current-buffer nnmail-cache-buffer
(goto-char (point-max))
(search-backward id nil t))))
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 827eafdc7e..b79e7103ce 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -208,20 +208,16 @@ by nnmaildir-request-article.")
(eval param))
(defmacro nnmaildir--with-nntp-buffer (&rest body)
- `(save-excursion
- (set-buffer nntp-server-buffer)
+ `(with-current-buffer nntp-server-buffer
,@body))
(defmacro nnmaildir--with-work-buffer (&rest body)
- `(save-excursion
- (set-buffer (get-buffer-create " *nnmaildir work*"))
+ `(with-current-buffer (get-buffer-create " *nnmaildir work*")
,@body))
(defmacro nnmaildir--with-nov-buffer (&rest body)
- `(save-excursion
- (set-buffer (get-buffer-create " *nnmaildir nov*"))
+ `(with-current-buffer (get-buffer-create " *nnmaildir nov*")
,@body))
(defmacro nnmaildir--with-move-buffer (&rest body)
- `(save-excursion
- (set-buffer (get-buffer-create " *nnmaildir move*"))
+ `(with-current-buffer (get-buffer-create " *nnmaildir move*")
,@body))
(defmacro nnmaildir--subdir (dir subdir)
@@ -1249,8 +1245,7 @@ by nnmaildir-request-article.")
(setf (nnmaildir--srv-error nnmaildir--cur-server)
"Article has expired")
(throw 'return nil))
- (save-excursion
- (set-buffer (or to-buffer nntp-server-buffer))
+ (with-current-buffer (or to-buffer nntp-server-buffer)
(erase-buffer)
(nnheader-insert-file-contents nnmaildir-article-file-name))
(cons gname num-msgid))))
@@ -1289,8 +1284,7 @@ by nnmaildir-request-article.")
(setf (nnmaildir--srv-error nnmaildir--cur-server)
(concat "File exists: " tmpfile))
(throw 'return nil))
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(gmm-write-region (point-min) (point-max) tmpfile nil 'no-message nil
'excl))
(unix-sync) ;; no fsync :(
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index 04db76b942..b43a83e3a3 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -445,8 +445,7 @@ Other back ends might or might not work.")
nil)
((not query)
;; No query -> return empty group
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(insert (concat "211 0 1 0 " group))
t))
@@ -501,9 +500,9 @@ Other back ends might or might not work.")
(nnmairix-request-group-with-article-number-correction
folder qualgroup)))
((and (= rval 1)
- (save-excursion (set-buffer nnmairix-mairix-output-buffer)
- (goto-char (point-min))
- (looking-at "^Matched 0 messages")))
+ (with-current-buffer nnmairix-mairix-output-buffer
+ (goto-char (point-min))
+ (looking-at "^Matched 0 messages")))
;; No messages found -> return empty group
(nnheader-message 5 "Mairix: No matches found.")
(set-buffer nntp-server-buffer)
@@ -584,8 +583,7 @@ Other back ends might or might not work.")
(when server (nnmairix-open-server server))
(if (nnmairix-call-backend "request-list" nnmairix-backend-server)
(let (cpoint cur qualgroup folder)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(setq cpoint (point))
(while (re-search-forward nnmairix-group-regexp (point-max) t)
@@ -699,8 +697,7 @@ Other back ends might or might not work.")
(when (or (eq nnmairix-propagate-marks-upon-close t)
(and (eq nnmairix-propagate-marks-upon-close 'ask)
(y-or-n-p "Propagate marks to original articles? ")))
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(nnmairix-propagate-marks)
;; update mairix group
(gnus-group-jump-to-group qualgroup)
@@ -998,8 +995,7 @@ with m:msgid of the current article and enabled threads."
(if server
(if (gnus-buffer-live-p gnus-article-buffer)
(progn
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(gnus-summary-toggle-header 1)
(setq mid (message-fetch-field "Message-ID")))
(while (string-match "[<>]" mid)
@@ -1021,8 +1017,7 @@ f:current_from."
(if server
(if (gnus-buffer-live-p gnus-article-buffer)
(progn
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(gnus-summary-toggle-header 1)
(setq from (cadr (gnus-extract-address-components
(gnus-fetch-field "From"))))
@@ -1046,8 +1041,7 @@ before deleting a group on the back end. SERVER specifies nnmairix server."
(when (nnmairix-call-backend
"request-list" nnmairix-backend-server)
(let (cur qualgroup folder)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(while (re-search-forward nnmairix-group-regexp (point-max) t)
(setq cur (match-string 0)
@@ -1152,8 +1146,7 @@ nnmairix server. Only marks from current session will be set."
(push (list (car ogroup) (list (list number) (nth 1 mid-marks) (nth 2 mid-marks)))
number-cache)))))
;; now we set the marks
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(nnheader-message 5 "nnmairix: Propagating marks...")
(dolist (cur number-cache)
(setq method (gnus-find-method-for-group (car cur)))
@@ -1272,9 +1265,8 @@ Marks propagation has to be enabled for this to work."
"Call mairix binary with COMMAND, using FOLDER and SEARCHQUERY.
If THREADS is non-nil, enable full threads."
(let ((args (cons (car command) '(nil t nil))))
- (save-excursion
- (set-buffer
- (get-buffer-create nnmairix-mairix-output-buffer))
+ (with-current-buffer
+ (get-buffer-create nnmairix-mairix-output-buffer)
(erase-buffer)
(when (> (length command) 1)
(setq args (append args (cdr command))))
@@ -1291,9 +1283,8 @@ If THREADS is non-nil, enable full threads."
(defun nnmairix-call-mairix-binary-raw (command query)
"Call mairix binary with COMMAND and QUERY in raw mode."
(let ((args (cons (car command) '(nil t nil))))
- (save-excursion
- (set-buffer
- (get-buffer-create nnmairix-mairix-output-buffer))
+ (with-current-buffer
+ (get-buffer-create nnmairix-mairix-output-buffer)
(erase-buffer)
(when (> (length command) 1)
(setq args (append args (cdr command))))
@@ -1430,8 +1421,7 @@ MAIRIXGROUP. NUMC contains values for article number correction."
(corr (not (zerop numc)))
(name (buffer-name nntp-server-buffer))
header cur xref)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(erase-buffer)
(set-buffer nntp-server-buffer)
(goto-char (point-min))
@@ -1621,8 +1611,7 @@ search in raw mode."
(let ((server (nth 1 gnus-current-select-method))
mid rval group allgroups)
;; get message id
- (save-excursion
- (set-buffer gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
(gnus-summary-toggle-header 1)
(setq mid (message-fetch-field "Message-ID"))
;; first check the registry (if available)
@@ -1678,8 +1667,7 @@ SERVER."
(if (zerop (nnmairix-call-mairix-binary-raw
(split-string nnmairix-mairix-command)
(list (concat "m:" mid))))
- (save-excursion
- (set-buffer nnmairix-mairix-output-buffer)
+ (with-current-buffer nnmairix-mairix-output-buffer
(goto-char (point-min))
(while (re-search-forward "^/.*$" nil t)
(push (nnmairix-get-group-from-file-path (match-string 0))
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index 7d71dc1c1e..4b01bfa5c6 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -79,8 +79,7 @@
(nnoo-define-basics nnmbox)
(deffoo nnmbox-retrieve-headers (sequence &optional newsgroup server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let ((number (length sequence))
(count 0)
@@ -149,8 +148,7 @@
(deffoo nnmbox-request-article (article &optional newsgroup server buffer)
(nnmbox-possibly-change-newsgroup newsgroup server)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(when (nnmbox-find-article article)
(let (start stop)
(re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
@@ -208,8 +206,7 @@
(nnmail-get-new-mail
'nnmbox
(lambda ()
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(nnmbox-save-buffer)))
(file-name-directory nnmbox-mbox-file)
group
@@ -253,8 +250,7 @@
rest)
(nnmail-activate 'nnmbox)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(while (and articles is-old)
(when (nnmbox-find-article (car articles))
(if (setq is-old
@@ -292,8 +288,7 @@
result)
(and
(nnmbox-request-article article group server)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(erase-buffer)
(insert-buffer-substring nntp-server-buffer)
(goto-char (point-min))
@@ -364,8 +359,7 @@
(deffoo nnmbox-request-replace-article (article group buffer)
(nnmbox-possibly-change-newsgroup group)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(if (not (nnmbox-find-article article))
nil
(nnmbox-delete-mail t t)
@@ -391,8 +385,7 @@
;; Delete all articles in GROUP.
(if (not force)
() ; Don't delete the articles.
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(goto-char (point-min))
;; Delete all articles in this group.
(let ((ident (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":"))
@@ -412,8 +405,7 @@
(deffoo nnmbox-request-rename-group (group new-name &optional server)
(nnmbox-possibly-change-newsgroup group server)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(goto-char (point-min))
(let ((ident (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":"))
(new-ident (concat "\nX-Gnus-Newsgroup: " new-name ":"))
@@ -633,8 +625,7 @@
(nnmbox-create-mbox)
(if (and nnmbox-mbox-buffer
(buffer-name nnmbox-mbox-buffer)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
+ (with-current-buffer nnmbox-mbox-buffer
(= (buffer-size) (nnheader-file-size nnmbox-mbox-file))))
()
(save-excursion
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 6d676bb851..5d62192819 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -160,8 +160,7 @@ non-nil.")
(deffoo nnml-retrieve-headers (sequence &optional group server fetch-old)
(when (nnml-possibly-change-directory group server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let* ((file nil)
(number (length sequence))
@@ -405,8 +404,7 @@ non-nil.")
(let (nnml-current-directory
nnml-current-group
nnml-article-file-alist)
- (save-excursion
- (set-buffer buf)
+ (with-current-buffer buf
(insert-buffer-substring nntp-server-buffer)
(setq result (eval accept-form))
(kill-buffer (current-buffer))
@@ -462,8 +460,7 @@ non-nil.")
(deffoo nnml-request-replace-article (article group buffer)
(nnml-possibly-change-directory group)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(nnml-possibly-create-directory group)
(let ((chars (nnmail-insert-lines))
(art (concat (int-to-string article) "\t"))
@@ -478,8 +475,7 @@ non-nil.")
t)
(setq headers (nnml-parse-head chars article))
;; Replace the NOV line in the NOV file.
- (save-excursion
- (set-buffer (nnml-open-nov group))
+ (with-current-buffer (nnml-open-nov group)
(goto-char (point-min))
(if (or (looking-at art)
(search-forward (concat "\n" art) nil t))
@@ -614,8 +610,7 @@ non-nil.")
;; Find an article number in the current group given the Message-ID.
(defun nnml-find-group-number (id server)
- (save-excursion
- (set-buffer (get-buffer-create " *nnml id*"))
+ (with-current-buffer (get-buffer-create " *nnml id*")
(let ((alist nnml-group-alist)
number)
;; We want to look through all .overview files, but we want to
@@ -657,8 +652,7 @@ non-nil.")
nil
(let ((nov (expand-file-name nnml-nov-file-name nnml-current-directory)))
(when (file-exists-p nov)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(nnheader-insert-file-contents nov)
(if (and fetch-old
@@ -804,16 +798,14 @@ article number. This function is called narrowed to an article."
(defun nnml-add-incremental-nov (group article headers)
"Add a nov line for the GROUP nov headers, incrementally."
- (save-excursion
- (set-buffer (nnml-open-incremental-nov group))
+ (with-current-buffer (nnml-open-incremental-nov group)
(goto-char (point-max))
(mail-header-set-number headers article)
(nnheader-insert-nov headers)))
(defun nnml-add-nov (group article headers)
"Add a nov line for the GROUP base."
- (save-excursion
- (set-buffer (nnml-open-nov group))
+ (with-current-buffer (nnml-open-nov group)
(goto-char (point-max))
(mail-header-set-number headers article)
(nnheader-insert-nov headers)))
@@ -844,8 +836,7 @@ article number. This function is called narrowed to an article."
"")
decoded)))
(file-name-coding-system nnmail-pathname-coding-system))
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(set (make-local-variable 'nnml-nov-buffer-file-name)
(nnmail-group-pathname decoded nnml-directory nnml-nov-file-name))
(erase-buffer)
@@ -942,9 +933,8 @@ Unless no-active is non-nil, update the active file too."
(nov (concat dir nnml-nov-file-name))
(nov-buffer (get-buffer-create " *nov*"))
chars file headers)
- (save-excursion
+ (with-current-buffer nov-buffer
;; Init the nov buffer.
- (set-buffer nov-buffer)
(buffer-disable-undo)
(erase-buffer)
(set-buffer nntp-server-buffer)
@@ -964,20 +954,17 @@ Unless no-active is non-nil, update the active file too."
(unless (zerop (buffer-size))
(goto-char (point-min))
(setq headers (nnml-parse-head chars (caar files)))
- (save-excursion
- (set-buffer nov-buffer)
+ (with-current-buffer nov-buffer
(goto-char (point-max))
(nnheader-insert-nov headers)))
(widen))
(setq files (cdr files)))
- (save-excursion
- (set-buffer nov-buffer)
+ (with-current-buffer nov-buffer
(nnmail-write-region (point-min) (point-max) nov nil 'nomesg)
(kill-buffer (current-buffer))))))
(defun nnml-nov-delete-article (group article)
- (save-excursion
- (set-buffer (nnml-open-nov group))
+ (with-current-buffer (nnml-open-nov group)
(when (nnheader-find-nov-line article)
(delete-region (point) (progn (forward-line 1) (point)))
(when (bobp)
@@ -1260,8 +1247,7 @@ Use the nov database for the current group if available."
(gnus-info-set-marks info newmarks))
;; 3/ Update the NOV entry for this article:
(unless nnml-nov-is-evil
- (save-excursion
- (set-buffer (nnml-open-nov group))
+ (with-current-buffer (nnml-open-nov group)
(when (nnheader-find-nov-line old-number)
;; Replace the article number:
(looking-at old-number-string)
diff --git a/lisp/gnus/nnnil.el b/lisp/gnus/nnnil.el
index f6bc35aec3..dd5e9841c1 100644
--- a/lisp/gnus/nnnil.el
+++ b/lisp/gnus/nnnil.el
@@ -58,8 +58,7 @@
(defun nnnil-request-group (group &optional server fast)
(let (deactivate-mark)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(insert "411 no such news group\n")))
(setq nnnil-status-string "No such group")
diff --git a/lisp/gnus/nnspool.el b/lisp/gnus/nnspool.el
index cdf2b829ec..ee1e36f55c 100644
--- a/lisp/gnus/nnspool.el
+++ b/lisp/gnus/nnspool.el
@@ -109,8 +109,7 @@ there.")
(deffoo nnspool-retrieve-headers (articles &optional group server fetch-old)
"Retrieve the headers of ARTICLES."
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(when (nnspool-possibly-change-directory group)
(let* ((number (length articles))
@@ -209,8 +208,7 @@ there.")
(nnspool-possibly-change-directory group)
(let ((res (nnspool-request-article id)))
(when res
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
(delete-region (point-min) (point)))
@@ -221,8 +219,7 @@ there.")
(nnspool-possibly-change-directory group)
(let ((res (nnspool-request-article id)))
(when res
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
(delete-region (1- (point)) (point-max)))
@@ -343,8 +340,7 @@ there.")
;;; Internal functions.
(defun nnspool-inews-sentinel (proc status)
- (save-excursion
- (set-buffer (process-buffer proc))
+ (with-current-buffer (process-buffer proc)
(goto-char (point-min))
(if (or (zerop (buffer-size))
(search-forward "spooled" nil t))
@@ -367,8 +363,7 @@ there.")
last)
(if (not (file-exists-p nov))
()
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(if nnspool-sift-nov-with-sed
(nnspool-sift-nov-with-sed articles nov)
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 3cdd63084e..59f803d8c6 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -1014,7 +1014,8 @@ command whose response triggered the error."
(unless (assq 'nntp-address defs)
(setq defs (append defs (list (list 'nntp-address server)))))
(nnoo-change-server 'nntp server defs)
- (unless connectionless
+ (if connectionless
+ t
(or (nntp-find-connection nntp-server-buffer)
(nntp-open-connection nntp-server-buffer)))))
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index c94d1837fa..18faa23a80 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -93,8 +93,7 @@ component group will show up when you enter the virtual group.")
(deffoo nnvirtual-retrieve-headers (articles &optional newsgroup
server fetch-old)
(when (nnvirtual-possibly-change-server server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(if (stringp (car articles))
'headers
@@ -170,8 +169,7 @@ component group will show up when you enter the virtual group.")
;; the nntp-server-buffer, which is where Gnus expects to find
;; them.
(prog1
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(insert-buffer-substring vbuf)
;; FIX FIX FIX, we should be able to sort faster than
@@ -215,8 +213,7 @@ component group will show up when you enter the virtual group.")
(t
(setq nnvirtual-last-accessed-component-group cgroup)
(if buffer
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
;; We bind this here to avoid double decoding.
(let ((gnus-article-decode-hook nil))
(gnus-request-article-this-buffer (cdr amap) cgroup)))
@@ -335,8 +332,7 @@ component group will show up when you enter the virtual group.")
(when (not (numberp (gnus-group-unread g)))
(gnus-activate-group g)))
nnvirtual-component-groups)
- (save-excursion
- (set-buffer gnus-group-buffer)
+ (with-current-buffer gnus-group-buffer
(gnus-group-catchup-current nil all)))))
diff --git a/lisp/gnus/nnweb.el b/lisp/gnus/nnweb.el
index 3b4f71c80a..e6289c57bc 100644
--- a/lisp/gnus/nnweb.el
+++ b/lisp/gnus/nnweb.el
@@ -104,8 +104,7 @@ Valid types include `google', `dejanews', and `gmane'.")
(deffoo nnweb-retrieve-headers (articles &optional group server fetch-old)
(nnweb-possibly-change-server group server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(erase-buffer)
(let (article header)
(mm-with-unibyte-current-buffer
@@ -147,16 +146,14 @@ Valid types include `google', `dejanews', and `gmane'.")
(deffoo nnweb-close-group (group &optional server)
(nnweb-possibly-change-server group server)
(when (gnus-buffer-live-p nnweb-buffer)
- (save-excursion
- (set-buffer nnweb-buffer)
+ (with-current-buffer nnweb-buffer
(set-buffer-modified-p nil)
(kill-buffer nnweb-buffer)))
t)
(deffoo nnweb-request-article (article &optional group server buffer)
(nnweb-possibly-change-server group server)
- (save-excursion
- (set-buffer (or buffer nntp-server-buffer))
+ (with-current-buffer (or buffer nntp-server-buffer)
(let* ((header (cadr (assq article nnweb-articles)))
(url (and header (mail-header-xref header))))
(when (or (and url
@@ -185,16 +182,14 @@ Valid types include `google', `dejanews', and `gmane'.")
(deffoo nnweb-close-server (&optional server)
(when (and (nnweb-server-opened server)
(gnus-buffer-live-p nnweb-buffer))
- (save-excursion
- (set-buffer nnweb-buffer)
+ (with-current-buffer nnweb-buffer
(set-buffer-modified-p nil)
(kill-buffer nnweb-buffer)))
(nnoo-close-server 'nnweb server))
(deffoo nnweb-request-list (&optional server)
(nnweb-possibly-change-server nil server)
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (with-current-buffer nntp-server-buffer
(nnmail-generate-active (list (assoc server nnweb-group-alist)))
t))
@@ -402,8 +397,7 @@ Valid types include `google', `dejanews', and `gmane'.")
(defun nnweb-google-create-mapping ()
"Perform the search and create a number-to-url alist."
- (save-excursion
- (set-buffer nnweb-buffer)
+ (with-current-buffer nnweb-buffer
(erase-buffer)
(nnheader-message 7 "Searching google...")
(when (funcall (nnweb-definition 'search) nnweb-search)
@@ -459,8 +453,7 @@ Valid types include `google', `dejanews', and `gmane'.")
;;;
(defun nnweb-gmane-create-mapping ()
"Perform the search and create a number-to-url alist."
- (save-excursion
- (set-buffer nnweb-buffer)
+ (with-current-buffer nnweb-buffer
(let ((case-fold-search t)
(active (or (cadr (assoc nnweb-group nnweb-group-alist))
(cons 1 0)))
diff --git a/lisp/gnus/pop3.el b/lisp/gnus/pop3.el
index 950cae25c4..63ed8004a9 100644
--- a/lisp/gnus/pop3.el
+++ b/lisp/gnus/pop3.el
@@ -279,9 +279,9 @@ Returns the process associated with the connection."
(let ((coding-system-for-read 'binary)
(coding-system-for-write 'binary)
process)
- (with-current-buffer
- (get-buffer-create (concat " trace of POP session to "
- mailhost))
+ (save-excursion
+ (set-buffer (get-buffer-create (concat " trace of POP session to "
+ mailhost)))
(erase-buffer)
(setq pop3-read-point (point-min))
(setq process
@@ -353,7 +353,8 @@ Returns the process associated with the connection."
Return the response string if optional second argument is non-nil."
(let ((case-fold-search nil)
match-end)
- (with-current-buffer (process-buffer process)
+ (save-excursion
+ (set-buffer (process-buffer process))
(goto-char pop3-read-point)
(while (and (memq (process-status process) '(open run))
(not (search-forward "\r\n" nil t)))
@@ -510,7 +511,8 @@ Otherwise, return the size of the message-id MSG"
(if msg
(string-to-number (nth 2 (split-string response " ")))
(let ((start pop3-read-point) end)
- (with-current-buffer (process-buffer process)
+ (save-excursion
+ (set-buffer (process-buffer process))
(while (not (re-search-forward "^\\.\r\n" nil t))
(pop3-accept-process-output process)
(goto-char start))
@@ -528,7 +530,8 @@ Otherwise, return the size of the message-id MSG"
(pop3-send-command process (format "RETR %s" msg))
(pop3-read-response process)
(let ((start pop3-read-point) end)
- (with-current-buffer (process-buffer process)
+ (save-excursion
+ (set-buffer (process-buffer process))
(while (not (re-search-forward "^\\.\r\n" nil t))
(pop3-accept-process-output process)
(goto-char start))
@@ -544,7 +547,8 @@ Otherwise, return the size of the message-id MSG"
(setq end (point-marker))
(pop3-clean-region start end)
(pop3-munge-message-separator start end)
- (with-current-buffer crashbuf
+ (save-excursion
+ (set-buffer crashbuf)
(erase-buffer))
(copy-to-buffer crashbuf start end)
(delete-region start end)
@@ -581,7 +585,8 @@ and close the connection."
(pop3-send-command process "QUIT")
(pop3-read-response process t)
(if process
- (with-current-buffer (process-buffer process)
+ (save-excursion
+ (set-buffer (process-buffer process))
(goto-char (point-max))
(delete-process process))))
diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el
index d836f32016..a266819946 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -708,8 +708,7 @@ The following commands are available:
"Go to the SMIME buffer."
(interactive)
(unless (get-buffer smime-buffer)
- (save-excursion
- (set-buffer (get-buffer-create smime-buffer))
+ (with-current-buffer (get-buffer-create smime-buffer)
(smime-mode)))
(smime-draw-buffer)
(switch-to-buffer smime-buffer))
diff --git a/lisp/gnus/spam-report.el b/lisp/gnus/spam-report.el
index 0e32e93404..e73444e85c 100644
--- a/lisp/gnus/spam-report.el
+++ b/lisp/gnus/spam-report.el
@@ -109,8 +109,7 @@ Reports is as ham when HAM is set."
;; select this particular article
(gnus-summary-select-article nil nil nil article)
;; resend it to the destination address
- (save-excursion
- (set-buffer gnus-original-article-buffer)
+ (with-current-buffer gnus-original-article-buffer
(message-resend spam-report-resend-to))))
(defun spam-report-resend-ham (articles)
@@ -292,8 +291,7 @@ symbol `ask', query before flushing the queue file."
(gnus-message 7 "Processing requests using `%s'."
spam-report-url-ping-function))
(or file (setq file spam-report-requests-file))
- (save-excursion
- (set-buffer (find-file-noselect file))
+ (with-current-buffer (find-file-noselect file)
(goto-char (point-min))
(while (and (not (eobp))
(re-search-forward
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index d079be2fcd..b7908e5507 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -1605,8 +1605,7 @@ to find it out)."
article))))
(defun spam-fetch-article-header (article)
- (save-excursion
- (set-buffer gnus-summary-buffer)
+ (with-current-buffer gnus-summary-buffer
(gnus-read-header article)
(nth 3 (assq article gnus-newsgroup-data))))
;;}}}
@@ -2172,8 +2171,7 @@ See `spam-ifile-database'."
(with-temp-buffer
(let ((temp-buffer-name (buffer-name))
(db-param (spam-get-ifile-database-parameter)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(apply 'call-process-region
(point-min) (point-max) spam-ifile-program
nil temp-buffer-name nil "-c"
@@ -2318,9 +2316,8 @@ With a non-nil REMOVE, remove the ADDRESSES."
;; else, we have a list of addresses here
(unless (file-exists-p (file-name-directory file))
(make-directory (file-name-directory file) t))
- (save-excursion
- (set-buffer
- (find-file-noselect file))
+ (with-current-buffer
+ (find-file-noselect file)
(dolist (a addresses)
(when (stringp a)
(goto-char (point-min))
@@ -2521,8 +2518,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
return)
(with-temp-buffer
(let ((temp-buffer-name (buffer-name)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(apply 'call-process-region
(point-min) (point-max)
spam-bogofilter-program
@@ -2579,8 +2575,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
(let ((article-buffer-name (buffer-name)))
(with-temp-buffer
(let ((temp-buffer-name (buffer-name)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(let ((status
(apply 'call-process-region
(point-min) (point-max)
@@ -2656,8 +2651,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
(let ((article-buffer-name (buffer-name)))
(with-temp-buffer
(let ((temp-buffer-name (buffer-name)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(apply 'call-process-region
(point-min) (point-max) spam-assassin-program
nil temp-buffer-name nil spam-spamassassin-arguments))
@@ -2691,8 +2685,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
;; group the articles into mbox format
(dolist (article articles)
(let (article-string)
- (save-excursion
- (set-buffer summary-buffer-name)
+ (with-current-buffer summary-buffer-name
(setq article-string (spam-get-article-as-string article)))
(when (stringp article-string)
(insert "From \n") ; mbox separator (sa-learn only checks the
@@ -2755,8 +2748,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
return)
(with-temp-buffer
(let ((temp-buffer-name (buffer-name)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(apply 'call-process-region
(point-min) (point-max)
spam-bsfilter-program
@@ -2841,8 +2833,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
return)
(with-temp-buffer
(let ((temp-buffer-name (buffer-name)))
- (save-excursion
- (set-buffer article-buffer-name)
+ (with-current-buffer article-buffer-name
(apply 'call-process-region
(point-min) (point-max)
spam-crm114-program
diff --git a/lisp/gnus/starttls.el b/lisp/gnus/starttls.el
index 02a557de5c..bf1982f54d 100644
--- a/lisp/gnus/starttls.el
+++ b/lisp/gnus/starttls.el
@@ -254,8 +254,7 @@ handshake, or nil on failure."
(starttls-set-process-query-on-exit-flag process nil)
(while (and (processp process)
(eq (process-status process) 'run)
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(goto-char old-max)
(not (setq done (re-search-forward
starttls-connect nil t)))))
diff --git a/lisp/gnus/utf7.el b/lisp/gnus/utf7.el
index cca647d94b..74bd092a3d 100644
--- a/lisp/gnus/utf7.el
+++ b/lisp/gnus/utf7.el
@@ -205,6 +205,7 @@ Characters are in raw byte pairs in narrowed buffer."
(mm-decode-coding-region (point-min) (point-max) 'iso-8859-1)
(mm-enable-multibyte))
+;;;###autoload
(defun utf7-encode (string &optional for-imap)
"Encode UTF-7 STRING. Use IMAP modification if FOR-IMAP is non-nil."
(if (and (coding-system-p 'utf-7) (coding-system-p 'utf-7-imap))
diff --git a/lisp/net/netrc.el b/lisp/net/netrc.el
index 408eca9bac..3636c89272 100644
--- a/lisp/net/netrc.el
+++ b/lisp/net/netrc.el
@@ -228,6 +228,7 @@ MODE can be \"login\" or \"password\", suitable for passing to
(eq type (car (cddr service)))))))
(cadr service)))
+;;;###autoload
(defun netrc-credentials (machine &rest ports)
"Return a user name/password pair.
Port specifications will be prioritised in the order they are