+Sun Sep 14 21:17:34 1997 Lars Magne Ingebrigtsen <larsi@menja.ifi.uio.no>
+
+ * gnus.el: Quassia Gnus v0.3 is released.
+
+Sun Sep 14 01:51:45 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-agent.el (gnus-agent-short-article): New variables.
+
+ * message.el (message-set-auto-save-file-name): Use drafts.
+
+ * nndraft.el (nndraft-request-expire-articles): Use it.
+
+ * nnmh.el (nnmh-deletable-article-p): Change.
+ (nnmh-allow-delete-final): New variable.
+
+ * gnus-msg.el (gnus-summary-send-draft): Removed.
+
+ * gnus.el (gnus-article-mark-lists): Save unsendable marks.
+
+ * gnus-sum.el (gnus-newsgroup-unsendable): New variable.
+
+ * gnus-draft.el: New file.
+
+ * gnus-sum.el (gnus-unsendable-mark): New variable.
+
+ * nndraft.el (nndraft-execute-nnmh-command): Cleanup.
+
+ * message.el (message-send-news): Use `gnus-request-post'.
+
+ * gnus-agent.el (gnus-agentize): New command.
+
+ * gnus-bcklg.el (gnus-backlog-remove-article): Remove the ident
+ from the list.
+
Sun Sep 14 00:26:47 1997 Lars Magne Ingebrigtsen <larsi@menja.ifi.uio.no>
* gnus.el: Quassia Gnus v0.2 is released.
$(EMACS) $(FLAGS) -f dgnushack-compile
some:
- $(EMACS) $(FLAGS) -f dgnushack-recompile
+ $(EMACS) $(FLAGS) -f dgnushack-compile
tags:
etags *.el
;;; Commentary:
-;; (add-hook 'gnus-before-startup-hook 'gnus-open-agent)
-
;;; Code:
(require 'gnus)
(require 'gnus-cache)
(require 'nnvirtual)
(require 'gnus-sum)
+(eval-when-compile (require 'cl))
(defcustom gnus-agent-directory (nnheader-concat gnus-directory "agent/")
"Where the Gnus agent will store its files."
(defvar gnus-category-group-cache nil)
(defvar gnus-agent-spam-hashtb nil)
(defvar gnus-agent-file-name nil)
+(defvar gnus-agent-send-mail-function nil)
(defvar gnus-plugged t
"Whether Gnus is plugged or not.")
(setq gnus-plugged nil)
(gnus))
+;;;###autoload
+(defun gnus-agentize ()
+ "Allow Gnus to be an offline newsreader.
+The normal usage of this command is to put the following as the
+last form in your `.gnus.el' file:
+
+\(gnus-agentize)
+
+This will modify the `gnus-before-startup-hook', `gnus-post-method',
+and `message-send-mail-function' variables, and install the Gnus
+agent minor mode in all Gnus buffers."
+ (interactive)
+ (add-hook 'gnus-before-startup-hook 'gnus-open-agent)
+ (setq gnus-agent-send-mail-function message-send-mail-function
+ message-send-mail-function 'gnus-agent-send-mail))
+
+(defun gnus-agent-send-mail ()
+ (if gnus-plugged
+ (funcall gnus-agent-send-mail-function)
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (replace-match "\n")
+ (gnus-request-accept-article "nndraft:drafts")))
+
;;;
;;; Group mode commands
;;;
(defvar gnus-category-mode-line-format "Gnus: %%b"
"The format specification for the category mode line.")
+(defvar gnus-agent-short-article 100
+ "Articles that have fewer lines than this are short.")
+
+(defvar gnus-agent-long-article 200
+ "Articles that have more lines than this are long.")
+
+(defvar gnus-agent-low-score 0
+ "Articles that have a score lower than this have a low score.")
+
+(defvar gnus-agent-high-score 0
+ "Articles that have a score higher than this have a high score.")
+
+
;;; Internal variables.
(defvar gnus-category-buffer "*Agent Category*")
(gnus-sethash string t gnus-agent-spam-hashtb)))))
(defun gnus-agent-short-p ()
- "Say whether an article is short (less than 100 lines) or not."
- (< (mail-header-lines gnus-headers) 100))
+ "Say whether an article is short or not."
+ (< (mail-header-lines gnus-headers) gnus-agent-short-article))
(defun gnus-agent-long-p ()
- "Say whether an article is long (more than 200 lines) or not."
- (> (mail-header-lines gnus-headers) 200))
+ "Say whether an article is long or not."
+ (> (mail-header-lines gnus-headers) gnus-agent-long-article))
(defun gnus-agent-low-scored-p ()
"Say whether an article has a low score or not."
- (< gnus-score gnus-summary-default-score))
+ (< gnus-score gnus-agent-low-score))
(defun gnus-agent-high-scored-p ()
"Say whether an article has a high score or not."
- (> gnus-score gnus-summary-default-score))
+ (> gnus-score gnus-agent-low-score))
(defun gnus-category-make-function (cat)
"Make a function from category CAT."
(1+ beg) 'gnus-backlog (current-buffer) (point-max)))
(delete-region beg end)
;; Return success.
- t)))))))
+ t))
+ (setq gnus-backlog-articles (delq ident gnus-backlog-articles)))))))
(defun gnus-backlog-request-article (group number buffer)
(when (numberp number)
--- /dev/null
+;;; gnus-draft.el --- draft message support for Gnus
+;; Copyright (C) 1997 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'gnus)
+(require 'gnus-sum)
+(require 'message)
+(require 'gnus-msg)
+(eval-when-compile (require 'cl))
+
+;;; Draft minor mode
+
+(defvar gnus-draft-mode nil
+ "Minor mode for providing a draft summary buffers.")
+
+(defvar gnus-draft-mode-map nil)
+
+(unless gnus-draft-mode-map
+ (setq gnus-draft-mode-map (make-sparse-keymap))
+
+ (gnus-define-keys gnus-draft-mode-map
+ "Dt" gnus-draft-toggle-sending
+ "De" gnus-draft-edit-message
+ "Ds" gnus-draft-send-message
+ "DS" gnus-draft-send-all-messages))
+
+(defun gnus-draft-make-menu-bar ()
+ (unless (boundp 'gnus-draft-menu)
+ (easy-menu-define
+ gnus-draft-menu gnus-draft-mode-map ""
+ '("Drafts"
+ ["Toggle whether to send" gnus-draft-toggle-sending t]))))
+
+(defun gnus-draft-mode (&optional arg)
+ "Minor mode for providing a draft summary buffers.
+
+\\{gnus-draft-mode-map}"
+ (interactive "P")
+ (when (eq major-mode 'gnus-summary-mode)
+ (if (not (set (make-local-variable 'gnus-draft-mode)
+ (if (null arg) (not gnus-draft-mode)
+ (> (prefix-numeric-value arg) 0))))
+ (remove-hook 'gnus-message-setup-hook 'gnus-draft-setup-message)
+ ;; Set up the menu.
+ (when (gnus-visual-p 'draft-menu 'menu)
+ (gnus-draft-make-menu-bar))
+ (gnus-add-minor-mode 'gnus-draft-mode " Draft" gnus-draft-mode-map)
+ (run-hooks 'gnus-draft-mode-hook))))
+
+;;; Commands
+
+(defun gnus-draft-toggle-sending (article)
+ "Toggle whether to send an article or not."
+ (interactive (list (gnus-summary-article-number)))
+ (if (gnus-draft-article-sendable-p article)
+ (progn
+ (push article gnus-newsgroup-unsendable)
+ (gnus-summary-mark-article article gnus-unsendable-mark))
+ (setq gnus-newsgroup-unsendable
+ (delq article gnus-newsgroup-unsendable))
+ (gnus-summary-mark-article article gnus-unread-mark))
+ (gnus-summary-position-point))
+
+(defun gnus-draft-edit-message ()
+ "Enter a mail/post buffer to edit and send the draft."
+ (interactive)
+ (gnus-set-global-variables)
+ (let ((article (gnus-summary-article-number)))
+ (gnus-draft-setup article)
+ (push
+ `((lambda ()
+ (when (buffer-name (get-buffer ,gnus-summary-buffer))
+ (save-excursion
+ (set-buffer (get-buffer ,gnus-summary-buffer))
+ (gnus-cache-possibly-remove-article ,article nil nil nil t)
+ (gnus-summary-mark-as-read ,article gnus-canceled-mark)))))
+ message-send-actions)))
+
+(defun gnus-draft-send-message (&optional n)
+ "Send the current draft."
+ (interactive "P")
+ (gnus-set-global-variables)
+ (let ((articles (gnus-summary-work-articles n))
+ article)
+ (while (setq article (pop articles))
+ (gnus-summary-remove-process-mark article)
+ (unless (memq article gnus-newsgroup-unsendable)
+ (gnus-draft-send article)
+ (gnus-summary-mark-article article gnus-canceled-mark)))))
+
+(defun gnus-draft-send (article)
+ "Send message ARTICLE."
+ (gnus-draft-setup article)
+ (message-send-and-exit))
+
+(defun gnus-draft-send-all-messages ()
+ "Send all the sendable drafts."
+ (interactive)
+ (gnus-uu-mark-buffer)
+ (gnus-draft-send-message))
+
+;;; Utility functions
+
+(defun gnus-draft-setup (article)
+ (gnus-setup-message 'forward
+ (message-mail)
+ (erase-buffer)
+ (if (not (gnus-request-restore-buffer article gnus-newsgroup-name))
+ (error "Couldn't restore the article")
+ ;; Insert the separator.
+ (goto-char (point-min))
+ (search-forward "\n\n")
+ (forward-char -1)
+ (insert mail-header-separator)
+ (forward-line 1)
+ (save-buffer 0))))
+
+(defun gnus-draft-article-sendable-p (article)
+ "Say whether ARTICLE is sendable."
+ (not (memq article gnus-newsgroup-unsendable)))
+
+(provide 'gnus-draft)
+
+;;; gnus-draft.el ends here
+
article (gnus-group-real-name group)
(nth 1 gnus-command-method) accept-function last)))
-(defun gnus-request-accept-article (group gnus-command-method &optional last)
+(defun gnus-request-accept-article (group &optional gnus-command-method last)
;; Make sure there's a newline at the end of the article.
(when (stringp gnus-command-method)
(setq gnus-command-method (gnus-server-to-method gnus-command-method)))
(insert " ")))
(insert "\n")))))))
-(defun gnus-summary-send-draft ()
- "Enter a mail/post buffer to edit and send the draft."
- (interactive)
- (gnus-set-global-variables)
- (let (buf)
- (if (not (setq buf (gnus-request-restore-buffer
- (gnus-summary-article-number) gnus-newsgroup-name)))
- (error "Couldn't restore the article")
- (switch-to-buffer buf)
- (when (eq major-mode 'news-reply-mode)
- (local-set-key "\C-c\C-c" 'gnus-inews-news))
- ;; Insert the separator.
- (goto-char (point-min))
- (search-forward "\n\n")
- (forward-char -1)
- (insert mail-header-separator)
- ;; Configure windows.
- (let ((gnus-draft-buffer (current-buffer)))
- (gnus-configure-windows 'draft t)
- (goto-char (point))))))
-
(gnus-add-shutdown 'gnus-inews-close 'gnus)
(defun gnus-inews-close ()
;; Do the actual startup.
(gnus-setup-news nil level dont-connect)
+ (gnus-draft-setup)
;; Generate the group buffer.
(gnus-group-list-groups level)
(gnus-group-first-unread-group)
(gnus-group-set-mode-line)
(run-hooks 'gnus-started-hook))))))
+(defun gnus-draft-setup ()
+ "Make sure the draft group exists."
+ (unless (gnus-gethash "nndraft:draft" gnus-newsrc-hashtb)
+ (gnus-request-create-group "draft" '(nndraft ""))
+ (let ((gnus-level-default-subscribed 1))
+ (gnus-subscribe-group "nndraft:draft" nil '(nndraft "")))
+ (gnus-group-set-parameter
+ "nndraft:draft" 'gnus-dummy '((gnus-draft-mode)))))
+
;;;###autoload
(defun gnus-unload ()
"Unload all Gnus features."
:group 'gnus-summary-marks
:type 'character)
+(defcustom gnus-unsendable-mark ?=
+ "*Mark used for articles that won't be sent."
+ :group 'gnus-summary-marks
+ :type 'character)
+
(defcustom gnus-score-over-mark ?+
"*Score mark used for articles with high scores."
:group 'gnus-summary-marks
(defvar gnus-newsgroup-undownloaded nil
"List of articles in the current newsgroup that haven't been downloaded..")
+(defvar gnus-newsgroup-unsendable nil
+ "List of articles in the current newsgroup that won't be sent.")
+
(defvar gnus-newsgroup-bookmarks nil
"List of articles in the current newsgroup that have bookmarks.")
gnus-newsgroup-replied gnus-newsgroup-expirable
gnus-newsgroup-processable gnus-newsgroup-killed
gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
+ gnus-newsgroup-unsendable
gnus-newsgroup-bookmarks gnus-newsgroup-dormant
gnus-newsgroup-headers gnus-newsgroup-threads
gnus-newsgroup-prepared gnus-summary-highlight-line-function
(defmacro gnus-article-mark (number)
`(cond
+ ((memq ,number gnus-newsgroup-unsendable) gnus-unsendable-mark)
((memq ,number gnus-newsgroup-undownloaded) gnus-undownloaded-mark)
((memq ,number gnus-newsgroup-downloadable) gnus-downloadable-mark)
((memq ,number gnus-newsgroup-unreads) gnus-unread-mark)
(vertical 1.0
(article 0.5)
(message 1.0 point)))
- (draft
- (vertical 1.0
- (draft 1.0 point)))
(pipe
(vertical 1.0
(summary 0.25 point)
:link '(custom-manual "(gnus)Exiting Gnus")
:group 'gnus)
-(defconst gnus-version-number "0.2"
+(defconst gnus-version-number "0.3"
"Version number for this version of Gnus.")
(defconst gnus-version (format "Quassia Gnus v%s" gnus-version-number)
(expirable . expire) (killed . killed)
(bookmarks . bookmark) (dormant . dormant)
(scored . score) (saved . save)
- (cached . cache) (downloadable . download)))
+ (cached . cache) (downloadable . download)
+ (unsendable . unsend)))
(defvar gnus-headers-retrieved-by nil)
(defvar gnus-article-reply nil)
gnus-async-prefetch-article gnus-async-prefetch-remove-group
gnus-async-halt-prefetch)
("gnus-agent" gnus-open-agent gnus-agent-get-function
- gnus-agent-save-groups gnus-agent-save-active)
+ gnus-agent-save-groups gnus-agent-save-active gnus-agent-method-p)
("gnus-agent" :interactive t
gnus-unplugged)
("gnus-vm" :interactive t gnus-summary-save-in-vm
- gnus-summary-save-article-vm))))
+ gnus-summary-save-article-vm)
+ ("gnus-draft" :interactive t gnus-draft-mode))))
;;; gnus-sum.el thingies
:type 'file
:group 'message-headers)
-(defcustom message-autosave-directory "~/"
- ; (concat (file-name-as-directory message-directory) "drafts/")
- "*Directory where message autosaves buffers.
-If nil, message won't autosave."
+(defcustom message-autosave-directory
+ (nnheader-concat message-directory "drafts/")
+ "*Directory where Message autosaves buffers.
+If nil, Message won't autosave."
:group 'message-buffers
:type 'directory)
(defvar message-buffer-list nil)
(defvar message-this-is-news nil)
(defvar message-this-is-mail nil)
+(defvar message-draft-article nil)
;; Byte-compiler warning
(defvar gnus-active-hashtb)
(make-local-variable 'message-exit-actions)
(make-local-variable 'message-kill-actions)
(make-local-variable 'message-postpone-actions)
+ (make-local-variable 'message-draft-article)
(set-syntax-table message-mode-syntax-table)
(use-local-map message-mode-map)
(setq local-abbrev-table message-mode-abbrev-table)
(if (fboundp 'mail-abbrevs-setup)
(mail-abbrevs-setup)
(funcall (intern "mail-aliases-setup"))))
+ (message-set-auto-save-file-name)
(run-hooks 'text-mode-hook 'message-mode-hook))
\f
;; (mail-hist-put-headers-into-history))
(run-hooks 'message-sent-hook)
(message "Sending...done")
- ;; If buffer has no file, mark it as unmodified and delete autosave.
- (unless buffer-file-name
- (set-buffer-modified-p nil)
- (delete-auto-save-file-if-necessary t))
+ ;; Mark the buffer as unmodified and delete autosave.
+ (set-buffer-modified-p nil)
+ (delete-auto-save-file-if-necessary t)
+ (message-disassociate-draft)
;; Delete other mail buffers and stuff.
(message-do-send-housekeeping)
(message-do-actions message-send-actions)
(replace-match "\n")
(backward-char 1))
(run-hooks 'message-send-news-hook)
- (require (car method))
- (funcall (intern (format "%s-open-server" (car method)))
- (cadr method) (cddr method))
- (setq result
- (funcall (intern (format "%s-request-post" (car method)))
- (cadr method))))
+ ;;(require (car method))
+ ;;(funcall (intern (format "%s-open-server" (car method)))
+ ;;(cadr method) (cddr method))
+ ;;(setq result
+ ;; (funcall (intern (format "%s-request-post" (car method)))
+ ;; (cadr method)))
+ (gnus-open-server method)
+ (setq result (gnus-request-post method)))
(kill-buffer tembuf))
(set-buffer messbuf)
(if result
(copy-sequence message-required-mail-headers))))))
(run-hooks 'message-signature-setup-hook)
(message-insert-signature)
- (message-set-auto-save-file-name)
(save-restriction
(message-narrow-to-headers)
(run-hooks 'message-header-setup-hook))
(defun message-set-auto-save-file-name ()
"Associate the message buffer with a file in the drafts directory."
(when message-autosave-directory
- (unless (file-exists-p message-autosave-directory)
- (make-directory message-autosave-directory t))
- (let ((name (make-temp-name
- (expand-file-name
- (concat (file-name-as-directory message-autosave-directory)
- "msg."
- (nnheader-replace-chars-in-string
- (nnheader-replace-chars-in-string
- (buffer-name) ?* ?.)
- ?/ ?-))))))
- (setq buffer-auto-save-file-name
- (save-excursion
- (prog1
- (progn
- (set-buffer (get-buffer-create " *draft tmp*"))
- (setq buffer-file-name name)
- (make-auto-save-file-name))
- (kill-buffer (current-buffer)))))
- (clear-visited-file-modtime))))
+ (setq message-draft-article (nndraft-request-associate-buffer "drafts"))
+ (clear-visited-file-modtime)))
+
+(defun message-disassociate-draft ()
+ "Disassociate the message buffer from the drafts directory."
+ (nndraft-request-expire-articles
+ (list message-draft-article) "drafts" nil t))
\f
(regexp "^gnus\\|^nn\\|^message"))
(mapcar
(lambda (local)
- (when (and (car local)
+ (when (and (consp local)
+ (car local)
(string-match regexp (symbol-name (car local))))
(ignore-errors
(set (make-local-variable (car local))
(deffoo nnagent-request-newgroups (date server)
nil)
+(deffoo nnagent-request-post (&optional server)
+ (gnus-request-accept-article "nndraft:draft"))
+
;; Use nnml functions for just about everything.
(nnoo-import nnagent
(nnml))
;;; Code:
(require 'nnheader)
+(require 'nnmail)
+(require 'gnus-start)
(require 'nnmh)
(require 'nnoo)
-(eval-and-compile (require 'cl))
+(eval-when-compile (require 'cl))
-(nnoo-declare nndraft)
+(nnoo-declare nndraft
+ nnmh)
-(eval-and-compile
- (autoload 'mail-send-and-exit "sendmail"))
-
-(defvoo nndraft-directory nil
- "Where nndraft will store its directory.")
+(defvoo nndraft-directory (nnheader-concat message-directory "drafts/")
+ "Where nndraft will store its files."
+ nnmh-current-directory)
\f
+(defvoo nndraft-current-group "" nil nnmh-current-group)
+(defvoo nndraft-top-directory nil nil nnmh-directory)
+(defvoo nndraft-get-new-mail nil nil nnmh-get-new-mail)
+
(defconst nndraft-version "nndraft 1.0")
-(defvoo nndraft-status-string "")
+(defvoo nndraft-status-string "" nnmh-status-string)
\f
(nnoo-define-basics nndraft)
+(deffoo nndraft-open-server (server &optional defs)
+ (push `(nndraft-current-group
+ ,(file-name-nondirectory (directory-file-name nndraft-directory)))
+ defs)
+ (push `(nndraft-top-directory
+ ,(file-name-directory (directory-file-name nndraft-directory)))
+ defs)
+ (nnoo-change-server 'nndraft server defs)
+ (cond
+ ((not (file-exists-p nndraft-directory))
+ (nndraft-close-server)
+ (nnheader-report 'nndraft "No such file or directory: %s"
+ nndraft-directory))
+ ((not (file-directory-p (file-truename nndraft-directory)))
+ (nndraft-close-server)
+ (nnheader-report 'nndraft "Not a directory: %s" nndraft-directory))
+ (t
+ (nnheader-report 'nndraft "Opened server %s using directory %s"
+ server nndraft-directory)
+ t)))
+
(deffoo nndraft-retrieve-headers (articles &optional group server fetch-old)
(save-excursion
(set-buffer nntp-server-buffer)
(nnheader-fold-continuation-lines)
'headers))))
-(deffoo nndraft-open-server (server &optional defs)
- (nnoo-change-server 'nndraft server defs)
- (unless (assq 'nndraft-directory defs)
- (setq nndraft-directory server))
- (cond
- ((not (file-exists-p nndraft-directory))
- (nndraft-close-server)
- (nnheader-report 'nndraft "No such file or directory: %s"
- nndraft-directory))
- ((not (file-directory-p (file-truename nndraft-directory)))
- (nndraft-close-server)
- (nnheader-report 'nndraft "Not a directory: %s" nndraft-directory))
- (t
- (nnheader-report 'nndraft "Opened server %s using directory %s"
- server nndraft-directory)
- t)))
-
(deffoo nndraft-request-article (id &optional group server buffer)
(when (numberp id)
;; We get the newest file of the auto-saved file and the
(deffoo nndraft-request-restore-buffer (article &optional group server)
"Request a new buffer that is restored to the state of ARTICLE."
- (let ((file (nndraft-article-filename article ".state"))
- nndraft-point nndraft-mode nndraft-buffer-name)
- (when (file-exists-p file)
- (load file t t t)
- (when nndraft-buffer-name
- (set-buffer (get-buffer-create
- (generate-new-buffer-name nndraft-buffer-name)))
- (nndraft-request-article article group server (current-buffer))
- (funcall nndraft-mode)
- (let ((gnus-verbose-backends nil))
- (nndraft-request-expire-articles (list article) group server t))
- (goto-char nndraft-point))
- nndraft-buffer-name)))
+ (when (nndraft-request-article article group server (current-buffer))
+ (let ((gnus-verbose-backends nil))
+ (nndraft-request-expire-articles (list article) group server t))
+ t))
(deffoo nndraft-request-update-info (group info &optional server)
(setcar (cddr info) nil)
- (when (nth 3 info)
- (setcar (nthcdr 3 info) nil))
+ (let (marks)
+ (when (setq marks (nth 3 info))
+ (setcar (nthcdr 3 info)
+ (if (assq 'unsend marks)
+ (list (assq 'unsend marks))
+ nil))))
t)
(deffoo nndraft-request-associate-buffer (group)
"Associate the current buffer with some article in the draft group."
- (let* ((gnus-verbose-backends nil)
- (article (cdr (nndraft-request-accept-article
- group (nnoo-current-server 'nndraft) t 'noinsert)))
- (file (nndraft-article-filename article)))
+ (let ((gnus-verbose-backends nil)
+ (buf (current-buffer))
+ article file)
+ (nnheader-temp-write nil
+ (insert-buffer buf)
+ (setq article (cdr (nndraft-request-accept-article
+ group (nnoo-current-server 'nndraft) t 'noinsert)))
+ (setq file (nndraft-article-filename article)))
(setq buffer-file-name file)
(setq buffer-auto-save-file-name (make-auto-save-file-name))
(clear-visited-file-modtime)
article))
-(deffoo nndraft-request-group (group &optional server dont-check)
- (prog1
- (nndraft-execute-nnmh-command
- `(nnmh-request-group group "" ,dont-check))
- (nnheader-report 'nndraft nnmh-status-string)))
-
-(deffoo nndraft-request-list (&optional server dir)
- (nndraft-execute-nnmh-command
- `(nnmh-request-list nil ,dir)))
-
-(deffoo nndraft-request-newgroups (date &optional server)
- (nndraft-execute-nnmh-command
- `(nnmh-request-newgroups ,date ,server)))
-
-(deffoo nndraft-request-expire-articles
- (articles group &optional server force)
- (let ((res (nndraft-execute-nnmh-command
- `(nnmh-request-expire-articles
- ',articles group ,server ,force)))
- article)
+(deffoo nndraft-request-expire-articles (articles group &optional server force)
+ (let* ((nnmh-allow-delete-final t)
+ (res (nndraft-execute-nnmh-command
+ `(nnmh-request-expire-articles
+ ',articles group ,server ,force)))
+ article)
;; Delete all the "state" files of articles that have been expired.
(while articles
(unless (memq (setq article (pop articles)) res)
- (let ((file (nndraft-article-filename article ".state"))
- (auto (nndraft-auto-save-file-name
+ (let ((auto (nndraft-auto-save-file-name
(nndraft-article-filename article))))
- (when (file-exists-p file)
- (funcall nnmail-delete-file-function file))
(when (file-exists-p auto)
(funcall nnmail-delete-file-function auto)))))
res))
(deffoo nndraft-request-accept-article (group &optional server last noinsert)
- (let* ((point (point))
- (mode major-mode)
- (name (buffer-name))
- (gnus-verbose-backends nil)
- (gart (nndraft-execute-nnmh-command
- `(nnmh-request-accept-article group ,server ,last noinsert)))
- (state
- (nndraft-article-filename (cdr gart) ".state")))
- ;; Write the "state" file.
- (save-excursion
- (nnheader-set-temp-buffer " *draft state*")
- (insert (format "%S\n" `(setq nndraft-mode (quote ,mode)
- nndraft-point ,point
- nndraft-buffer-name ,name)))
- (write-region (point-min) (point-max) state nil 'silent)
- (kill-buffer (current-buffer)))
- gart))
-
-(deffoo nndraft-close-group (group &optional server)
- t)
+ (let ((gnus-verbose-backends nil))
+ (nndraft-execute-nnmh-command
+ `(nnmh-request-accept-article group ,server ,last noinsert))))
(deffoo nndraft-request-create-group (group &optional server args)
(if (file-exists-p nndraft-directory)
;;; Low-Level Interface
(defun nndraft-execute-nnmh-command (command)
- (let ((dir (expand-file-name nndraft-directory)))
- (when (string-match "/$" dir)
- (setq dir (substring dir 0 (match-beginning 0))))
- (string-match "/[^/]+$" dir)
- (let ((group (substring dir (1+ (match-beginning 0))))
- (nnmh-directory (substring dir 0 (1+ (match-beginning 0))))
- (nnmail-keep-last-article nil)
- (nnmh-get-new-mail nil))
- (eval command))))
+ (let* ((dir (directory-file-name (expand-file-name nndraft-directory)))
+ (group (file-name-nondirectory dir))
+ (nnmh-directory (file-name-directory dir))
+ (nnmail-keep-last-article nil)
+ (nnmh-get-new-mail nil))
+ (eval command)))
(defun nndraft-article-filename (article &rest args)
(apply 'concat
(make-auto-save-file-name))
(kill-buffer (current-buffer)))))
+(nnoo-map-functions nndraft
+ (nnmh-retrieve-headers 0 nndraft-current-group 0 0)
+ (nnmh-request-group nndraft-current-group 0 0)
+ (nnmh-close-group nndraft-current-group 0)
+ (nnmh-request-list (nnoo-current-server 'nndraft) nndraft-directory)
+ (nnmh-request-newsgroups (nnoo-current-server 'nndraft) nndraft-directory))
+
(provide 'nndraft)
;;; nndraft.el ends here
(defvoo nnmh-status-string "")
(defvoo nnmh-group-alist nil)
+(defvoo nnmh-allow-delete-final nil)
\f
(large (and (numberp nnmail-large-newsgroup)
(> number nnmail-large-newsgroup)))
(count 0)
- ;; 1997/8/12 by MORIOKA Tomohiko
- ;; for XEmacs/mule.
(pathname-coding-system 'binary)
beg article)
(nnmh-possibly-change-directory newsgroup server)
(let ((file (if (stringp id)
nil
(concat nnmh-current-directory (int-to-string id))))
- ;; 1997/8/12 by MORIOKA Tomohiko
- ;; for XEmacs/mule.
(pathname-coding-system 'binary)
(nntp-server-buffer (or buffer nntp-server-buffer)))
(and (stringp file)
(deffoo nnmh-request-group (group &optional server dont-check)
(let ((pathname (nnmail-group-pathname group nnmh-directory))
- ;; 1997/8/12 by MORIOKA Tomohiko
- ;; for XEmacs/mule.
(pathname-coding-system 'binary)
dir)
(cond
(nnmh-open-server server))
(when newsgroup
(let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))
- ;; 1997/8/12 by MORIOKA Tomohiko
- ;; for XEmacs/mule.
(pathname-coding-system 'binary))
(if (file-directory-p pathname)
(setq nnmh-current-directory pathname)
(let ((path (concat nnmh-current-directory (int-to-string article))))
;; Writable.
(and (file-writable-p path)
- ;; We can never delete the last article in the group.
- (not (eq (cdr (nth 1 (assoc group nnmh-group-alist)))
- article)))))
+ (or
+ ;; We can never delete the last article in the group.
+ (not (eq (cdr (nth 1 (assoc group nnmh-group-alist)))
+ article))
+ ;; Well, we can.
+ nnmh-allow-delete-final))))
(provide 'nnmh)
(string-to-int (file-name-nondirectory path)))))))
(deffoo nnml-request-group (group &optional server dont-check)
- ;; 1997/8/12 by MORIOKA Tomohiko
- ;; for XEmacs/mule.
(let ((pathname-coding-system 'binary))
(cond
((not (nnml-possibly-change-directory group server))
\input texinfo @c -*-texinfo-*-
@setfilename gnus
-@settitle Quassia Gnus 0.2 Manual
+@settitle Quassia Gnus 0.3 Manual
@synindex fn cp
@synindex vr cp
@synindex pg cp
@tex
@titlepage
-@title Quassia Gnus 0.2 Manual
+@title Quassia Gnus 0.3 Manual
@author by Lars Magne Ingebrigtsen
@page
spool or your mbox file. All at the same time, if you want to push your
luck.
-This manual corresponds to Quassia Gnus 0.2.
+This manual corresponds to Quassia Gnus 0.3.
@end ifinfo
* Posting Server:: What server should you post via?
* Mail and Post:: Mailing and posting at the same time.
* Archived Messages:: Where Gnus stores the messages you've sent.
-@c * Posting Styles:: An easier way to configure some key elements.
-@c * Drafts:: Postponing messages and rejected messages.
-@c * Rejected Articles:: What happens if the server doesn't like your article?
+* Drafts:: Postponing messages and rejected messages.
+* Rejected Articles:: What happens if the server doesn't like your article?
@end menu
Also see @pxref{Canceling and Superseding} for information on how to
@c (signature . "~/.mail-signature"))))
@c @end lisp
-@c @node Drafts
-@c @section Drafts
-@c @cindex drafts
-@c
-@c If you are writing a message (mail or news) and suddenly remember that
-@c you have a steak in the oven (or some pesto in the food processor, you
-@c craazy vegetarians), you'll probably wish there was a method to save the
-@c message you are writing so that you can continue editing it some other
-@c day, and send it when you feel its finished.
-@c
-@c Well, don't worry about it. Whenever you start composing a message of
-@c some sort using the Gnus mail and post commands, the buffer you get will
-@c automatically associate to an article in a special @dfn{draft} group.
-@c If you save the buffer the normal way (@kbd{C-x C-s}, for instance), the
-@c article will be saved there. (Auto-save files also go to the draft
-@c group.)
-@c
-@c @cindex nndraft
-@c @vindex gnus-draft-group-directory
-@c The draft group is a special group (which is implemented as an
-@c @code{nndraft} group, if you absolutely have to know) called
-@c @samp{nndraft:drafts}. The variable @code{gnus-draft-group-directory}
-@c controls both the name of the group and the location---the leaf element
-@c in the path will be used as the name of the group. What makes this
-@c group special is that you can't tick any articles in it or mark any
-@c articles as read---all articles in the group are permanently unread.
-@c
-@c If the group doesn't exist, it will be created and you'll be subscribed
-@c to it.
-@c
-@c @findex gnus-dissociate-buffer-from-draft
-@c @kindex C-c M-d (Mail)
-@c @kindex C-c M-d (Post)
-@c @findex gnus-associate-buffer-with-draft
-@c @kindex C-c C-d (Mail)
-@c @kindex C-c C-d (Post)
-@c If you're writing some super-secret message that you later want to
-@c encode with PGP before sending, you may wish to turn the auto-saving
-@c (and association with the draft group) off. You never know who might be
-@c interested in reading all your extremely valuable and terribly horrible
-@c and interesting secrets. The @kbd{C-c M-d}
-@c (@code{gnus-dissociate-buffer-from-draft}) command does that for you.
-@c If you change your mind and want to turn the auto-saving back on again,
-@c @kbd{C-c C-d} (@code{gnus-associate-buffer-with-draft} does that.
-@c
-@c @vindex gnus-use-draft
-@c To leave association with the draft group off by default, set
-@c @code{gnus-use-draft} to @code{nil}. It is @code{t} by default.
-@c
-@c @findex gnus-summary-send-draft
-@c @kindex S D c (Summary)
-@c When you want to continue editing the article, you simply enter the
-@c draft group and push @kbd{S D c} (@code{gnus-summary-send-draft}) to do
-@c that. You will be placed in a buffer where you left off.
-@c
-@c Rejected articles will also be put in this draft group (@pxref{Rejected
-@c Articles}).
-@c
-@c @findex gnus-summary-send-all-drafts
-@c If you have lots of rejected messages you want to post (or mail) without
-@c doing further editing, you can use the @kbd{S D a} command
-@c (@code{gnus-summary-send-all-drafts}). This command understands the
-@c process/prefix convention (@pxref{Process/Prefix}).
-@c
-@c
-@c @node Rejected Articles
-@c @section Rejected Articles
-@c @cindex rejected articles
-@c
-@c Sometimes a news server will reject an article. Perhaps the server
-@c doesn't like your face. Perhaps it just feels miserable. Perhaps
-@c @emph{there be demons}. Perhaps you have included too much cited text.
-@c Perhaps the disk is full. Perhaps the server is down.
-@c
-@c These situations are, of course, totally beyond the control of Gnus.
-@c (Gnus, of course, loves the way you look, always feels great, has angels
-@c fluttering around inside of it, doesn't care about how much cited text
-@c you include, never runs full and never goes down.) So Gnus saves these
-@c articles until some later time when the server feels better.
-@c
-@c The rejected articles will automatically be put in a special draft group
-@c (@pxref{Drafts}). When the server comes back up again, you'd then
-@c typically enter that group and send all the articles off.
-@c
+@node Drafts
+@section Drafts
+@cindex drafts
+
+If you are writing a message (mail or news) and suddenly remember that
+you have a steak in the oven (or some pesto in the food processor, you
+craazy vegetarians), you'll probably wish there was a method to save the
+message you are writing so that you can continue editing it some other
+day, and send it when you feel its finished.
+
+Well, don't worry about it. Whenever you start composing a message of
+some sort using the Gnus mail and post commands, the buffer you get will
+automatically associate to an article in a special @dfn{draft} group.
+If you save the buffer the normal way (@kbd{C-x C-s}, for instance), the
+article will be saved there. (Auto-save files also go to the draft
+group.)
+
+@cindex nndraft
+@vindex gnus-draft-group-directory
+The draft group is a special group (which is implemented as an
+@code{nndraft} group, if you absolutely have to know) called
+@samp{nndraft:drafts}. The variable @code{gnus-draft-group-directory}
+controls both the name of the group and the location---the leaf element
+in the path will be used as the name of the group. What makes this
+group special is that you can't tick any articles in it or mark any
+articles as read---all articles in the group are permanently unread.
+
+If the group doesn't exist, it will be created and you'll be subscribed
+to it.
+
+@findex gnus-dissociate-buffer-from-draft
+@kindex C-c M-d (Mail)
+@kindex C-c M-d (Post)
+@findex gnus-associate-buffer-with-draft
+@kindex C-c C-d (Mail)
+@kindex C-c C-d (Post)
+If you're writing some super-secret message that you later want to
+encode with PGP before sending, you may wish to turn the auto-saving
+(and association with the draft group) off. You never know who might be
+interested in reading all your extremely valuable and terribly horrible
+and interesting secrets. The @kbd{C-c M-d}
+(@code{gnus-dissociate-buffer-from-draft}) command does that for you.
+If you change your mind and want to turn the auto-saving back on again,
+@kbd{C-c C-d} (@code{gnus-associate-buffer-with-draft} does that.
+
+@vindex gnus-use-draft
+To leave association with the draft group off by default, set
+@code{gnus-use-draft} to @code{nil}. It is @code{t} by default.
+
+@findex gnus-summary-send-draft
+@kindex S D c (Summary)
+When you want to continue editing the article, you simply enter the
+draft group and push @kbd{S D c} (@code{gnus-summary-send-draft}) to do
+that. You will be placed in a buffer where you left off.
+
+Rejected articles will also be put in this draft group (@pxref{Rejected
+Articles}).
+
+@findex gnus-summary-send-all-drafts
+If you have lots of rejected messages you want to post (or mail) without
+doing further editing, you can use the @kbd{S D a} command
+(@code{gnus-summary-send-all-drafts}). This command understands the
+process/prefix convention (@pxref{Process/Prefix}).
+
+
+@node Rejected Articles
+@section Rejected Articles
+@cindex rejected articles
+
+Sometimes a news server will reject an article. Perhaps the server
+doesn't like your face. Perhaps it just feels miserable. Perhaps
+@emph{there be demons}. Perhaps you have included too much cited text.
+Perhaps the disk is full. Perhaps the server is down.
+
+These situations are, of course, totally beyond the control of Gnus.
+(Gnus, of course, loves the way you look, always feels great, has angels
+fluttering around inside of it, doesn't care about how much cited text
+you include, never runs full and never goes down.) So Gnus saves these
+articles until some later time when the server feels better.
+
+The rejected articles will automatically be put in a special draft group
+(@pxref{Drafts}). When the server comes back up again, you'd then
+typically enter that group and send all the articles off.
+
@node Select Methods
@chapter Select Methods
* Getting Mail:: Reading your personal mail with Gnus.
* Other Sources:: Reading directories, files, SOUP packets.
* Combined Groups:: Combining groups into one group.
+* Gnus Unplugged:: Reading news and mail offline.
@end menu
their @sc{nov} lines removed from the @sc{nov} file.
+@node Gnus Unplugged
+@section Gnus Unplugged
+@cindex offline
+@cindex unplugged
+@cindex Agent
+@cindex Gnus Agent
+@cindex Gnus Unplugged
+
+In olden times (ca. February '88), people used to run their newsreaders
+on big machines with permanent connections to the net. News transport
+was dealt with by news servers, and all the newsreaders had to do was to
+read news. Believe it or not.
+
+Nowadays most people read news and mail at home, and use some sort of
+modem to connect to the net. To avoid running up huge phone bills, it
+would be nice to have a way to slurp down all the news and mail, hang up
+the phone, read for several hours, and then upload any responses you
+have to make. And then you repeat the procedure.
+
+Of course, you can use news servers for doing this as well. I've used
+@code{inn} together with @code{slurp}, @code{pop} and @code{sendmail}
+for some years, but doing that's a bore. Moving the news server
+functionality up to the newsreader makes sense if you're the only person
+reading news on a machine.
+
+Using Gnus as an ``offline'' newsreader is quite simple.
+
+@itemize @bullet
+@item
+First, set ut Gnus as you would do if you were running it on a machine
+that has full connection to the net. Go ahead. I'll still be waiting
+here.
+
+@item
+Then, put the following magical incantation at the end of your
+@file{.gnus.el} file:
+
+@lisp
+(gnus-agentize)
+@end lisp
+@end itemize
+
+That's it. Gnus is now an ``offline'' newsreader.
+
+Of course, to use it as such, you have to learn a few new commands.
+
+@menu
+* Agent Basics:: How it all is supposed to work.
+* Agent Categories:: How to tell the Gnus Agent what to download.
+* Agent Commands:: New commands for all the buffers.
+* Agent Variables:: Customizing is fun.
+@end menu
+
+
+@node Agent Basics
+@subsection Agent Basics
+
+First, let's get some terminilogy out of the way.
+
+The Gnus Agent is said to be @dfn{unplugged} when you have severed the
+connection to the net (and notified the Agent that this is the case).
+When the connection to the net is up again (and Gnus knows this), the
+Agent is @dfn{plugged}.
+
+The @dfn{local} machine is the one you're running on, and which isn't
+connected to the net continously.
+
+@dfn{Downloading} means fetching things from the net to your local
+machine. @dfn{Uploading} is doing the opposite.
+
+Let's take a typical Gnus session using the Agent.
+
+@itemize @bullet
+
+@item
+You start Gnus with @code{gnus-unplugged}. This brings up the Gnus
+Agent in a disconnected state. You can read all the news that you have
+already fetched while in this mode.
+
+@item
+You then decide to see whether any new news has arrived. You connect
+your machine to the net (using PPP or whatever), and then hit @kbd{J j}
+to make Gnus become @dfn{plugged}.
+
+@item
+You can then read the new news immediately, or you can download the news
+onto your local machine. If you want to do the latter, you press @kbd{J
+s} to fetch all the eligible articles in all the groups. (To let Gnus
+know which articles you want to download, @pxref{Agent Categories}.)
+
+@item
+After fetching the articles, you press @kbd{J j} to make Gnus become
+unplugged again, and you shut down the PPP thing (or whatever). And
+then you read the news offline.
+
+@item
+And then you go to step 2.
+@end itemize
+
+
+@node Agent Categories
+@subsection Agent Categories
+
+On of the main reasons to integrate the news transport layer into the
+newsreader is to allow greater control over what articles to download.
+There's not much point in downloading huge amounts of articles, just to
+find out that you're not interested in reading any of them. It's better
+to be somewhat more conservative in choosing what to download, and then
+mark the articles for downloading manually if it should turn out that
+you're interested in the articles anyway.
+
+The main way to control what is to be downloaded is to create a
+@dfn{category} and then assign some (or all) groups to this category.
+Gnus has its own buffer for creating and managing categories.
+
+@menu
+* Category Syntax:: What a category looks like.
+* The Category Buffer:: A buffer for maintaining categories.
+* Category Variables:: Customize'r'Us.
+@end menu
+
+
+@node Category Syntax
+@subsubsection Category Syntax
+
+A category consists of two things.
+
+@enumerate
+@item
+A predicate which (generally) gives a rough outline of which articles
+are eligible for downloading; and
+
+@item
+a score rule which (generally) gives you a finer granularity when
+deciding what articles to download. (Note that this @dfn{download
+score} is wholly unrelated to normal scores.)
+@end enumerate
+
+A predicate consists of predicates with logical operators sprinkled in
+between.
+
+Perhaps some examples are in order.
+
+Here's a simple predicate. (It's the default predicate, in fact, used
+for all groups that don't belong to any other category.)
+
+@lisp
+short
+@end lisp
+
+Quite simple, eh? This predicate is true if and only if the article is
+short (for some value of ``short'').
+
+Here's a more complex predicate:
+
+@lisp
+(or high
+ (and
+ (not low)
+ (not long)))
+@end lisp
+
+This means that an article should be downloaded if it has a high score,
+or if the score is not low and the article is not long. You get the
+drift.
+
+The available logical operators are @code{or}, @code{and} and
+@code{not}. (If you prefer, you can use the more ``C''-ish operators
+@samp{|}, @code{&} and @code{!} instead.)
+
+The following predicates are pre-defined, but if none of these fit what
+you want to do, you can write your own.
+
+@table @code
+@item short
+True iff the article is shorter than @code{gnus-agent-short-article}
+lines; default 100.
+
+@item long
+True iff the article is longer than @code{gnus-agent-long-article}
+lines; default 200.
+
+@item low
+True iff the article has a download score less than
+@code{gnus-agent-low-score}; default 0.
+
+@item high
+True iff the article has a download score greater than
+@code{gnus-agent-high-score}; default 0.
+
+@item spam
+True iff the Gnus Agent guesses that the article is spam. The
+heuristics may change over time, but at present it just computes a
+checksum and see whether articles match.
+
+@item true
+Always true.
+
+@item false
+Always false.
+@end table
+
+If you want to create your own predicate function, here's what you have
+to know: The functions are called with no parameters, but the
+@code{gnus-headers} and @code{gnus-score} dynamic variables are bound to
+useful values.
+
+Now, the syntax of the download score is the same as the syntax of
+normal score files, except that all elements that require actually
+seeing the article itself is verboten. This means that only the
+following headers can be scored on: @code{From}, @code{Subject},
+@code{Date}, @code{Xref}, @code{Lines}, @code{Chars}, @code{Message-ID},
+and @code{References}.
+
+
+@node The Category Buffer
+@subsubsection The Category Buffer
+
+You'd normally do all category maintenance from the category buffer.
+When you enter it for the first time (with the @kbd{J c} command from
+the group buffer), you'll only see the @code{default} category.
+
+The following commands are available in this buffer:
+
+@table @kbd
+@item q
+@kindex q (Category)
+@findex gnus-category-exit
+Return to the group buffer (@code{gnus-category-exit}).
+
+@item k
+@kindex k (Category)
+@findex gnus-category-kill
+Kill the current category (@code{gnus-category-kill}).
+
+@item c
+@kindex c (Category)
+@findex gnus-category-copy
+Copy the current category (@code{gnus-category-copy}).
+
+@item a
+@kindex a (Category)
+@findex gnus-category-add
+Add a new category (@code{gnus-category-add}).
+
+@item p
+@kindex p (Category)
+@findex gnus-category-edit-predicate
+Edit the predicate of the current category
+(@code{gnus-category-edit-predicate}).
+
+@item g
+@kindex g (Category)
+@findex gnus-category-edit-groups
+Edit the list of groups belonging to the current category
+(@code{gnus-category-edit-groups}).
+
+@item s
+@kindex s (Category)
+@findex gnus-category-edit-score
+Edit the download score rule of the current category
+(@code{gnus-category-edit-score}).
+
+@item l
+@kindex l (Category)
+@findex gnus-category-list
+List all the categories (@code{gnus-category-list}).
+@end table
+
+
+@node Category Variables
+@subsubsection Category Variables
+
+@table @code
+@item gnus-category-mode-hook
+@vindex gnus-category-mode-hook
+Hook run in category buffers.
+
+@item gnus-category-line-format
+@vindex gnus-category-line-format
+Format of the lines in the category buffer (@pxref{Formatting
+Variables}). Legal elements are:
+
+@table @samp
+@item c
+The name of the category.
+
+@item g
+The number of groups in the category.
+@end table
+
+@item gnus-category-mode-line-format
+@vindex gnus-category-mode-line-format
+Format of the category mode line.
+
+@item gnus-agent-short-article
+@vindex gnus-agent-short-article
+Articles that have fewer lines than this are short. Default 100.
+
+@item gnus-agent-long-article
+@vindex gnus-agent-long-article
+Articles that have more lines than this are long. Default 200.
+
+@item gnus-agent-low-score
+@vindex gnus-agent-low-score
+Articles that have a score lower than this have a low score. Default
+0.
+
+@item gnus-agent-high-score
+@vindex gnus-agent-high-score
+Articles that have a score higher than this have a high score. Default
+0.
+
+@end table
+
+
+@node Agent Commands
+@subsection Agent Commands
+
+All the Gnus Agent commands is on the @kbd{J} submap. The @kbd{J j}
+(@code{gnus-agent-toggle-plugged} command works in all modes, and
+toggles the plugged/unplugged state of the Gnus Agent.
+
+
+@menu
+* Group Agent Commands::
+* Summary Agent Commands::
+* Server Agent Commands::
+@end menu
+
+
+@node Group Agent Commands
+@subsubsection Group Agent Commands
+
+@table @kbd
+@item J u
+@kindex J u (Agent Group)
+@findex gnus-agent-fetch-group
+Fetch all eligible articles in the current group
+(@code{gnus-agent-fetch-group}).
+
+@item J c
+@kindex J c (Agent Group)
+@findex gnus-enter-category-buffer
+Enter the Agent category buffer (@code{gnus-enter-category-buffer}).
+
+@item J s
+@kindex J s (Agent Group)
+@findex gnus-agent-fetch-session
+Fetch all eligible articles in all groups
+(@code{gnus-agent-fetch-session}).
+
+@item J a
+@kindex J a (Agent Group)
+@findex gnus-agent-add-group
+Add the current group to an Agent category
+(@code{gnus-agent-add-group}).
+
+@end table
+
+
+@node Summary Agent Commands
+@subsubsection Summary Agent Commands
+
+@table @kbd
+@item J #
+@kindex J # (Agent Summary)
+@findex gnus-agent-mark-article
+Mark the article for downloading (@code{gnus-agent-mark-article}).
+
+@item J M-#
+@kindex J M-# (Agent Summary)
+@findex gnus-agent-unmark-article
+Remove the downloading mark from the article
+(@code{gnus-agent-unmark-article}).
+
+@item @@
+@kindex @@ (Agent Summary)
+@findex gnus-agent-toggle-mark
+Toggle whether to download the article (@code{gnus-agent-toggle-mark}).
+
+@item J c
+@kindex J c (Agent Summary)
+@findex gnus-agent-catchup
+Mark all undownloaded articles as read (@code{gnus-agent-catchup}).
+
+@end table
+
+
+@node Server Agent Commands
+@subsubsection Server Agent Commands
+
+@table @kbd
+@item J a
+@kindex J a (Agent Server)
+@findex gnus-agent-add-server
+Add the current server to the list of servers covered by the Gnus Agent
+(@code{gnus-agent-add-server}).
+
+@item J r
+@kindex J r (Agent Server)
+@findex gnus-agent-remove-server
+Remove the current server from the list of servers covered by the Gnus
+Agent (@code{gnus-agent-remove-server}).
+
+@end table
+
+
+@node Agent Variables
+@subsection Agent Variables
+
+@table @code
+@item gnus-agent-directory
+@vindex gnus-agent-directory
+Where the Gnus Agent will store its files. The default is
+@file{~/News/agent/}.
+
+@item gnus-agent-plugged-hook
+@vindex gnus-agent-plugged-hook
+Hook run when connecting to the network.
+
+@item gnus-agent-unplugged-hook
+@vindex gnus-agent-unplugged-hook
+Hook run when disconnecting from the network.
+
+@end table
+
+
@node Scoring
@chapter Scoring
@cindex scoring
\input texinfo @c -*-texinfo-*-
@setfilename message
-@settitle Message 0.2 Manual
+@settitle Message 0.3 Manual
@synindex fn cp
@synindex vr cp
@synindex pg cp
@tex
@titlepage
-@title Message 0.2 Manual
+@title Message 0.3 Manual
@author by Lars Magne Ingebrigtsen
@page
* Key Index:: List of Message mode keys.
@end menu
-This manual corresponds to Message 0.2. Message is distributed with
+This manual corresponds to Message 0.3. Message is distributed with
the Gnus distribution bearing the same version number as this manual
has.