(system-name)))
"*Default method for selecting a newsgroup.
This variable should be a list, where the first element is how the
-news is to be fetched, the second is the address. An optional third
-element can be included to specify a port number if nntp is used.
+news is to be fetched, the second is the address.
For instance, if you want to get your news via NNTP from
-\"flab.flab.edu\" on port 23, you could say:
+\"flab.flab.edu\", you could say:
-(setq gnus-select-method '(nntp \"flab.flab.edu\" 23))
+(setq gnus-select-method '(nntp \"flab.flab.edu\"))
If you want to use your local spool, say:
(setq gnus-select-method (list 'nnspool (system-name)))
-If you use this variable, you must set `gnus-nntp-server' to nil.")
+If you use this variable, you must set `gnus-nntp-server' to nil.
+
+There is a lot more to know about select methods and virtual servers -
+see the manual for details.")
;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
(defvar gnus-post-method nil
nntp server for your newsgroup and want to change the port number
used to 899, you would say something along these lines:
- (setq gnus-select-method '(nntp \"my.nntp.server\" 899))")
+ (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
(defvar gnus-startup-file "~/.newsrc"
"*Your `.newsrc' file.
If this variable is nil, Gnus will only know about the groups in your
`.newsrc' file.
-If you set this variable to nil, you probably still want to be told
-about new newsgroups that arrive. To do that, set
+If this variable is `some', Gnus will try to only read the relevant
+parts of the active file from the server. Not all servers support
+this, and it might be quite slow with other servers, but this should
+generally be faster than both the t and nil value.
+
+If you set this variable to nil or `some', you probably still want to
+be told about new newsgroups that arrive. To do that, set
`gnus-check-new-newsgroups' to `ask-server'. This may not work
-properly with all servers.")
+properly with all servers.")
+
+(defvar gnus-level-subscribed 5
+ "*Groups with levels less than or equal to this variable are subscribed.")
+
+(defvar gnus-level-unsubscribed 7
+ "*Groups with levels less than or equal to this variable are unsubscribed.
+Groups with levels less than `gnus-level-subscribed', which should be
+less than thiss variable, are subscribed.")
+
+(defvar gnus-level-zombie 8
+ "*Groups with this level are zombie groups.")
+
+(defvar gnus-level-killed 9
+ "*Groups with this level are killed.")
+
+(defvar gnus-level-default-subscribed 3
+ "*New subscribed groups will be subscribed at this level.")
+
+(defvar gnus-level-default-unsubscribed
+ "*New unsubscribed groups will be unsubscribed at this level.")
(defvar gnus-activate-foreign-newsgroups nil
"*If nil, Gnus will not check foreign newsgroups at startup.
If it is non-nil, it should be a number between one and nine. Foreign
newsgroups that have a level lower or equal to this number will be
activated on startup. For instance, if you want to active all
-subscribed newsgroups, but not the rest, you'd set this variable to 5.
+subscribed newsgroups, but not the rest, you'd set this variable to
+`gnus-level-subscribed'.
If you subscribe to lots of newsgroups from different servers, startup
might take a while. By setting this variable to nil, you'll save time,
"*Default article score level.
If this variable is nil, scoring will be disabled.")
-(defvar gnus-group-default-list-level 5
+(defvar gnus-group-default-list-level gnus-level-subscribed
"*Default listing level.")
-(defvar gnus-group-always-list-unread 5
+(defvar gnus-group-always-list-unread gnus-level-subscribed
"*Always list groups less than this variable with unread articles.
If nil, use parameter to specify.")
be placed first in the article buffer in the sequence specified by
this list.")
+(defvar gnus-check-before-posting t
+ "In non-nil, Gnus will attempt to run some checks on outgoing posts.")
+
(defvar gnus-required-headers
'(From Date Newsgroups Subject Message-ID Organization Lines X-Newsreader)
"*Headers to be generated or prompted for when posting an article.
%M Only marked articles (character, \"*\" or \" \")
%S Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
-%L Level of subscribedness (integer, 1-9)
+%L Level of subscribedness (integer)
%N Number of unread articles (integer)
%I Number of dormant articles (integer)
%i Number of ticked and dormant (integer)
(defvar gnus-newsgroup-dependencies nil)
(defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
-(defvar gnus-default-subscribe-level 2)
-(defvar gnus-default-unsubscribe-level 6)
-(defvar gnus-default-kill-level 9)
(defconst gnus-group-line-format-alist
(list (list ?M 'marked ?c)
(defconst gnus-maintainer "Lars Magne Ingebrigtsen <larsi@ifi.uio.no>"
"The mail address of the Gnus maintainer.")
-(defconst gnus-version "(ding) Gnus v0.53"
+(defconst gnus-version "(ding) Gnus v0.54"
"Version number for this version of Gnus.")
(defvar gnus-info-nodes
"Subscribe new NEWSGROUP.
If NEXT is non-nil, it is inserted before NEXT. Otherwise it is made
the first newsgroup."
- ;; We subscribe the group by changing its level to 3.
+ ;; We subscribe the group by changing its level to `subscribed'.
(gnus-group-change-level
- newsgroup 3 9 (gnus-gethash (or next "dummy.group") gnus-newsrc-hashtb))
+ newsgroup gnus-level-default-subscribed
+ gnus-level-killed (gnus-gethash (or next "dummy.group") gnus-newsrc-hashtb))
(message "Subscribe newsgroup: %s" newsgroup))
;; For directories
(define-key gnus-group-mode-map "\M-f" 'gnus-group-fetch-faq)
(define-key gnus-group-mode-map "?" 'gnus-group-describe-briefly)
(define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node)
- (define-key gnus-group-mode-map "\M-e" 'gnus-group-edit-group)
+ (define-key gnus-group-mode-map "\M-e" 'gnus-group-edit-group-method)
(define-key gnus-group-mode-map "^" 'gnus-group-enter-server-mode)
(define-key gnus-group-mode-map
(if gnus-xemacs [button2] [mouse-2]) 'gnus-mouse-pick-group)
(define-key gnus-group-make-map "a" 'gnus-group-make-archive-group)
(define-key gnus-group-make-map "k" 'gnus-group-make-kiboze-group)
(define-key gnus-group-make-map "m" 'gnus-group-make-group)
- (define-key gnus-group-make-map "e" 'gnus-group-edit-group)
+ (define-key gnus-group-make-map "E" 'gnus-group-edit-group)
+ (define-key gnus-group-make-map "e" 'gnus-group-edit-group-method)
+ (define-key gnus-group-make-map "p" 'gnus-group-edit-group-parameters)
(define-prefix-command 'gnus-group-list-map)
(define-key gnus-group-mode-map "G" 'gnus-group-list-map)
prompt the user for the name of an NNTP server to use.
As opposed to `gnus', this command will not connect to the local server."
(interactive "P")
- (gnus (or arg 2) t))
+ (gnus (or arg (1- gnus-level-default-subscribed)) t))
(defalias '\(ding\) 'gnus)
(defun gnus-group-list-groups (level &optional unread)
"List newsgroups with level LEVEL or lower that have unread alticles.
-Default is 5, which lists all subscribed groups.
+Default is all subscribed groups.
If argument UNREAD is non-nil, groups with no unread articles are also listed."
(interactive "P")
- (setq level (or level gnus-group-default-list-level 5))
+ (setq level (or level gnus-group-default-list-level gnus-level-subscribed))
(gnus-group-setup-buffer) ;May call from out of group buffer
(let ((case-fold-search nil)
(group (gnus-group-group-name)))
(lowest (or lowest 1))
info clevel unread group)
(erase-buffer)
- (if (< lowest 8)
+ (if (< lowest gnus-level-zombie)
;; List living groups.
(while newsrc
(setq info (car newsrc)
nil group (car (cdr info)) (nth 3 info) unread (nth 4 info)))))
;; List dead groups.
- (and (>= level 8) (<= lowest 8)
+ (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie)
(gnus-group-prepare-flat-list-dead
- (setq gnus-zombie-list (sort gnus-zombie-list 'string<)) 8 ?Z
+ (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
+ gnus-level-zombie ?Z
regexp))
- (and (>= level 9) (<= lowest 9)
+ (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)
(gnus-group-prepare-flat-list-dead
- (setq gnus-killed-list (sort gnus-killed-list 'string<)) 9 ?K
- regexp))
+ (setq gnus-killed-list (sort gnus-killed-list 'string<))
+ gnus-level-killed ?K regexp))
(gnus-group-set-mode-line)
(setq gnus-have-all-newsgroups all)
"Return nil if GROUP is native, non-nil if it is foreign."
(string-match ":" group))
-(defun gnus-group-set-info (info)
- (let ((entry (gnus-gethash (car info) gnus-newsrc-hashtb)))
+(defun gnus-group-set-info (info &optional method-only-group part)
+ (let* ((entry (gnus-gethash
+ (or method-only-group (car info)) gnus-newsrc-hashtb))
+ (part-info info)
+ (info (if method-only-group (nth 2 entry) info)))
+ (if (not method-only-group)
+ ()
+ (or entry
+ (error "Trying to change non-existant group %s" method-only-group))
+ ;; We have recevied parts of the actual group info - either the
+ ;; select method or the group parameters. We first check
+ ;; whether we have to extend the info, and if so, do that.
+ (let ((len (length info))
+ (total (if (eq part 'method) 5 6)))
+ (and (< len total)
+ (setcdr (nthcdr (1- len) info)
+ (make-list (- total len) nil)))
+ ;; Then we enter the new info.
+ (setcar (nthcdr (1- total) info) part-info)))
+ ;; We uncompress some lists of marked articles.
(let (marked)
(if (not (setq marked (nth 3 info)))
()
(setq marked (cdr marked)))))
(if entry
()
+ ;; This is a new group, so we just create it.
(save-excursion
(set-buffer gnus-group-buffer)
(if (nth 4 info)
+ ;; It's a foreign group...
(gnus-group-make-group
(gnus-group-real-name (car info))
(prin1-to-string (car (nth 4 info)))
(nth 1 (nth 4 info)))
+ ;; It's a native group.
(gnus-group-make-group
(car info)
(prin1-to-string (car gnus-select-method))
(gnus-group-real-name (car info))
(or (nth 4 info) gnus-select-method))
gnus-newsrc-hashtb))))
+ ;; Whether it was a new group or not, we now have the entry, so we
+ ;; can do the update.
(if entry
(progn
(setcar (nthcdr 2 entry) info)
(length (cdr (assq 'dormant marked)))))))))
(error "No such group: %s" (car info)))))
+(defun gnus-group-set-method-info (group select-method)
+ (gnus-group-set-info select-method group 'method))
+
+(defun gnus-group-set-params-info (group params)
+ (gnus-group-set-info params group 'params))
+
(defun gnus-group-update-group-line ()
"This function updates the current line in the newsgroup buffer and
moves the point to the colon."
nil group (nth 1 info) (nth 3 info) (car entry) (nth 4 info)))
(setq active (gnus-gethash group gnus-active-hashtb))
(gnus-group-insert-group-line
- nil group (if (member group gnus-zombie-list) 8 9)
+ nil group (if (member group gnus-zombie-list) gnus-level-zombie
+ gnus-level-killed)
nil (if active (- (1+ (cdr active)) (car active)) 0) nil))))
(defun gnus-group-insert-group-line (gformat group level marked number method)
(if (numberp number)
(max 0 (- number-total number))
"*"))
- (subscribed (cond ((< level 6) ? )
- ((< level 8) ?U)
- ((= level 8) ?Z)
+ (subscribed (cond ((<= level gnus-level-subscribed) ? )
+ ((<= level gnus-level-unsubscribed) ?U)
+ ((= level gnus-level-zombie) ?Z)
(t ?K)))
(qualified-group (gnus-group-real-name group))
(newsgroup-description
(let ((unread
(get-text-property (point) 'gnus-unread)))
(or (eq unread t) (and unread (> unread 0))))
- (let ((lev (get-text-property (point) 'gnus-level)))
- (and lev (< (get-text-property (point) 'gnus-level) 6)))))
+ (let ((lev (get-text-property
+ (point) 'gnus-level)))
+ (and lev (<= (get-text-property
+ (point) 'gnus-level)
+ gnus-level-subscribed)))))
(or (not level)
(let ((lev (get-text-property (point) 'gnus-level)))
(if (and lev (<= lev level))
(and (gnus-gethash nname gnus-active-hashtb)
(error "Group %s already exists" nname))
(gnus-group-change-level
- (setq info (list t nname 3 nil nil meth))
- 3 9 (gnus-gethash (or (gnus-group-group-name) "dummy.group")
+ (setq info (list t nname gnus-level-default-subscribed nil nil meth))
+ gnus-level-default-subscribed gnus-level-killed
+ (gnus-gethash (or (gnus-group-group-name) "dummy.group")
gnus-newsrc-hashtb) t)
(gnus-sethash nname '(0 . 0) gnus-active-hashtb)
(gnus-dribble-enter
(and (gnus-check-backend-function 'request-create-group nname)
(gnus-request-create-group nname))))
-(defun gnus-group-edit-group (group)
+(defun gnus-group-edit-group (group &optional part)
"Edit the group on the current line."
(interactive (list (gnus-group-group-name)))
(let (info)
(setcdr (car marked)
(gnus-compress-sequence (sort (cdr (car marked)) '<) t)))
(setq marked (cdr marked))))
- (insert (pp-to-string (list 'gnus-group-set-info
- (list 'quote cinfo)))))))
+ (cond ((eq part 'method)
+ (insert
+ "(gnus-group-set-method-info \"" group "\"\n "
+ (pp-to-string (list 'quote (or (nth 4 info) "native"))) ")\n"))
+ ((eq part 'params)
+ (insert
+ "(gnus-group-set-params-info \"" group "\"\n "
+ (pp-to-string (list 'quote (nth 5 info))) ")\n"))
+ (t
+ (insert (pp-to-string
+ (list 'gnus-group-set-info (list 'quote cinfo)))))))))
+
+(defun gnus-group-edit-group-method (group)
+ "Edit the select method of GROUP."
+ (interactive (list (gnus-group-group-name)))
+ (gnus-group-edit-group group 'method))
+
+(defun gnus-group-edit-group-parameters (group)
+ "Edit the group parameters of GROUP."
+ (interactive (list (gnus-group-group-name)))
+ (gnus-group-edit-group group 'params))
(defun gnus-group-edit-group-done ()
(interactive)
(setq gnus-newsrc-assoc
(sort (cdr gnus-newsrc-assoc) gnus-group-sort-function))
(gnus-make-hashtable-from-newsrc-alist)
- (gnus-get-unread-articles 6)
+ (gnus-get-unread-articles (1+ gnus-level-subscribed))
(gnus-group-list-groups nil))
(defun gnus-group-sort-by-alphabet (info1 info2)
(if (and gnus-read-active-file (not arg))
(progn
(gnus-read-active-file)
- (gnus-get-unread-articles (or arg 6)))
+ (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed))))
(let ((gnus-read-active-file nil))
- (gnus-get-unread-articles (or arg 6))))
+ (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed)))))
(gnus-group-list-groups
- (or gnus-group-always-list-unread arg 5) gnus-have-all-newsgroups))
+ (or gnus-group-always-list-unread arg gnus-level-subscribed)
+ gnus-have-all-newsgroups))
(defun gnus-group-get-new-news-this-group (n)
"Check for newly arrived news in the current group (and the N-1 next groups).
(symbol-value group)))
(add-text-properties
b (1+ b) (list 'gnus-group group
- 'gnus-unread t 'gnus-marked nil 'gnus-level 6)))
+ 'gnus-unread t 'gnus-marked nil
+ 'gnus-level (1+ gnus-level-subscribed))))
gnus-description-hashtb)
(goto-char (point-min))
(gnus-group-position-cursor)))
If ALL, also list groups with no unread articles.
If LOWEST, don't list groups with level lower than LOWEST."
(interactive "P\nsList newsgroups matching: ")
- (gnus-group-prepare-flat (or level 5) all (or lowest 1) regexp)
+ (gnus-group-prepare-flat (or level gnus-level-subscribed)
+ all (or lowest 1) regexp)
(goto-char (point-min))
(gnus-group-position-cursor))
level to cut off listing groups.
If LOWEST, don't list groups with level lower than LOWEST."
(interactive "P\nsList newsgroups matching: ")
- (gnus-group-list-matching (or level 9) regexp t lowest))
+ (gnus-group-list-matching (or level gnus-level-killed) regexp t lowest))
;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
(defun gnus-group-save-newsrc ()
(if sub
(progn
(gnus-group-change-level
- (list t group 3 nil nil gnus-browse-current-method) 3 9
+ (list t group gnus-level-default-subscribed
+ nil nil gnus-browse-current-method)
+ gnus-level-default-subscribed gnus-level-killed
(gnus-gethash (car (nth 1 gnus-newsrc-assoc)) gnus-newsrc-hashtb)
t)
(insert ? ))
- (gnus-group-change-level group 9 3)
+ (gnus-group-change-level
+ group gnus-level-killed gnus-level-default-subscribed)
(insert ?K)))
t))
(setq gnus-newsgroup-auto-expire
(or (and (stringp gnus-auto-expirable-newsgroups)
(string-match gnus-auto-expirable-newsgroups group))
- (memq 'auto-expire gnus-current-select-method)))
+ (memq 'auto-expire (nth 5 info))))
;; First and last article in this newsgroup.
(and gnus-newsgroup-headers
(setq gnus-newsgroup-begin
virtual
;; Only do cross-references on subscribed
;; groups, if that is what is wanted.
- (<= (nth 1 info) 5)))
+ (<= (nth 1 info) gnus-level-subscribed)))
(progn
(setq num 0)
;; Set the new list of read articles in this group.
(set-buffer gnus-group-buffer)
(gnus-sethash
name
- (list t nil (list name 3 nil nil
+ (list t nil (list name gnus-level-default-subscribed nil nil
(list 'nndigest gnus-article-buffer
(cons 'quit-buffer buf))))
gnus-newsrc-hashtb)
(while newsrc
(setq group (car (car newsrc)))
(setq entry (gnus-gethash group gnus-newsrc-hashtb))
- (if (and (<= (nth 1 (car newsrc)) 5)
+ (if (and (<= (nth 1 (car newsrc)) gnus-level-subscribed)
(and (car entry)
(or (eq (car entry) t)
(not (zerop (car entry)))))
(format "%s" (car (gnus-find-method-for-group
gnus-newsgroup-name)))
gnus-valid-select-methods))))
- (assq 'to-address (gnus-find-method-for-group gnus-newsgroup-name))
+ (assq 'to-address (nth 5 (nth 2 (gnus-gethash gnus-newsgroup-name
+ gnus-newsrc-hashtb))))
(gnus-y-or-n-p "Are you sure you want to post to all of USENET? "))
(let ((sumart (if (not post)
(save-excursion
(defun gnus-inews-check-post ()
"Check whether the post looks ok."
- (and
- ;; Check excessive size.
- (if (> (buffer-size) 60000)
- (gnus-y-or-n-p (format "The article is %d octets long. Really post? "
- (buffer-size)))
- t)
- ;; Check for commands in Subject.
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (if (string-match "^cmsg " (mail-fetch-field "subject"))
- (gnus-y-or-n-p
- "The control code \"cmsg \" is in the subject. Really post? ")
- t)))
- ;; Check for control characters.
- (save-excursion
- (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
- (gnus-y-or-n-p
- "The article contains control characters. Really post? ")
- t))
- ;; Check for multiple identical headers.
- (let (found)
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (goto-char (point-min))
- (while (and (not found) (re-search-forward "^[^ \t:]+: " nil t))
- (save-excursion
- (or (re-search-forward
- (concat "^" (setq found
- (buffer-substring (match-beginning 0)
- (match-end 0))))
- nil t)
- (setq found nil))))
- (if found
- (gnus-y-or-n-p
- (format "Multiple %s headers. Really post? " found))
- t))))
- ;; Check for version and sendsys.
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (if (re-search-backward "^Sendsys:\\|^Version:" nil t)
- (gnus-yes-or-no-p
- (format "The article contains a %s command. Really post? "
- (buffer-substring (match-beginning 0) (match-end 0))))
- t)))
- ;; Check the From header.
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (let* ((case-fold-search t)
- (from (mail-fetch-field "from")))
- (if (and from
- (string-match "@" from)
- (not (string-match "@[^\\.]*\\." from)))
- (gnus-yes-or-no-p
- (format "The domain looks strange: \"%s\". Really post? "
- from))
- t))))
- ;; Check for long lines.
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (while
- (and
- (progn
- (end-of-line)
- (< (current-column) 80))
- (zerop (forward-line 1))))
- (or (eobp)
- (gnus-yes-or-no-p
- (format
- "You have lines longer than 79 characters. Really post? ")))))
- ;; Use the (size . checksum) variable to see whether the
- ;; article is empty or has only quoted text.
- (if (and (= (buffer-size) (car gnus-article-check-size))
- (= (gnus-article-checksum) (cdr gnus-article-check-size)))
- (gnus-yes-or-no-p
- "It looks like there's no new text in your article. Really post? ")
- t)))
+ (or
+ (not gnus-check-before-posting)
+ (and
+ ;; We narrow to the headers and check them first.
+ (save-excursion
+ (save-restriction
+ (goto-char (point-min))
+ (narrow-to-region
+ (point)
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "$")))
+ (goto-char (point-min))
+ (and
+ ;; Check for commands in Subject.
+ (save-excursion
+ (if (string-match "^cmsg " (mail-fetch-field "subject"))
+ (gnus-y-or-n-p
+ "The control code \"cmsg \" is in the subject. Really post? ")
+ t))
+ ;; Check for multiple identical headers.
+ (save-excursion
+ (let (found)
+ (while (and (not found) (re-search-forward "^[^ \t:]+: " nil t))
+ (save-excursion
+ (or (re-search-forward
+ (concat "^" (setq found
+ (buffer-substring
+ (match-beginning 0)
+ (- (match-end 0) 2))))
+ nil t)
+ (setq found nil))))
+ (if found
+ (gnus-y-or-n-p
+ (format "Multiple %s headers. Really post? " found))
+ t)))
+ ;; Check for version and sendsys.
+ (save-excursion
+ (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
+ (gnus-yes-or-no-p
+ (format "The article contains a %s command. Really post? "
+ (buffer-substring (match-beginning 0)
+ (1- (match-end 0)))))
+ t))
+ ;; Check the Message-Id header.
+ (save-excursion
+ (let* ((case-fold-search t)
+ (message-id (mail-fetch-field "message-id")))
+ (or (and (string-match "@" message-id)
+ (string-match "@[^\\.]*\\." message-id))
+ (gnus-yes-or-no-p
+ (format "The Message-ID looks strange: \"%s\". Really post? "
+ message-id)))))
+ ;; Check the From header.
+ (save-excursion
+ (let* ((case-fold-search t)
+ (from (mail-fetch-field "from")))
+ (or (and (string-match "@" from)
+ (string-match "@[^\\.]*\\." from))
+ (gnus-yes-or-no-p
+ (format "The From looks strange: \"%s\". Really post? "
+ from))))))))
+ ;; Check for long lines.
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "$"))
+ (while (and
+ (progn
+ (end-of-line)
+ (< (current-column) 80))
+ (zerop (forward-line 1))))
+ (or (bolp)
+ (gnus-yes-or-no-p
+ (format
+ "You have lines longer than 79 characters. Really post? "))))
+ ;; Check for control characters.
+ (save-excursion
+ (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
+ (gnus-y-or-n-p
+ "The article contains control characters. Really post? ")
+ t))
+ ;; Check excessive size.
+ (if (> (buffer-size) 60000)
+ (gnus-y-or-n-p (format "The article is %d octets long. Really post? "
+ (buffer-size)))
+ t)
+ ;; Use the (size . checksum) variable to see whether the
+ ;; article is empty or has only quoted text.
+ (if (and (= (buffer-size) (car gnus-article-check-size))
+ (= (gnus-article-checksum) (cdr gnus-article-check-size)))
+ (gnus-yes-or-no-p
+ "It looks like there's no new text in your article. Really post? ")
+ t))))
(defun gnus-article-checksum ()
(let ((sum 0))
(not
(gnus-y-or-n-p
(format
- "Your .sig is %d lines; it should be max 4. Really post? "
+ "Your .sig is %d lines; it should be max 4. Really post? "
b)))
(if (file-exists-p signature)
(error (format "Edit %s." signature))
;; Should return a status string (not in the nntp buffer, but as the
;; result of the function).
;;
+;; `choke-retrieve-groups GROUPS &optional SERVER'
+;; Optional function for retrieving active file info on all groups in
+;; GROUPS. Two return formats are supported: The normal active file
+;; format, and a list of GROUP lines. This function should return (as
+;; a function value) either `active' or `group', depending on what
+;; format it returns.
+;;
;; The following functions are optional and apply only to backends
;; that are able to control the contents of their groups totally
;; (ie. mail backends.) Backends that aren't able to do that
(funcall (gnus-get-function method 'retrieve-headers)
articles (gnus-group-real-name group) (nth 1 method))))
+(defun gnus-retrieve-groups (groups method)
+ (funcall (gnus-get-function method 'retrieve-groups) groups (nth 1 method)))
+
(defun gnus-request-article (article group &optional buffer)
(let ((method (gnus-find-method-for-group group)))
(funcall (gnus-get-function method 'request-article)
(funcall (gnus-get-function method 'request-create-group)
(gnus-group-real-name group) (nth 1 method))))
-(defun gnus-find-method-for-group (group)
+(defun gnus-find-method-for-group (group &optional info)
(or gnus-override-method
(and (not group)
gnus-select-method)
- (let ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
+ (let ((info (or info (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))
method)
(if (or (not info)
(not (setq method (nth 4 info))))
(gnus-server-extend-method group method))
(t
method))))
- (let ((method-name (symbol-name (car method))))
- (if (and (memq 'address (assoc method-name
- gnus-valid-select-methods))
- (not (assq (intern (concat method-name "-address"))
- method)))
- (setq method
- (append method
- (list (list (intern (concat
- method-name "-address"))
- (nth 1 method)))))))
- method)))
-
+ (gnus-server-add-address method))))
(defun gnus-check-backend-function (func group)
(let ((method (if (stringp group) (car (gnus-find-method-for-group group))
(let ((init (not (and gnus-newsrc-assoc gnus-active-hashtb (not rawfile)))))
;; Clear some variables to re-initialize news information.
(if init (setq gnus-newsrc-assoc nil gnus-active-hashtb nil))
+
+ ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
+ (if init (gnus-read-newsrc-file rawfile))
+
;; Read the active file and create `gnus-active-hashtb'.
;; If `gnus-read-active-file' is nil, then we just create an empty
;; hash table. The partial filling out of the hash table will be
(gnus-read-active-file)
(setq gnus-active-hashtb (make-vector 4095 0)))
- ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
- (if init (gnus-read-newsrc-file rawfile))
;; Find the number of unread articles in each non-dead group.
- (gnus-get-unread-articles (or level 6))
+ (gnus-get-unread-articles (or level (1+ gnus-level-subscribed)))
;; Find new newsgroups and treat them.
(if (and init gnus-check-new-newsgroups gnus-read-active-file (not level)
(gnus-server-opened gnus-select-method))
gnus-active-hashtb)
(while groups
(if (gnus-gethash (car groups) gnus-active-hashtb)
- (gnus-group-change-level (car groups) 3 9))
+ (gnus-group-change-level
+ (car groups) gnus-level-default-subscribed gnus-level-killed))
(setq groups (cdr groups)))
(gnus-group-make-help-group)
(and gnus-novice-user
(setq group entry))
(if (and (stringp entry)
oldlevel
- (< oldlevel 8))
+ (< oldlevel gnus-level-zombie))
(setq entry (gnus-gethash entry gnus-newsrc-hashtb)))
(if (and (not oldlevel)
(listp entry))
;; If the group was killed, we remove it from the killed or zombie
;; list. If not, and it is in fact going to be killed, we remove
;; it from the newsrc hash table and assoc.
- (cond ((>= oldlevel 8)
- (if (= oldlevel 8)
+ (cond ((>= oldlevel gnus-level-zombie)
+ (if (= oldlevel gnus-level-zombie)
(setq gnus-zombie-list (delete group gnus-zombie-list))
(setq gnus-killed-list (delete group gnus-killed-list))))
(t
- (if (>= level 8)
+ (if (>= level gnus-level-zombie)
(progn
(gnus-sethash (car (nth 2 entry))
nil gnus-newsrc-hashtb)
;; Finally we enter (if needed) the list where it is supposed to
;; go, and change the subscription level. If it is to be killed,
;; we enter it into the killed or zombie list.
- (cond ((>= level 8)
+ (cond ((>= level gnus-level-zombie)
(and (string= group (gnus-group-real-name group))
- (if (= level 8)
+ (if (= level gnus-level-zombie)
(setq gnus-zombie-list (cons group gnus-zombie-list))
(setq gnus-killed-list (cons group gnus-killed-list)))))
(t
;; If the list is to be entered into the newsrc assoc, and
;; it was killed, we have to create an entry in the newsrc
;; hashtb format and fix the pointers in the newsrc assoc.
- (if (>= oldlevel 8)
+ (if (>= oldlevel gnus-level-zombie)
(progn
(if (listp entry)
(progn
(defun gnus-kill-newsgroup (newsgroup)
"Obsolete function. Kills a newsgroup."
- (gnus-group-change-level (gnus-gethash newsgroup gnus-newsrc-hashtb) 9))
+ (gnus-group-change-level
+ (gnus-gethash newsgroup gnus-newsrc-hashtb) gnus-level-killed))
(defun gnus-check-bogus-newsgroups (&optional confirm)
"Remove bogus newsgroups.
;; then removing them from the list of killed groups.
(while bogus
(gnus-group-change-level
- (gnus-gethash (car bogus) gnus-newsrc-hashtb) 9)
+ (gnus-gethash (car bogus) gnus-newsrc-hashtb) gnus-level-killed)
(setq gnus-killed-list (delete (car bogus) gnus-killed-list))
(setq bogus (cdr bogus)))
;; Then we remove all bogus groups from the list of killed and
;; and compute how many unread articles there are in each group.
(defun gnus-get-unread-articles (&optional level)
(let ((newsrc (cdr gnus-newsrc-assoc))
- (level (or level 6))
+ (level (or level (1+ gnus-level-subscribed)))
info group active virtuals)
(message "Checking new news...")
(while newsrc
(defun gnus-read-active-file ()
"Get active file from NNTP server."
(gnus-group-set-mode-line)
- (let ((methods (cons gnus-select-method gnus-secondary-select-methods)))
+ (let ((methods (cons gnus-select-method gnus-secondary-select-methods))
+ list-type)
(setq gnus-have-read-active-file nil)
- (while methods
- (let* ((where (nth 1 (car methods)))
- (mesg (format "Reading active file%s via %s..."
- (if (and where (not (zerop (length where))))
- (concat " from " where) "")
- (car (car methods)))))
- (message mesg)
- (gnus-check-news-server (car methods))
- (if (gnus-request-list (car methods)) ; Get active
- (save-excursion
- (set-buffer nntp-server-buffer)
+ (save-excursion
+ (set-buffer nntp-server-buffer)
+ (while methods
+ (let* ((where (nth 1 (car methods)))
+ (mesg (format "Reading active file%s via %s..."
+ (if (and where (not (zerop (length where))))
+ (concat " from " where) "")
+ (car (car methods)))))
+ (message mesg)
+ (gnus-check-news-server (car methods))
+ (cond
+ ((and (eq gnus-read-active-file 'some)
+ (gnus-check-backend-function
+ 'retrieve-groups (car (car methods))))
+ (let ((newsrc (cdr gnus-newsrc-assoc))
+ groups)
+ (while newsrc
+ (and (gnus-server-equal
+ (gnus-find-method-for-group
+ (car (car newsrc)) (car newsrc))
+ (gnus-server-get-method nil (car methods)))
+ (setq groups (cons (car (car newsrc)) groups)))
+ (setq newsrc (cdr newsrc)))
+ (setq list-type (gnus-retrieve-groups groups (car methods)))
+ (cond ((not list-type)
+ (message "Cannot read partial active file from %s server."
+ (car (car methods)))
+ (ding))
+ ((eq list-type 'active)
+ (gnus-active-to-gnus-format
+ (and gnus-have-read-active-file (car methods)))
+ (setq gnus-have-read-active-file t))
+ (t
+ (gnus-groups-to-gnus-format
+ (and gnus-have-read-active-file (car methods)))
+ (setq gnus-have-read-active-file t)))))
+ (t
+ (if (not (gnus-request-list (car methods)))
+ (progn
+ (message "Cannot read active file from %s server."
+ (car (car methods)))
+ (ding))
(gnus-active-to-gnus-format
(and gnus-have-read-active-file (car methods)))
(setq gnus-have-read-active-file t)
- (message "%s...done" mesg))
- (message "Cannot read active file from %s server."
- (car (car methods)))
- (ding)))
- (setq methods (cdr methods)))))
+ (message "%s...done" mesg)))))
+ (setq methods (cdr methods))))))
;; rewritten by jwz based on ideas from Rick Sladkey <jrs@world.std.com>
;; Further rewrites by lmi.
(error
(progn (ding) (message "Possible error in active file."))))))))
+(defun gnus-groups-to-gnus-format (method &optional hashtb)
+ ;; Parse a "groups" active file.
+ (let ((cur (current-buffer))
+ (hashtb (or hashtb
+ (if method
+ gnus-active-hashtb
+ (setq gnus-active-hashtb
+ (gnus-make-hashtable
+ (count-lines (point-min) (point-max)))))))
+ (prefix (and method (not (eq method gnus-select-method))
+ (gnus-group-prefixed-name "" method))))
+
+ (goto-char (point-min))
+ (condition-case ()
+ ;; 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)
+ (while (not (eobp))
+ (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))
+ (forward-line 1)))
+ (let (min max opoint)
+ (while (not (eobp))
+ (read cur) (read cur)
+ (setq min (read cur)
+ max (read cur))
+ (set (let ((obarray hashtb)) (read cur))
+ (cons min max))
+ (forward-line 1))))
+ (error
+ (progn (ding) (message "Possible error in active file."))))))
+
(defun gnus-read-newsrc-file (&optional force)
"Read startup file.
If FORCE is non-nil, the .newsrc file is read."
(if info
(progn
(setcar (nthcdr 2 info) (cdr (cdr group)))
- (setcar (cdr info) (if (nth 1 group) 3 6))
+ (setcar (cdr info)
+ (if (nth 1 group) gnus-level-default-subscribed
+ gnus-level-default-unsubscribed))
(setq gnus-newsrc-assoc (cons info gnus-newsrc-assoc)))
(setq gnus-newsrc-assoc
(cons
(setq info
(list (car group)
- (if (nth 1 group) 3 6) (cdr (cdr group))))
+ (if (nth 1 group) gnus-level-default-subscribed
+ gnus-level-default-unsubscribed)
+ (cdr (cdr group))))
gnus-newsrc-assoc)))
(if (setq m (assoc (car group) marked))
(setcdr (cdr (cdr info)) (cons (list (cons 'tick (cdr m))) nil))))
;; only change it if there's been a status change
;; from subscribed to unsubscribed, or vice versa.
(setq level (nth 1 info))
- (cond ((and (<= level 5) (not subscribe))
- (setq level (if read-list 6 7)))
- ((and (> level 5) subscribe)
- (setq level 3)))
+ (cond ((and (<= level gnus-level-subscribed) (not subscribe))
+ (setq level (if read-list
+ gnus-level-default-unsubscribed
+ (1+ gnus-level-default-unsubscribed))))
+ ((and (> level gnus-level-subscribed) subscribe)
+ (setq level gnus-level-default-subscribed)))
(setcar (cdr info) level))
(setq gnus-newsrc-assoc
- (cons (list newsgroup (if subscribe 3 (if read-list 6 7))
+ (cons (list newsgroup
+ (if subscribe
+ gnus-level-default-subscribed
+ (if read-list gnus-level-default-subscribed
+ (1+ gnus-level-default-subscribed)))
(nreverse read-list))
gnus-newsrc-assoc))))))
(setq line (1+ line))
(setq info (car newsrc))
(if (not (nth 4 info)) ;Don't write foreign groups to .newsrc.
(progn
- (insert (car info) (if (>= (nth 1 info) 6) "!" ":"))
+ (insert (car info) (if (> (nth 1 info) gnus-level-subscribed)
+ "!" ":"))
(if (setq ranges (nth 2 info))
(progn
(insert " ")
(gnus-server-position-cursor))))))
(defun gnus-server-set-info (info)
+ ;; Enter a select method into the virtual server alist.
(gnus-dribble-enter
(concat "(gnus-server-set-info '"
(prin1-to-string info) ")"))
(nconc gnus-server-alist (list (cons server info)))))))
(defun gnus-server-to-method (server)
+ ;; Map virtual server names to select methods.
(cdr (assoc server gnus-server-alist)))
(defun gnus-server-extend-method (group method)
+ ;; This function "extends" a virtual server. If the server is
+ ;; "hello", and the select method is ("hello" (my-var "something"))
+ ;; in the group "alt.alt", this will result in a new virtual server
+ ;; called "helly+alt.alt".
(let ((entry
- (gnus-copy-sequence (cdr (assoc (car method) gnus-server-alist)))))
+ (gnus-copy-sequence
+ (if (equal (car method) "native") gnus-select-method
+ (cdr (assoc (car method) gnus-server-alist))))))
(setcar (cdr entry) (concat (nth 1 entry) "+" group))
(nconc entry (cdr method))))
(defun gnus-server-get-method (group method)
+ ;; Input either a server name, and extended server name, or a
+ ;; select method, and return a select method.
(cond ((stringp method)
(gnus-server-to-method method))
((stringp (car method))
(gnus-server-extend-method group method))
(t
- method)))
+ (gnus-server-add-address method))))
+
+(defun gnus-server-add-address (method)
+ (let ((method-name (symbol-name (car method))))
+ (if (and (memq 'address (assoc method-name gnus-valid-select-methods))
+ (not (assq (intern (concat method-name "-address")) method)))
+ (append method (list (list (intern (concat method-name "-address"))
+ (nth 1 method))))
+ method)))
+
+(defun gnus-server-equal (s1 s2)
+ (or (equal s1 s2)
+ (and (= (length s1) (length s2))
+ (progn
+ (while (and s1 (member (car s1) s2))
+ (setq s1 (cdr s1)))
+ (null s1)))))
;;; Interactive server functions.
\input texinfo @c -*-texinfo-*-
@comment %**start of header (This is for running Texinfo on a region.)
@setfilename gnus
-@settitle Gnus 0.51 Manual
+@settitle Gnus 0.54 Manual
@synindex fn cp
@synindex vr cp
@synindex pg cp
Note that if you subscribe to lots and lots of groups, setting this
variable to @code{nil} will probabaly make Gnus slower, not faster. At
present, having this variable @code{nil} will slow Gnus down
-considerably, unless you read news over a 2400 baud modem. Gnus does
-the group info fetching in total lock-step, so if you have this variable
-@code{nil}, you should kill all groups that you aren't interested in to
-speed things up.
+considerably, unless you read news over a 2400 baud modem.
-There are plans for doing lots of Gnus stuff asynchronously, which
-should make this option more useful, but that's probably some ways off
-in the future.
+This variable can also have the value @code{some}. Gnus will then
+attempt to read active info only on the subscribed groups. On some
+servers this is quite fast (on sparkling, brand new INN servers that
+support the @samp{LIST ACTIVE group} command), on others this is not
+fast at all. In any case, @code{some} should be faster than @code{nil},
+and is certainly faster than @code{t} over slow lines.
+
+If this variable is @code{nil}, Gnus will as for group info in total
+lock-step, which isn't very fast. If it is @code{some} and you use an
+NNTP server, Gnus will pump out commands as fast as it can, and read all
+the replies in one swoop. This will normally result in better
+performance, but if the server does not support the aforementioned
+@samp{LIST ACTIVE group} command, this isn't very nice to the server.
+
+In any case, if you use @code{some} or @code{nil}, you should kill all
+groups that you aren't interested in.
@node Startup Variables
@section Startup Variables
* Group Subscribing:: Unsubscribing, killing, subscribing.
* Group Levels:: Levels? What are those, then?
* Foreign Groups:: How to create foreign groups.
+* Group Parameters:: Each group may have different parameters set.
* Listing Groups:: Gnus can list various subsets of the groups.
* Group Maintenance:: Maintaining a tidy @file{.newsrc} file.
* Browse Foreign Server:: You can browse a server. See what if has to offer.
prefix is given, this command will prompt the user for a level.
@end table
-Gnus considers groups on levels 1-5 to be subscribed, 6-7 to be
-unsubscribed, 8 to be zombies (walking dead) and 9 to be killed,
-completely dead. Gnus treats subscribed and unsubscribed groups exactly
-the same, but zombie and killed groups have no information on what
-articles you have read, etc, stored. This distinction between dead and
-living groups isn't done because it is nice or clever, it is done purely
-for reasons of efficiency. On the other hand, if you would like a finer
-granularity to the levels - you're out of luck. The nine levels are
-hardcoded into the source. Sorry.
-
-It is recommended that you keep all regular groups on level 3 or higher,
-and keep your mail groups (if any) on level 1 or 2.
+@vindex gnus-level-killed
+@vindex gnus-level-zombie
+@vindex gnus-level-unsubscribed
+@vindex gnus-level-subscribed
+Gnus considers groups on between levels 1 and
+@code{gnus-level-subscribed} (inclusive) to be subscribed,
+@code{gnus-level-subscribed} (ecxlusive) and
+@code{gnus-level-unsubscribed} (inclusive) to be unsubscribed,
+@code{gnus-level-zombie} to be zombies (walking dead) and
+@code{gnus-level-killed} to be killed, completely dead. Gnus treats
+subscribed and unsubscribed groups exactly the same, but zombie and
+killed groups have no information on what articles you have read, etc,
+stored. This distinction between dead and living groups isn't done
+because it is nice or clever, it is done purely for reasons of
+efficiency.
+
+It is recommended that you keep all your mail groups (if any) on quite
+low levels (eg. 1 or 2).
+
+If you want to play with the level variables, you should show some care.
+Set them once, and don't touch them ever again.
+
+@vindex gnus-level-default-unsubscribed
+@vindex gnus-level-default-subscribed
+Two closely related variables are @code{gnus-level-default-subscribed}
+and @code{gnus-level-default-unsubscribed}, which are the leves that new
+groups will be put on if they are (un)subscribed. These two variables
+should, of course, be inside the relevant legal ranges.
@vindex gnus-keep-same-level
If @code{gnus-keep-same-level} is non-@code{nil}, some movement commands
A foreign group (or any group, really) is specified by a @dfn{name} and
a @dfn{select method}. To take the latter first, a select method is a
list where the first element says what backend to use (eg. nntp,
-nnspool, nnml) and the second element is the @dfn{address}, in some
-meaning of the word. There may be additional elements in the select
-method, where the value may have special meaning for the backend in
-question.
+nnspool, nnml) and the second element is the @dfn{server name}. There
+may be additional elements in the select method, where the value may
+have special meaning for the backend in question.
+
+One could say that a select method defines a @dfn{virtual server} - so
+we do just that (@pxref{The Server Buffer}).
The @dfn{name} of the group is the name the backend will recognize the
group as.
to subscribe to @sc{nntp} groups, @xref{Browse Foreign Server}.
@item M e
@kindex M e (Group)
+@findex gnus-group-edit-group-method
+Enter a buffer where you can edit the select method of the current
+group (@code{gnus-group-edit-group-method}).
+@item M p
+@kindex M p (Group)
+@findex gnus-group-edit-group-parameters
+Enter a buffer where you can edit the group parameters
+(@code{gnus-group-edit-group-parameters}).
+@item M E
+@kindex M E (Group)
@findex gnus-group-edit-group
-Edit a group entry. Gnus will pop up a new buffer where you can edit
-the entry (@code{gnus-group-edit-group}).
+Enter a buffer where you can edit the group info
+(@code{gnus-group-edit-group}).
@item M d
@kindex M d (Group)
@findex gnus-group-make-directory-group
when, or if, you decide to enter them. You can also activate any group
with @kbd{M-g} to see how many unread articles there are.
-@cindex to-address
-If the select method contains an element that looks like
-@samp{(to-address . "some@@where.com")}, that address will be used by
-the backend when doing followups and posts. This is primarily useful in
-mail groups that represent mailing lists. You just set this address to
-whatever the list address is.
-
-This trick will actually work whether the group is foreign or not.
-Let's say there's a group on the server that is called @samp{fa.4ad-l}.
-This is a real newsgroup, but the server has gotten the articles from a
-mail-to-news gateway. Posting directly to this group is therefore
-impossible - you have to send mail to the mailing list address instead.
-
-To achieve this, go to the group in question in the group buffer and
-type @kbd{M e} to edit the group entry. You'll then be put in a buffer
-where you can edit the group entry.
-
-@lisp
-(gnus-group-set-info
- '("ifi.fritt-forum" 3
- ((1 . 3321)
- (3325 . 3325))
- ((score
- (3322 . 1000)
- (3324 . 1000)))))
-@end lisp
-
-A fifth entry has to be added. (In case there isn't a fourth one, you
-have to add a fourth one yourself - @code{nil}.) The fifth entry should
-look like this:
-
-@lisp
-(nntp "your.host" (to-address . "4ad-l@@jhuvm.hcf.jhu.edu"))
-@end lisp
-
-The two first entries in this method should, of course, be the same as
-@code{gnus-select-method}.
-
-Quite simple, eh? <duck> @strong{Ouch}.
-
@node nntp
@subsection nntp
@cindex @sc{nntp}
fact, you can subscribe to the same group from as many different servers
you feel like. There will be no name collisions.
+The following variables can be used to create a virtual @code{nntp}
+server:
+
+@table @code
+@item nntp-server-opened-hook
+@vindex nntp-server-opened-hook
@cindex @sc{mode reader}
@cindex authinfo
@findex nntp-send-authinfo
@findex nntp-send-mode-reader
-@vindex nntp-server-opened-hook
@code{nntp-server-opened-hook} is run after a connection has been made.
It can be used to send commands to the @sc{nntp} server after it has
been contacted. By default is sends the command @samp{MODE READER} to
popular function is @code{nntp-send-authinfo}, which will prompt you for
an @sc{nntp} password and stuff.
+@item nntp-maximum-request
@vindex nntp-maximum-request
If the @sc{nntp} server doesn't support @sc{nov} headers, this backend
will collect headers by sending a series of @code{head} commands. To
by the @code{nntp-maximum-request} variable, and is 400 by default. If
your network is buggy, you should set this to 1.
+@item nntp-connection-timeout
@vindex nntp-connection-timeout
-If you have lots of foreign nntp groups that you connect to regularly,
-you're sure to have problems with nntp servers not responding properly,
-or being too loaded to reply within reasonable time. This is can lead
-to awkward problems, which can be helped somewhat by setting
-@code{nntp-connection-timeout}. This is an integer that says how many
-seconds the nntp backend should wait for a connection before giving up.
-If it is @code{nil}, which is the default, no timeouts are done.
+If you have lots of foreign @code{nntp} groups that you connect to
+regularly, you're sure to have problems with @sc{nntp} servers not
+responding properly, or being too loaded to reply within reasonable
+time. This is can lead to awkward problems, which can be helped
+somewhat by setting @code{nntp-connection-timeout}. This is an integer
+that says how many seconds the @code{nntp} backend should wait for a
+connection before giving up. If it is @code{nil}, which is the default,
+no timeouts are done.
+
+@item nntp-server-hook
+@vindex nntp-server-hook
+This hook is run as the last step when connecting to an @sc{nntp}
+server.
+
+@findex nntp-open-rlogin
+@findex nntp-open-network-stream
+@item nntp-open-server-function
+@vindex nntp-open-server-function
+This function is used to connect to the remote system. Two pre-made
+functions are @code{nntp-open-network-stream}, which is the default, and
+simply connects to some port or other on the remote system. The other
+is @code{nntp-open-rlogin}, which does an rlogin on the remote system,
+and then does a telnet to the @sc{nntp} server available there.
+
+@item nntp-rlogin-parameters
+@vindex nntp-rlogin-parameters
+If you use @code{nntp-open-rlogin} as the
+@code{nntp-open-server-function}, this list will be used as the
+parameter list given to @code{rsh}.
+
+@item nntp-rlogin-user-name
+@vindex nntp-rlogin-user-name
+User name on the remote system when using the @code{rlogin} connect
+function.
+
+@item nntp-address
+@vindex nntp-address
+The address of the remote system running the @sc{nntp} server.
+
+@item nntp-port-number
+@vindex nntp-port-number
+Port number to connect to when using the @code{nntp-open-network-stream}
+connect function.
+
+@item nntp-buggy-select
+@vindex nntp-buggy-select
+Set this to non-@code{nil} if your select routine is buggy.
+
+@item nntp-nov-is-evil
+@vindex nntp-nov-is-evil
+If the @sc{nntp} server does not support @sc{nov}, you could set this
+variable to @code{t}, but @code{nntp} usually checks whether @sc{nov}
+can be used automatically.
+
+@item nntp-xover-commands
+@vindex nntp-xover-commands
+List of strings that are used as commands to fetch @sc{nov} lines from a
+server. The default value of this variable is @code{("XOVER"
+"XOVERVIEW")}.
+
+@item nntp-prepare-server-hook
+@vindex nntp-prepare-server-hook
+A hook run before attempting to connect to an @sc{nntp} server.
+
+@end table
@node nnspool
@subsection nnspool
@table @code
@item nnspool-inews-program
+@vindex nnspool-inews-program
Program used to post an article.
+
+@item nnspool-inews-switches
+@vindex nnspool-inews-switches
+Parameters given to the inews program when posting an article.
+
@item nnspool-spool-directory
+@vindex nnspool-spool-directory
Where nnspool looks for the articles. This is normally
@file{/usr/spool/news/}.
+
@item nnspool-nov-directory
+@vindex nnspool-nov-directory
Where nnspool will look for @sc{nov} files. This is normally
@file{/usr/spool/news/over.view/}.
+
@item nnspool-lib-dir
+@vindex nnspool-lib-dir
Where the news lib dir is (@file{/usr/lib/news/} by default).
+
+@item nnspool-active-file
+@vindex nnspool-active-file
+The path of the active file.
+
+@item nnspool-newsgroups-file
+@vindex nnspool-newsgroups-file
+The path of the group description file.
+
+@item nnspool-history-file
+@vindex nnspool-history-file
+The path of the news history file.
+
+@item nnspool-active-times-file
+@vindex nnspool-active-times-file
+The path of the active date file.
+
+@item nnspool-nov-is-evil
+@vindex nnspool-nov-is-evil
+If non-@code{nil}, @code{nnspool} won't try to use any @sc{nov} files
+that it finds.
@end table
@node nnvirtual
@vindex nnmbox-active-file
@vindex nnmbox-mbox-file
The @dfn{nnmbox} backend will use the standard Un*x mbox file to store
-mail. The path of the mbox file is given by the @code{nnmbox-mbox-file}
-variable. In addition, Gnus needs to store information about active
-articles. The file specified by @code{nnmbox-active-file} will be used
-for that.
+mail. @code{nnmbox} will add extra headers to each mail article to say
+which group it belongs in.
-nnmbox will add extra headers to each mail article to say which
-group it belongs in.
+@table @code
+@item nnmbox-mbox-file
+@vindex nnmbox-mbox-file
+The name of the mail box in the user's home directory.
+
+@item nnmbox-active-file
+@vindex nnmbox-active-file
+The name of the active file for the mail box.
+
+@item nnmbox-get-new-mail
+@vindex nnmbox-get-new-mail
+If non-@code{nil}, @code{nnmbox} will read incoming mail and split it
+into groups.
+@end table
@node nnbabyl
@subsubsection nnbabyl
@vindex nnbabyl-active-file
@vindex nnbabyl-mbox-file
-The @dfn{nnbabyl} backend will use a babyl mail box to store mail. The
-path of the rmail mail box file is given by the @code{nnbabyl-mbox-file}
-variable. In addition, Gnus needs to store information about active
-articles. The file specified by @code{nnbabyl-active-file} will be used
-for that.
-
-nnbabyl will add extra headers to each mail article to say which
+The @dfn{nnbabyl} backend will use a babyl mail box to store mail.
+@code{nnbabyl} will add extra headers to each mail article to say which
group it belongs in.
+@table @code
+@item nnbabyl-mbox-file
+@vindex nnbabyl-mbox-file
+The name of the rmail mbox file.
+
+@item nnbabyl-active-file
+@vindex nnbabyl-active-file
+The name of the active file for the rmail box.
+
+@item nnbabyl-get-new-mail
+@vindex nnbabyl-get-new-mail
+If non-@code{nil}, @code{nnbabyl} will read incoming mail.
+@end table
+
@node nnml
@subsubsection nnml
@cindex nnml
@sc{nov} databases for the incoming mails. This makes is the fastest
backend when it comes to reading mail.
+@table @code
+@item nnml-directory
+@vindex nnml-directory
+All @code{nnml} directories will be placed under this directory.
+
+@item nnml-active-file
+@vindex nnml-active-file
+The active file for the @code{nnml} server.
+
+@item nnml-newsgroups-file
+@vindex nnml-newsgroups-file
+The @code{nnml} group description file.
+
+@item nnml-get-new-mail
+@vindex nnml-get-new-mail
+If non-@code{nil}, @code{nnml} will read incoming mail.
+
+@item nnml-nov-is-evil
+@vindex nnml-nov-is-evil
+If non-@code{nil}, this backend will ignore any @sc{nov} files.
+
+@item nnml-nov-file-name
+@vindex nnml-nov-file-name
+The name of the @sc{nov} files. The default is @file{.overview}.
+
+@end table
+
@findex nnml-generate-nov-databases
If your @code{nnml} groups and @sc{nov} files get totally out of whack,
you can do a complete update by typing @kbd{M-x
@code{nnmh} a @emph{much} slower backend than @code{nnml}, but it also
makes it easier to write procmail scripts for.
+@table @code
+@item nnml-directory
+All @code{nnmh} directories will be located under this directory.
+
+@item nnmh-get-new-mail
+If non-@code{nil}, @code{nnml} will read incoming mail.
+@end table
+
@node nnfolder
@subsubsection nnfolder
@cindex nnfolder
will add extra headers to keep track of article numbers and arrival
dates.
-@vindex nnfolder-active-file
-@vindex nnfolder-directory
-@code{nnfolder-directory} says where to store these files, and
-@code{nnfolder-active-file} says where to store the @dfn{active}
-information.
+@table @code
+@item nnfolder-directory
+All the @code{nnfolder} mail boxes will be stored under this directory.
+
+@item nnfolder-active-file
+The name of the active file.
+
+@item nnfolder-newsgroups-file
+The name of the group description file.
+
+@item nnfolder-get-new-mail
+If non-@code{nil}, @code{nnfolder} will read incoming mail.
+@end table
+
+@node Group Parameters
+@section Group Parameters
+@cindex group parameters
+
+Gnus stores all information on a group in a list that is usually known
+as the @dfn{group info}. This list has from three to six elements.
+Here's an example info.
+
+@lisp
+("nnml:mail.ding" 3 ((1 . 232) 244 (256 . 270)) ((tick 246 249))
+ (nnml "private") ((to-address . "ding@@ifi.uio.no")))
+@end lisp
+
+The first element is the @dfn{group name}, as Gnus knows the group,
+anyway. The second element is the @dfn{subscription level}, which
+normally is a small integer. The third element is a list of ranges of
+read articles. The fourth element is a list of lists of article marks
+of various kinds. The fifth element is the select method (or virtual
+server, if you like). The sixth element is a list of @dfn{group
+parameters}, which is what this section is about.
+
+Any of the last three elements may be missing if they are not required.
+In fact, the vast majority of groups will normally only have the first
+three elements, which saves quite a lot of cons cells.
+
+At present, there's not much you can put in the group parameters list:
+
+@table @code
+@item to-address
+@cindex to-address
+If the group parameter list contains an element that looks like
+@samp{(to-address . "some@@where.com")}, that address will be used by
+the backend when doing followups and posts. This is primarily useful in
+mail groups that represent mailing lists. You just set this address to
+whatever the list address is.
+
+This trick will actually work whether the group is foreign or not.
+Let's say there's a group on the server that is called @samp{fa.4ad-l}.
+This is a real newsgroup, but the server has gotten the articles from a
+mail-to-news gateway. Posting directly to this group is therefore
+impossible - you have to send mail to the mailing list address instead.
+
+@item auto-expire
+@cindex auto-expire
+If this symbol is present in the group parameter list, all articles that
+are read will be marked as expirable. For an alternative approach,
+@xref{Expiring Old Mail Articles}.
+@end table
+
+If you want to change the group parameters (or anything else of the
+group info) you can use the @kbd{M E} to edit enter a buffer where you
+can edit the group info.
+
+You usually don't want to edit the entire group info, so you'd be better
+off using the @kbd{M p} command to just edit the group parameters.
@node Listing Groups
@section Listing Groups
@findex gnus-group-get-new-news-this-group
Check whether new articles have arrived in the current group
(@code{gnus-group-get-new-news-this-group}).
+
+@item ^
+@kindex ^ (Group)
+@findex gnus-group-enter-server-mode
+Enter the server buffer (@code{gnus-group-enter-server-mode}). @xref{The
+Server Buffer}.
+
@item M-f
@kindex M-f (Group)
@findex gnus-group-fetch-faq
to be posted. The hook is called from the @code{*post-news*} buffer,
narrowed to the head, and is intended for people who would like to
insert additional headers, or just change headers in some way or other.
+
+@item gnus-check-before-posting
+@vindex gnus-check-before-posting
+If non-@code{nil}, Gnus will attempt to check the legality of the
+headers, as well as some other stuff, before posting.
+
@end table
immediately. If this variable is @code{not-confirm}, the user won't even
be asked for a confirmation before viewing is done.
+So; there you are, reading your @emph{pseduo-articles} in your
+@emph{virtual newsgroup} from the @emph{virtual server}; and you think:
+Why isn't anything real anymore? How did we get here?
@node Various Article Stuff
@section Various Article Stuff