summaryrefslogtreecommitdiff
path: root/lisp/gnus/gnus-start.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/gnus/gnus-start.el')
-rw-r--r--lisp/gnus/gnus-start.el500
1 files changed, 223 insertions, 277 deletions
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 33462543d00..82141e02215 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -543,29 +543,21 @@ Can be used to turn version control on or off."
(message "Descend hierarchy %s? ([y]nsq): "
(substring prefix 1 (1- (length prefix)))))
(cond ((= ans ?n)
- (while (and groups
- (setq group (car groups)
- real-group (gnus-group-real-name group))
- (string-match prefix real-group))
- (push group gnus-killed-list)
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups)))
+ (dolist (g groups)
+ (when (string-match prefix (gnus-group-real-name g))
+ (push g gnus-killed-list)
+ (puthash g t gnus-killed-hashtb)))
(setq starts (cdr starts)))
((= ans ?s)
- (while (and groups
- (setq group (car groups)
- real-group (gnus-group-real-name group))
- (string-match prefix real-group))
- (gnus-sethash group group gnus-killed-hashtb)
- (gnus-subscribe-alphabetically (car groups))
- (setq groups (cdr groups)))
+ (dolist (g groups)
+ (when (string-match prefix (gnus-group-real-name g))
+ (puthash g t gnus-killed-hashtb)
+ (gnus-subscribe-alphabetically g)))
(setq starts (cdr starts)))
((= ans ?q)
- (while groups
- (setq group (car groups))
- (push group gnus-killed-list)
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups))))
+ (dolist (g groups)
+ (push g gnus-killed-list)
+ (puthash g t gnus-killed-hashtb)))
(t nil)))
(message "Subscribe %s? ([n]yq)" (car groups))
(while (not (memq (setq ans (read-char-exclusive))
@@ -575,16 +567,14 @@ Can be used to turn version control on or off."
(setq group (car groups))
(cond ((= ans ?y)
(gnus-subscribe-alphabetically (car groups))
- (gnus-sethash group group gnus-killed-hashtb))
+ (puthash group t gnus-killed-hashtb))
((= ans ?q)
- (while groups
- (setq group (car groups))
- (push group gnus-killed-list)
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups))))
+ (dolist (g groups)
+ (push g gnus-killed-list)
+ (puthash g t gnus-killed-hashtb)))
(t
(push group gnus-killed-list)
- (gnus-sethash group group gnus-killed-hashtb)))
+ (puthash group t gnus-killed-hashtb)))
(setq groups (cdr groups)))))))
(defun gnus-subscribe-randomly (newsgroup)
@@ -647,7 +637,7 @@ the first newsgroup."
;; We subscribe the group by changing its level to `subscribed'.
(gnus-group-change-level
newsgroup gnus-level-default-subscribed
- gnus-level-killed (gnus-group-entry (or next "dummy.group")))
+ gnus-level-killed (or next "dummy.group"))
(gnus-request-update-group-status newsgroup 'subscribe)
(gnus-message 5 "Subscribe newsgroup: %s" newsgroup)
(run-hook-with-args 'gnus-subscribe-newsgroup-functions newsgroup)
@@ -696,6 +686,7 @@ the first newsgroup."
gnus-agent-file-loading-cache nil
gnus-server-method-cache nil
gnus-newsrc-alist nil
+ gnus-group-list nil
gnus-newsrc-hashtb nil
gnus-killed-list nil
gnus-zombie-list nil
@@ -1018,7 +1009,7 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
(eq gnus-read-active-file 'some))
(gnus-update-active-hashtb-from-killed))
(unless gnus-active-hashtb
- (setq gnus-active-hashtb (gnus-make-hashtable 4096)))
+ (setq gnus-active-hashtb (gnus-make-hashtable 4000)))
;; Initialize the cache.
(when gnus-use-cache
(gnus-cache-open))
@@ -1108,7 +1099,7 @@ for new groups, and subscribe the new groups as zombies."
(gnus-ask-server-for-new-groups)
;; Go through the active hashtb and look for new groups.
(let ((groups 0)
- group new-newsgroups)
+ new-newsgroups)
(gnus-message 5 "Looking for new newsgroups...")
(unless gnus-have-read-active-file
(gnus-read-active-file))
@@ -1117,30 +1108,26 @@ for new groups, and subscribe the new groups as zombies."
(gnus-make-hashtable-from-killed))
;; Go though every newsgroup in `gnus-active-hashtb' and compare
;; with `gnus-newsrc-hashtb' and `gnus-killed-hashtb'.
- (mapatoms
- (lambda (sym)
- (if (or (null (setq group (symbol-name sym)))
- (not (boundp sym))
- (null (symbol-value sym))
- (gnus-gethash group gnus-killed-hashtb)
- (gnus-gethash group gnus-newsrc-hashtb))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
+ (maphash
+ (lambda (g-name active)
+ (unless (or (gethash g-name gnus-killed-hashtb)
+ (gethash g-name gnus-newsrc-hashtb))
+ (let ((do-sub (gnus-matches-options-n g-name)))
(cond
((eq do-sub 'subscribe)
(setq groups (1+ groups))
- (gnus-sethash group group gnus-killed-hashtb)
+ (puthash g-name t gnus-killed-hashtb)
(gnus-call-subscribe-functions
- gnus-subscribe-options-newsgroup-method group))
+ gnus-subscribe-options-newsgroup-method g-name))
((eq do-sub 'ignore)
nil)
(t
(setq groups (1+ groups))
- (gnus-sethash group group gnus-killed-hashtb)
+ (puthash g-name t gnus-killed-hashtb)
(if gnus-subscribe-hierarchical-interactive
- (push group new-newsgroups)
+ (push g-name new-newsgroups)
(gnus-call-subscribe-functions
- gnus-subscribe-newsgroup-method group)))))))
+ gnus-subscribe-newsgroup-method g-name)))))))
gnus-active-hashtb)
(when new-newsgroups
(gnus-subscribe-hierarchical-interactive new-newsgroups))
@@ -1213,36 +1200,32 @@ for new groups, and subscribe the new groups as zombies."
;; Enter all the new groups into a hashtable.
(gnus-active-to-gnus-format method hashtb 'ignore))
;; Now all new groups from `method' are in `hashtb'.
- (mapatoms
- (lambda (group-sym)
- (if (or (null (setq group (symbol-name group-sym)))
- (not (boundp group-sym))
- (null (symbol-value group-sym))
- (gnus-gethash group gnus-newsrc-hashtb)
- (member group gnus-zombie-list)
- (member group gnus-killed-list))
- ;; The group is already known.
- ()
+ (maphash
+ (lambda (g-name val)
+ (unless (or (null val) ; The group is already known.
+ (gethash g-name gnus-newsrc-hashtb)
+ (member g-name gnus-zombie-list)
+ (member g-name gnus-killed-list))
;; Make this group active.
- (when (symbol-value group-sym)
- (gnus-set-active group (symbol-value group-sym)))
+ (when val
+ (gnus-set-active g-name val))
;; Check whether we want it or not.
- (let ((do-sub (gnus-matches-options-n group)))
+ (let ((do-sub (gnus-matches-options-n g-name)))
(cond
((eq do-sub 'subscribe)
(cl-incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
+ (puthash g-name group gnus-killed-hashtb)
(gnus-call-subscribe-functions
- gnus-subscribe-options-newsgroup-method group))
+ gnus-subscribe-options-newsgroup-method g-name))
((eq do-sub 'ignore)
nil)
(t
(cl-incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
+ (puthash g-name group gnus-killed-hashtb)
(if gnus-subscribe-hierarchical-interactive
- (push group new-newsgroups)
+ (push g-name new-newsgroups)
(gnus-call-subscribe-functions
- gnus-subscribe-newsgroup-method group)))))))
+ gnus-subscribe-newsgroup-method g-name)))))))
hashtb))
(when new-newsgroups
(gnus-subscribe-hierarchical-interactive new-newsgroups)))
@@ -1263,29 +1246,28 @@ for new groups, and subscribe the new groups as zombies."
gnus-level-default-subscribed gnus-level-killed previous t)
t)
-;; `gnus-group-change-level' is the fundamental function for changing
-;; subscription levels of newsgroups. This might mean just changing
-;; from level 1 to 2, which is pretty trivial, from 2 to 6 or back
-;; again, which subscribes/unsubscribes a group, which is equally
-;; trivial. Changing from 1-7 to 8-9 means that you kill a group, and
-;; from 8-9 to 1-7 means that you remove the group from the list of
-;; killed (or zombie) groups and add them to the (kinda) subscribed
-;; groups. And last but not least, moving from 8 to 9 and 9 to 8,
-;; which is trivial.
-;; ENTRY can either be a string (newsgroup name) or a list (if
-;; FROMKILLED is t, it's a list on the format (NUM INFO-LIST),
-;; otherwise it's a list in the format of the `gnus-newsrc-hashtb'
-;; entries.
-;; LEVEL is the new level of the group, OLDLEVEL is the old level and
-;; PREVIOUS is the group (in hashtb entry format) to insert this group
-;; after.
+
(defun gnus-group-change-level (entry level &optional oldlevel
previous fromkilled)
+ "Change level of group ENTRY to LEVEL.
+This is the fundamental function for changing subscription levels
+of newsgroups. This might mean just changing from level 1 to 2,
+which is pretty trivial, from 2 to 6 or back again, which
+subscribes/unsubscribes a group, which is equally trivial.
+Changing from 1-7 to 8-9 means that you kill a group, and from
+8-9 to 1-7 means that you remove the group from the list of
+killed (or zombie) groups and add them to the (kinda) subscribed
+groups. And last but not least, moving from 8 to 9 and 9 to 8,
+which is trivial. ENTRY can either be a string (newsgroup name)
+or a list (if FROMKILLED is t, it's a list on the format (NUM
+INFO-LIST), otherwise it's a list in the format of the
+`gnus-newsrc-hashtb' entries. LEVEL is the new level of the
+group, OLDLEVEL is the old level and PREVIOUS is the group (a
+string name) to insert this group after."
(let (group info active num)
- ;; Glean what info we can from the arguments
+ ;; Glean what info we can from the arguments.
(if (consp entry)
- (if fromkilled (setq group (nth 1 entry))
- (setq group (car (nth 2 entry))))
+ (setq group (if fromkilled (nth 1 entry) (car (nth 1 entry))))
(setq group entry))
(when (and (stringp entry)
oldlevel
@@ -1293,21 +1275,17 @@ for new groups, and subscribe the new groups as zombies."
(setq entry (gnus-group-entry entry)))
(if (and (not oldlevel)
(consp entry))
- (setq oldlevel (gnus-info-level (nth 2 entry)))
+ (setq oldlevel (gnus-info-level (nth 1 entry)))
(setq oldlevel (or oldlevel gnus-level-killed)))
(when (stringp previous)
(setq previous (gnus-group-entry previous)))
-
- (if (and (>= oldlevel gnus-level-zombie)
- (gnus-group-entry group))
- ;; We are trying to subscribe a group that is already
- ;; subscribed.
- () ; Do nothing.
-
+ ;; Group is already subscribed.
+ (unless (and (>= oldlevel gnus-level-zombie)
+ (gnus-group-entry group))
(unless (gnus-ephemeral-group-p group)
(gnus-dribble-enter
(format "(gnus-group-change-level %S %S %S %S %S)"
- group level oldlevel (car (nth 2 previous)) fromkilled)))
+ group level oldlevel previous fromkilled)))
;; Then we remove the newgroup from any old structures, if needed.
;; If the group was killed, we remove it from the killed or zombie
@@ -1321,11 +1299,10 @@ for new groups, and subscribe the new groups as zombies."
(t
(when (and (>= level gnus-level-zombie)
entry)
- (gnus-sethash (car (nth 2 entry)) nil gnus-newsrc-hashtb)
- (when (nth 3 entry)
- (setcdr (gnus-group-entry (car (nth 3 entry)))
- (cdr entry)))
- (setcdr (cdr entry) (cdddr entry)))))
+ (remhash (car (nth 1 entry)) gnus-newsrc-hashtb)
+ (setq gnus-group-list (remove group gnus-group-list))
+ (setq gnus-newsrc-alist (delq (assoc group gnus-newsrc-alist)
+ gnus-newsrc-alist)))))
;; Finally we enter (if needed) the list where it is supposed to
;; go, and change the subscription level. If it is to be killed,
@@ -1333,12 +1310,13 @@ for new groups, and subscribe the new groups as zombies."
(cond
((>= level gnus-level-zombie)
;; Remove from the hash table.
- (gnus-sethash group nil gnus-newsrc-hashtb)
+ (remhash group gnus-newsrc-hashtb)
+ (setq gnus-group-list (remove group gnus-group-list))
(if (= level gnus-level-zombie)
(push group gnus-zombie-list)
(if (= oldlevel gnus-level-killed)
;; Remove from active hashtb.
- (unintern group gnus-active-hashtb)
+ (remhash group gnus-active-hashtb)
;; Don't add it into killed-list if it was killed.
(push group gnus-killed-list))))
(t
@@ -1349,7 +1327,7 @@ for new groups, and subscribe the new groups as zombies."
;; It was alive, and it is going to stay alive, so we
;; just change the level and don't change any pointers or
;; hash table entries.
- (setcar (cdaddr entry) level)
+ (setcar (cdadr entry) level)
(if (listp entry)
(setq info (cdr entry)
num (car entry))
@@ -1364,23 +1342,16 @@ for new groups, and subscribe the new groups as zombies."
(if method
(setq info (list group level nil nil method))
(setq info (list group level nil)))))
- (unless previous
- (setq previous
- (let ((p gnus-newsrc-alist))
- (while (cddr p)
- (setq p (cdr p)))
- p)))
- (setq entry (cons info (cddr previous)))
- (if (cdr previous)
- (progn
- (setcdr (cdr previous) entry)
- (gnus-sethash group (cons num (cdr previous))
- gnus-newsrc-hashtb))
- (setcdr previous entry)
- (gnus-sethash group (cons num previous)
- gnus-newsrc-hashtb))
- (when (cdr entry)
- (setcdr (gnus-group-entry (caadr entry)) entry))
+ ;; Add group. The exact ordering only matters for
+ ;; `gnus-group-list', though we need to keep the dummy group
+ ;; at the head of `gnus-newsrc-alist'.
+ (push info (cdr gnus-newsrc-alist))
+ (puthash group (list num info) gnus-newsrc-hashtb)
+ (let* ((prev-idx (seq-position gnus-group-list (caadr previous)))
+ (idx (if prev-idx
+ (1+ prev-idx)
+ (length gnus-group-list))))
+ (push group (nthcdr idx gnus-group-list)))
(gnus-dribble-enter
(format "(gnus-group-set-info '%S)" info)
(concat "^(gnus-group-set-info '(\"" (regexp-quote group) "\"")))))
@@ -1455,7 +1426,7 @@ newsgroup."
(defun gnus-cache-possibly-alter-active (group active)
"Alter the ACTIVE info for GROUP to reflect the articles in the cache."
(when gnus-cache-active-hashtb
- (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb)))
+ (let ((cache-active (gethash group gnus-cache-active-hashtb)))
(when cache-active
(when (< (car cache-active) (car active))
(setcar active (car cache-active)))
@@ -1837,19 +1808,24 @@ backend check whether the group actually exists."
(dolist (info infos)
(gnus-activate-group (gnus-info-group info) nil nil method t))))))
-;; Create a hash table out of the newsrc alist. The `car's of the
-;; alist elements are used as keys.
(defun gnus-make-hashtable-from-newsrc-alist ()
+ "Create a hash table from `gnus-newsrc-alist'.
+The keys are group names, and values are a cons of (unread info),
+where unread is an integer count of calculated unread
+messages (or nil), and info is a regular gnus info entry.
+
+The info element is shared with the same element of
+`gnus-newrc-alist', so as to conserve space."
(let ((alist gnus-newsrc-alist)
(ohashtb gnus-newsrc-hashtb)
- prev info method rest methods)
+ info method gname rest methods)
(setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
(setq alist
- (setq prev (setq gnus-newsrc-alist
- (if (equal (caar gnus-newsrc-alist)
- "dummy.group")
- gnus-newsrc-alist
- (cons (list "dummy.group" 0 nil) alist)))))
+ (setq gnus-newsrc-alist
+ (if (equal (caar gnus-newsrc-alist)
+ "dummy.group")
+ gnus-newsrc-alist
+ (cons (list "dummy.group" 0 nil) alist))))
(while alist
(setq info (car alist))
;; Make the same select-methods identical Lisp objects.
@@ -1858,17 +1834,18 @@ backend check whether the group actually exists."
(gnus-info-set-method info (car rest))
(push method methods)))
;; Check for duplicates.
- (if (gnus-gethash (car info) gnus-newsrc-hashtb)
+ (if (gethash (car info) gnus-newsrc-hashtb)
;; Remove this entry from the alist.
- (setcdr prev (cddr prev))
- (gnus-sethash
+ (setcdr alist (cddr alist))
+ (puthash
(car info)
;; Preserve number of unread articles in groups.
- (cons (and ohashtb (car (gnus-gethash (car info) ohashtb)))
- prev)
+ (list (and ohashtb (car (gethash (car info) ohashtb)))
+ info)
gnus-newsrc-hashtb)
- (setq prev alist))
+ (push (car info) gnus-group-list))
(setq alist (cdr alist)))
+ (setq gnus-group-list (nreverse gnus-group-list))
;; Make the same select-methods in `gnus-server-alist' identical
;; as well.
(while methods
@@ -1883,10 +1860,10 @@ backend check whether the group actually exists."
(setq gnus-killed-hashtb
(gnus-make-hashtable
(+ (length gnus-killed-list) (length gnus-zombie-list))))
- (while lists
- (setq list (symbol-value (pop lists)))
- (while list
- (gnus-sethash (car list) (pop list) gnus-killed-hashtb)))))
+ (dolist (g (append gnus-killed-list gnus-zombie-list))
+ ;; NOTE: We have lost the ordering that used to be kept in this
+ ;; variable.
+ (puthash g t gnus-killed-hashtb))))
(defun gnus-parse-active ()
"Parse active info in the nntp server buffer."
@@ -1900,7 +1877,7 @@ backend check whether the group actually exists."
(defun gnus-make-articles-unread (group articles)
"Mark ARTICLES in GROUP as unread."
- (let* ((info (nth 2 (or (gnus-group-entry group)
+ (let* ((info (nth 1 (or (gnus-group-entry group)
(gnus-group-entry
(gnus-group-real-name group)))))
(ranges (gnus-info-read info))
@@ -1924,7 +1901,7 @@ backend check whether the group actually exists."
"Mark ascending ARTICLES in GROUP as unread."
(let* ((entry (or (gnus-group-entry group)
(gnus-group-entry (gnus-group-real-name group))))
- (info (nth 2 entry))
+ (info (nth 1 entry))
(ranges (gnus-info-read info))
(r ranges)
modified)
@@ -1987,12 +1964,11 @@ backend check whether the group actually exists."
;; Insert the change into the group buffer and the dribble file.
(gnus-group-update-group group t))))
-;; Enter all dead groups into the hashtb.
(defun gnus-update-active-hashtb-from-killed ()
- (let ((hashtb (setq gnus-active-hashtb (gnus-make-hashtable 4096))))
- (dolist (list (list gnus-killed-list gnus-zombie-list))
- (dolist (group list)
- (gnus-sethash group nil hashtb)))))
+ (let ((hashtb (setq gnus-active-hashtb
+ (gnus-make-hashtable 4000))))
+ (dolist (g (append gnus-killed-list gnus-zombie-list))
+ (remhash g hashtb))))
(defun gnus-get-killed-groups ()
"Go through the active hashtb and mark all unknown groups as killed."
@@ -2003,20 +1979,16 @@ backend check whether the group actually exists."
(unless gnus-killed-hashtb
(gnus-make-hashtable-from-killed))
;; Go through all newsgroups that are known to Gnus - enlarge kill list.
- (mapatoms
- (lambda (sym)
- (let ((groups 0)
- (group (symbol-name sym)))
- (if (or (null group)
- (gnus-gethash group gnus-killed-hashtb)
- (gnus-gethash group gnus-newsrc-hashtb))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
- (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
- ()
+ (maphash
+ (lambda (g-name active)
+ (let ((groups 0))
+ (unless (or (gethash g-name gnus-killed-hashtb)
+ (gethash g-name gnus-newsrc-hashtb))
+ (let ((do-sub (gnus-matches-options-n g-name)))
+ (unless (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
(setq groups (1+ groups))
- (push group gnus-killed-list)
- (gnus-sethash group group gnus-killed-hashtb))))))
+ (push g-name gnus-killed-list)
+ (puthash g-name t gnus-killed-hashtb))))))
gnus-active-hashtb)
(gnus-dribble-touch))
@@ -2129,11 +2101,13 @@ backend check whether the group actually exists."
(not (equal method gnus-select-method)))
gnus-active-hashtb
(setq gnus-active-hashtb
- (if (equal method gnus-select-method)
- (gnus-make-hashtable
- (count-lines (point-min) (point-max)))
- (gnus-make-hashtable 4096))))))
+ (gnus-make-hashtable
+ (if (equal method gnus-select-method)
+ (count-lines (point-min) (point-max))
+ 4000))))))
group max min)
+ (unless gnus-moderated-hashtb
+ (setq gnus-moderated-hashtb (gnus-make-hashtable 100)))
;; Delete unnecessary lines.
(goto-char (point-min))
(cond
@@ -2143,12 +2117,6 @@ backend check whether the group actually exists."
(delete-matching-lines (concat "^to\\.\\|" gnus-ignored-newsgroups))))
(goto-char (point-min))
- (unless (re-search-forward "[\\\"]" nil t)
- ;; Make the group names readable as a lisp expression even if they
- ;; contain special characters.
- (goto-char (point-max))
- (while (re-search-backward "[][';?()#]" nil t)
- (insert ?\\)))
;; Let the Gnus agent save the active file.
(when (and gnus-agent real-active (gnus-online method))
@@ -2168,49 +2136,35 @@ backend check whether the group actually exists."
(insert prefix)
(zerop (forward-line 1)))))))
;; Store the active file in a hash table.
- ;; Use a unibyte buffer in order to make `read' read non-ASCII
- ;; group names (which have been encoded) as unibyte strings.
- (mm-with-unibyte-buffer
+
+ (with-temp-buffer
(insert-buffer-substring cur)
(setq cur (current-buffer))
(goto-char (point-min))
(while (not (eobp))
(condition-case ()
- (progn
- (narrow-to-region (point) (point-at-eol))
- ;; group gets set to a symbol interned in the hash table
- ;; (what a hack!!) - jwz
- (setq group (let ((obarray hashtb)) (read cur)))
- ;; ### The extended group name scheme makes
- ;; the previous optimization strategy sort of pointless...
- (when (stringp group)
- (setq group (intern group hashtb)))
- (if (and (numberp (setq max (read cur)))
- (numberp (setq min (read cur)))
- (progn
- (skip-chars-forward " \t")
- (not
- (or (eq (char-after) ?=)
- (eq (char-after) ?x)
- (eq (char-after) ?j)))))
- (progn
- (set group (cons min max))
- ;; if group is moderated, stick in moderation table
- (when (eq (char-after) ?m)
- (unless gnus-moderated-hashtb
- (setq gnus-moderated-hashtb (gnus-make-hashtable)))
- (gnus-sethash (symbol-name group) t
- gnus-moderated-hashtb)))
- (set group nil)))
+ (if (and (stringp (progn
+ (setq group (read cur)
+ group (if (numberp group)
+ (number-to-string group)
+ (symbol-name group)))))
+ (numberp (setq max (read cur)))
+ (numberp (setq min (read cur)))
+ (null (progn
+ (skip-chars-forward " \t")
+ (memq (char-after)
+ '(?= ?x ?j)))))
+ (progn (puthash group (cons min max) hashtb)
+ ;; If group is moderated, stick it in the
+ ;; moderation cache.
+ (when (eq (char-after) ?m)
+ (puthash group t gnus-moderated-hashtb)))
+ (setq group nil))
(error
- (and group
- (symbolp group)
- (set group nil))
(unless ignore-errors
(gnus-message 3 "Warning - invalid active: %s"
(buffer-substring
(point-at-bol) (point-at-eol))))))
- (widen)
(forward-line 1)))))
(defun gnus-groups-to-gnus-format (method &optional hashtb real-active)
@@ -2238,35 +2192,23 @@ backend check whether the group actually exists."
(gnus-active-to-gnus-format method hashtb nil real-active))
(goto-char (point-min))
- ;; We split this into to separate loops, one with the prefix
- ;; and one without to speed the reading up somewhat.
- (if prefix
- (let (min max opoint group)
- (while (not (eobp))
- (condition-case ()
- (progn
- (read cur) (read cur)
- (setq min (read cur)
- max (read cur)
- opoint (point))
- (skip-chars-forward " \t")
- (insert prefix)
- (goto-char opoint)
- (set (let ((obarray hashtb)) (read cur))
- (cons min max)))
- (error (and group (symbolp group) (set group nil))))
- (forward-line 1)))
- (let (min max group)
- (while (not (eobp))
- (condition-case ()
- (when (eq (char-after) ?2)
- (read cur) (read cur)
- (setq min (read cur)
- max (read cur))
- (set (setq group (let ((obarray hashtb)) (read cur)))
- (cons min max)))
- (error (and group (symbolp group) (set group nil))))
- (forward-line 1)))))))
+ (let (min max group)
+ (while (not (eobp))
+ (condition-case ()
+ (when (eq (char-after) ?2)
+ (read cur) (read cur)
+ (setq min (read cur)
+ max (read cur)
+ group (read cur)
+ group (if (numberp group)
+ (number-to-string group)
+ (symbol-name group)))
+ (puthash (if prefix
+ (concat prefix group)
+ group)
+ (cons min max) hashtb))
+ (error (remhash group hashtb)))
+ (forward-line 1))))))
(defun gnus-read-newsrc-file (&optional force)
"Read startup file.
@@ -2529,16 +2471,11 @@ If FORCE is non-nil, the .newsrc file is read."
(setq gnus-newsrc-options-n nil)
(unless gnus-active-hashtb
- (setq gnus-active-hashtb (gnus-make-hashtable 4096)))
+ (setq gnus-active-hashtb (gnus-make-hashtable 4000)))
(let ((buf (current-buffer))
(already-read (> (length gnus-newsrc-alist) 1))
- group subscribed options-symbol newsrc Options-symbol
- symbol reads num1)
+ group subscribed newsrc reads num1)
(goto-char (point-min))
- ;; We intern the symbol `options' in the active hashtb so that we
- ;; can `eq' against it later.
- (set (setq options-symbol (intern "options" gnus-active-hashtb)) nil)
- (set (setq Options-symbol (intern "Options" gnus-active-hashtb)) nil)
(while (not (eobp))
;; We first read the first word on the line by narrowing and
@@ -2549,15 +2486,16 @@ If FORCE is non-nil, the .newsrc file is read."
(point)
(progn (skip-chars-forward "^ \t!:\n") (point)))
(goto-char (point-min))
- (setq symbol
+ (setq group
(and (/= (point-min) (point-max))
- (let ((obarray gnus-active-hashtb)) (read buf))))
+ (read buf))
+ group (if (numberp group)
+ (number-to-string group)
+ (symbol-name group)))
(widen)
- ;; Now, the symbol we have read is either `options' or a group
- ;; name. If it is an options line, we just add it to a string.
(cond
- ((or (eq symbol options-symbol)
- (eq symbol Options-symbol))
+ ;; It's possible that "group" is actually an options line.
+ ((string-equal (downcase group) "options")
(setq gnus-newsrc-options
;; This concatting is quite inefficient, but since our
;; thorough studies show that approx 99.37% of all
@@ -2571,19 +2509,13 @@ If FORCE is non-nil, the .newsrc file is read."
(point-at-bol))
(point)))))
(forward-line -1))
- (symbol
- ;; Group names can be just numbers.
- (when (numberp symbol)
- (setq symbol (intern (int-to-string symbol) gnus-active-hashtb)))
- (unless (boundp symbol)
- (set symbol nil))
+ (group
;; It was a group name.
(setq subscribed (eq (char-after) ?:)
- group (symbol-name symbol)
reads nil)
(if (eolp)
;; If the line ends here, this is clearly a buggy line, so
- ;; we put point a the beginning of line and let the cond
+ ;; we put point at the beginning of line and let the cond
;; below do the error handling.
(beginning-of-line)
;; We skip to the beginning of the ranges.
@@ -2622,7 +2554,7 @@ If FORCE is non-nil, the .newsrc file is read."
;; It was just a simple number, so we add it to the
;; list of ranges.
(push num1 reads))
- ;; If the next char in ?\n, then we have reached the end
+ ;; If the next char is ?\n, then we have reached the end
;; of the line and return nil.
(not (eq (char-after) ?\n)))
((eq (char-after) ?\n)
@@ -2651,7 +2583,8 @@ If FORCE is non-nil, the .newsrc file is read."
(let ((info (gnus-get-info group))
level)
(if info
- ;; There is an entry for this file in the alist.
+ ;; There is an entry for this file in
+ ;; `gnus-newsrc-hashtb'.
(progn
(gnus-info-set-read info (nreverse reads))
;; We update the level very gently. In fact, we
@@ -2679,8 +2612,7 @@ If FORCE is non-nil, the .newsrc file is read."
(setq newsrc (nreverse newsrc))
- (if (not already-read)
- ()
+ (unless already-read
;; We now have two newsrc lists - `newsrc', which is what we
;; have read from .newsrc, and `gnus-newsrc-alist', which is
;; what we've read from .newsrc.eld. We have to merge these
@@ -2777,9 +2709,10 @@ If FORCE is non-nil, the .newsrc file is read."
(defvar gnus-save-newsrc-file-last-timestamp nil)
(defun gnus-save-newsrc-file (&optional force)
- "Save .newsrc file."
- ;; Note: We cannot save .newsrc file if all newsgroups are removed
- ;; from the variable gnus-newsrc-alist.
+ "Save .newsrc file.
+Use the group string names in `gnus-group-list' to pull info
+values from `gnus-newsrc-hashtb', and write a new value of
+`gnus-newsrc-alist'."
(when (and (or gnus-newsrc-alist gnus-killed-list)
gnus-current-startup-file)
;; Save agent range limits for the currently active method.
@@ -2895,7 +2828,13 @@ If FORCE is non-nil, the .newsrc file is read."
(gnus-group-set-mode-line)))))
(defun gnus-gnus-to-quick-newsrc-format (&optional minimal name &rest specific-variables)
- "Print Gnus variables such as `gnus-newsrc-alist' in Lisp format."
+ "Print Gnus variables such as `gnus-newsrc-alist' in Lisp format.
+Unless optional argument MINIMAL is non-nil, print human-readable
+information in the header of the file, including the file
+version. If NAME is present, print that as part of the header.
+
+Variables printed are either the variables specified in
+SPECIFIC-VARIABLES, or those in `gnus-variable-list'."
(princ (format ";; -*- mode:emacs-lisp; coding: %s; -*-\n"
gnus-ding-file-coding-system))
(if name
@@ -2929,9 +2868,18 @@ If FORCE is non-nil, the .newsrc file is read."
;; Remove the `gnus-killed-list' from the list of variables
;; to be saved, if required.
(delq 'gnus-killed-list (copy-sequence gnus-variable-list)))))
- ;; Peel off the "dummy" group.
- (gnus-newsrc-alist (cdr gnus-newsrc-alist))
variable)
+ ;; A bit of a fake-out here: the original value of
+ ;; `gnus-newsrc-alist' isn't written to file, instead it is
+ ;; constructed at the last minute by combining the group
+ ;; ordering in `gnus-group-list' with the group infos from
+ ;; `gnus-newsrc-hashtb'.
+ (set (nth (seq-position gnus-variable-list 'gnus-newsrc-alist)
+ gnus-variable-list)
+ (mapcar (lambda (g)
+ (nth 1 (gethash g gnus-newsrc-hashtb)))
+ gnus-group-list))
+
;; Insert the variables into the file.
(while variables
(when (and (boundp (setq variable (pop variables)))
@@ -2956,8 +2904,8 @@ If FORCE is non-nil, the .newsrc file is read."
(interactive (list (gnus-y-or-n-p "write foreign groups too? ")))
;; Generate and save the .newsrc file.
(with-current-buffer (create-file-buffer gnus-current-startup-file)
- (let ((newsrc (cdr gnus-newsrc-alist))
- (standard-output (current-buffer))
+ (let ((standard-output (current-buffer))
+ (groups (delete "dummy.group" (copy-sequence gnus-group-list)))
info ranges range method)
(setq buffer-file-name gnus-current-startup-file)
(setq default-directory (file-name-directory buffer-file-name))
@@ -2971,13 +2919,14 @@ If FORCE is non-nil, the .newsrc file is read."
(when gnus-newsrc-options
(insert gnus-newsrc-options))
;; Write subscribed and unsubscribed.
- (while (setq info (pop newsrc))
- ;; Don't write foreign groups to .newsrc.
+ (dolist (g-name groups)
+ (setq info (nth 1 (gnus-group-entry g-name)))
+ ;; Maybe don't write foreign groups to .newsrc.
(when (or (null (setq method (gnus-info-method info)))
(equal method "native")
(inline (gnus-server-equal method gnus-select-method))
foreign-ok)
- (insert (gnus-info-group info)
+ (insert g-name
(if (> (gnus-info-level info) gnus-level-subscribed)
"!" ":"))
(when (setq ranges (gnus-info-read info))
@@ -3105,10 +3054,10 @@ If FORCE is non-nil, the .newsrc file is read."
;; to avoid trying to re-read after a failed read.
(unless gnus-description-hashtb
(setq gnus-description-hashtb
- (gnus-make-hashtable (length gnus-active-hashtb))))
+ (gnus-make-hashtable (hash-table-size gnus-active-hashtb))))
;; Mark this method's desc file as read.
- (gnus-sethash (gnus-group-prefixed-name "" method) "Has read"
- gnus-description-hashtb)
+ (puthash (gnus-group-prefixed-name "" method) "Has read"
+ gnus-description-hashtb)
(gnus-message 5 "Reading descriptions file via %s..." (car method))
(cond
@@ -3144,29 +3093,26 @@ If FORCE is non-nil, the .newsrc file is read."
(zerop (forward-line 1)))))))
(goto-char (point-min))
(while (not (eobp))
- ;; If we get an error, we set group to 0, which is not a
- ;; symbol...
(setq group
(condition-case ()
- (let ((obarray gnus-description-hashtb))
- ;; Group is set to a symbol interned in this
- ;; hash table.
- (read nntp-server-buffer))
- (error 0)))
+ (read nntp-server-buffer)
+ (error nil)))
(skip-chars-forward " \t")
- ;; ... which leads to this line being effectively ignored.
- (when (symbolp group)
+ (when group
+ (setq group (if (numberp group)
+ (number-to-string group)
+ (symbol-name group)))
(let* ((str (buffer-substring
(point) (progn (end-of-line) (point))))
- (name (symbol-name group))
(charset
- (or (gnus-group-name-charset method name)
- (gnus-parameter-charset name)
+ (or (gnus-group-name-charset method group)
+ (gnus-parameter-charset group)
gnus-default-charset)))
;; Fixme: Don't decode in unibyte mode.
+ ;; Double fixme: We're not in unibyte mode, are we?
(when (and str charset)
(setq str (decode-coding-string str charset)))
- (set group str)))
+ (puthash group str gnus-description-hashtb)))
(forward-line 1))))
(gnus-message 5 "Reading descriptions file...done")
t))))