*** pub/qgnus/lisp/gnus-agent.el Sat Sep 13 21:56:41 1997 --- qgnus/lisp/gnus-agent.el Sun Sep 14 21:25:46 1997 *************** *** 23,36 **** ;;; Commentary: - ;; (add-hook 'gnus-before-startup-hook 'gnus-open-agent) - ;;; Code: (require 'gnus) (require 'gnus-cache) (require 'nnvirtual) (require 'gnus-sum) (defcustom gnus-agent-directory (nnheader-concat gnus-directory "agent/") "Where the Gnus agent will store its files." --- 23,35 ---- ;;; Commentary: ;;; 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." *************** *** 61,66 **** --- 60,66 ---- (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.") *************** *** 227,232 **** --- 227,257 ---- (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 ;;; *************** *** 793,798 **** --- 818,836 ---- (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*") *************** *** 1027,1046 **** (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)) (defun gnus-agent-long-p () ! "Say whether an article is long (more than 200 lines) or not." ! (> (mail-header-lines gnus-headers) 200)) (defun gnus-agent-low-scored-p () "Say whether an article has a low score or not." ! (< gnus-score gnus-summary-default-score)) (defun gnus-agent-high-scored-p () "Say whether an article has a high score or not." ! (> gnus-score gnus-summary-default-score)) (defun gnus-category-make-function (cat) "Make a function from category CAT." --- 1065,1084 ---- (gnus-sethash string t gnus-agent-spam-hashtb))))) (defun gnus-agent-short-p () ! "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 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-agent-low-score)) (defun gnus-agent-high-scored-p () "Say whether an article has a high score or not." ! (> gnus-score gnus-agent-low-score)) (defun gnus-category-make-function (cat) "Make a function from category CAT." *** pub/qgnus/lisp/gnus-bcklg.el Sat Sep 13 15:43:22 1997 --- qgnus/lisp/gnus-bcklg.el Sun Sep 14 21:25:46 1997 *************** *** 122,128 **** (1+ beg) 'gnus-backlog (current-buffer) (point-max))) (delete-region beg end) ;; Return success. ! t))))))) (defun gnus-backlog-request-article (group number buffer) (when (numberp number) --- 122,129 ---- (1+ beg) 'gnus-backlog (current-buffer) (point-max))) (delete-region beg end) ;; Return success. ! t)) ! (setq gnus-backlog-articles (delq ident gnus-backlog-articles))))))) (defun gnus-backlog-request-article (group number buffer) (when (numberp number) *** pub/qgnus/lisp/gnus-draft.el Sun Sep 14 21:26:01 1997 --- qgnus/lisp/gnus-draft.el Sun Sep 14 21:25:46 1997 *************** *** 0 **** --- 1,148 ---- + ;;; gnus-draft.el --- draft message support for Gnus + ;; Copyright (C) 1997 Free Software Foundation, Inc. + + ;; Author: Lars Magne Ingebrigtsen + ;; 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 + *** pub/qgnus/lisp/gnus-int.el Sat Sep 13 21:56:43 1997 --- qgnus/lisp/gnus-int.el Sun Sep 14 21:25:47 1997 *************** *** 391,397 **** 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) ;; 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))) --- 391,397 ---- article (gnus-group-real-name group) (nth 1 gnus-command-method) accept-function 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))) *** pub/qgnus/lisp/gnus-msg.el Sat Sep 13 15:43:22 1997 --- qgnus/lisp/gnus-msg.el Sun Sep 14 21:25:47 1997 *************** *** 1046,1072 **** (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 () --- 1046,1051 ---- *** pub/qgnus/lisp/gnus-start.el Sun Sep 14 00:30:32 1997 --- qgnus/lisp/gnus-start.el Sun Sep 14 21:25:48 1997 *************** *** 690,701 **** --- 690,711 ---- ;; 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-configure-windows '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 () *** pub/qgnus/lisp/gnus-sum.el Sun Sep 14 00:30:34 1997 --- qgnus/lisp/gnus-sum.el Sun Sep 14 21:25:50 1997 *************** *** 423,428 **** --- 423,433 ---- :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 *************** *** 886,891 **** --- 891,899 ---- (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.") *************** *** 926,931 **** --- 934,940 ---- 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 *************** *** 2170,2175 **** --- 2179,2185 ---- (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) *** pub/qgnus/lisp/gnus-win.el Sat Sep 13 21:56:48 1997 --- qgnus/lisp/gnus-win.el Sun Sep 14 21:25:50 1997 *************** *** 137,145 **** (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) --- 137,142 ---- *** pub/qgnus/lisp/gnus.el Sun Sep 14 00:32:24 1997 --- qgnus/lisp/gnus.el Sun Sep 14 21:25:51 1997 *************** *** 244,250 **** :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) ! (defconst gnus-version-number "0.2" "Version number for this version of Gnus.") (defconst gnus-version (format "Quassia Gnus v%s" gnus-version-number) --- 244,250 ---- :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) ! (defconst gnus-version-number "0.3" "Version number for this version of Gnus.") (defconst gnus-version (format "Quassia Gnus v%s" gnus-version-number) *************** *** 1445,1451 **** (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) (scored . score) (saved . save) ! (cached . cache) (downloadable . download))) (defvar gnus-headers-retrieved-by nil) (defvar gnus-article-reply nil) --- 1445,1452 ---- (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) (scored . score) (saved . save) ! (cached . cache) (downloadable . download) ! (unsendable . unsend))) (defvar gnus-headers-retrieved-by nil) (defvar gnus-article-reply nil) *************** *** 1696,1706 **** 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" :interactive t gnus-unplugged) ("gnus-vm" :interactive t gnus-summary-save-in-vm ! gnus-summary-save-article-vm)))) ;;; gnus-sum.el thingies --- 1697,1708 ---- 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-method-p) ("gnus-agent" :interactive t gnus-unplugged) ("gnus-vm" :interactive t gnus-summary-save-in-vm ! gnus-summary-save-article-vm) ! ("gnus-draft" :interactive t gnus-draft-mode)))) ;;; gnus-sum.el thingies *** pub/qgnus/lisp/message.el Sun Sep 14 00:30:38 1997 --- qgnus/lisp/message.el Sun Sep 14 21:25:52 1997 *************** *** 268,277 **** :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." :group 'message-buffers :type 'directory) --- 268,277 ---- :type 'file :group 'message-headers) ! (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) *************** *** 805,810 **** --- 805,811 ---- (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) *************** *** 1238,1243 **** --- 1239,1245 ---- (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) *************** *** 1286,1291 **** --- 1288,1294 ---- (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)) *************** *** 1777,1786 **** ;; (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)) ;; Delete other mail buffers and stuff. (message-do-send-housekeeping) (message-do-actions message-send-actions) --- 1780,1789 ---- ;; (mail-hist-put-headers-into-history)) (run-hooks 'message-sent-hook) (message "Sending...done") ! ;; 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) *************** *** 2040,2051 **** (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)))) (kill-buffer tembuf)) (set-buffer messbuf) (if result --- 2043,2056 ---- (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))) ! (gnus-open-server method) ! (setq result (gnus-request-post method))) (kill-buffer tembuf)) (set-buffer messbuf) (if result *************** *** 2997,3003 **** (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)) --- 3002,3007 ---- *************** *** 3010,3034 **** (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)))) --- 3014,3026 ---- (defun message-set-auto-save-file-name () "Associate the message buffer with a file in the drafts directory." (when message-autosave-directory ! (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)) *************** *** 3701,3707 **** (regexp "^gnus\\|^nn\\|^message")) (mapcar (lambda (local) ! (when (and (car local) (string-match regexp (symbol-name (car local)))) (ignore-errors (set (make-local-variable (car local)) --- 3693,3700 ---- (regexp "^gnus\\|^nn\\|^message")) (mapcar (lambda (local) ! (when (and (consp local) ! (car local) (string-match regexp (symbol-name (car local)))) (ignore-errors (set (make-local-variable (car local)) *** pub/qgnus/lisp/nnagent.el Sat Sep 13 21:56:51 1997 --- qgnus/lisp/nnagent.el Sun Sep 14 21:25:52 1997 *************** *** 104,109 **** --- 104,112 ---- (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)) *** pub/qgnus/lisp/nndraft.el Sat Sep 13 15:43:23 1997 --- qgnus/lisp/nndraft.el Sun Sep 14 21:25:52 1997 *************** *** 26,47 **** ;;; Code: (require 'nnheader) (require 'nnmh) (require 'nnoo) ! (eval-and-compile (require 'cl)) ! (nnoo-declare nndraft) ! (eval-and-compile ! (autoload 'mail-send-and-exit "sendmail")) ! ! (defvoo nndraft-directory nil ! "Where nndraft will store its directory.") (defconst nndraft-version "nndraft 1.0") ! (defvoo nndraft-status-string "") --- 26,52 ---- ;;; Code: (require 'nnheader) + (require 'nnmail) + (require 'gnus-start) (require 'nnmh) (require 'nnoo) ! (eval-when-compile (require 'cl)) ! (nnoo-declare nndraft ! nnmh) ! (defvoo nndraft-directory (nnheader-concat message-directory "drafts/") ! "Where nndraft will store its files." ! nnmh-current-directory) + (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 "" nnmh-status-string) *************** *** 49,54 **** --- 54,80 ---- (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) *************** *** 79,101 **** (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 --- 105,110 ---- *************** *** 118,207 **** (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))) (deffoo nndraft-request-update-info (group info &optional server) (setcar (cddr info) nil) ! (when (nth 3 info) ! (setcar (nthcdr 3 info) 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))) (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) ;; 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 (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) (deffoo nndraft-request-create-group (group &optional server args) (if (file-exists-p nndraft-directory) --- 127,181 ---- (deffoo nndraft-request-restore-buffer (article &optional group server) "Request a new buffer that is restored to the state of ARTICLE." ! (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) ! (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) ! (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-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 ((auto (nndraft-auto-save-file-name (nndraft-article-filename article)))) (when (file-exists-p auto) (funcall nnmail-delete-file-function auto))))) res)) (deffoo nndraft-request-accept-article (group &optional server last noinsert) ! (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) *************** *** 218,232 **** ;;; 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)))) (defun nndraft-article-filename (article &rest args) (apply 'concat --- 192,203 ---- ;;; Low-Level Interface (defun nndraft-execute-nnmh-command (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 *************** *** 242,247 **** --- 213,225 ---- (setq buffer-file-name file) (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) *** pub/qgnus/lisp/nnmh.el Sun Sep 14 00:30:38 1997 --- qgnus/lisp/nnmh.el Sun Sep 14 21:25:53 1997 *************** *** 60,65 **** --- 60,66 ---- (defvoo nnmh-status-string "") (defvoo nnmh-group-alist nil) + (defvoo nnmh-allow-delete-final nil) *************** *** 76,83 **** (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) --- 77,82 ---- *************** *** 137,144 **** (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) --- 136,141 ---- *************** *** 149,156 **** (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 --- 146,151 ---- *************** *** 409,416 **** (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) --- 404,409 ---- *************** *** 556,564 **** (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))))) (provide 'nnmh) --- 549,560 ---- (let ((path (concat nnmh-current-directory (int-to-string article)))) ;; Writable. (and (file-writable-p path) ! (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) *** pub/qgnus/lisp/nnml.el Sat Sep 13 21:56:52 1997 --- qgnus/lisp/nnml.el Sun Sep 14 21:25:53 1997 *************** *** 194,201 **** (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)) --- 194,199 ---- *** pub/qgnus/lisp/ChangeLog Sun Sep 14 00:30:30 1997 --- qgnus/lisp/ChangeLog Sun Sep 14 21:25:45 1997 *************** *** 2,7 **** --- 2,41 ---- * gnus.el: Quassia Gnus v0.1 is released. + Sun Sep 14 21:17:34 1997 Lars Magne Ingebrigtsen + + * gnus.el: Quassia Gnus v0.3 is released. + + Sun Sep 14 01:51:45 1997 Lars Magne Ingebrigtsen + + * 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 * gnus.el: Quassia Gnus v0.2 is released. *** pub/qgnus/lisp/Makefile Fri Mar 7 07:37:05 1997 --- qgnus/lisp/Makefile Sun Sep 14 21:25:53 1997 *************** *** 12,18 **** $(EMACS) $(FLAGS) -f dgnushack-compile some: ! $(EMACS) $(FLAGS) -f dgnushack-recompile tags: etags *.el --- 12,18 ---- $(EMACS) $(FLAGS) -f dgnushack-compile some: ! $(EMACS) $(FLAGS) -f dgnushack-compile tags: etags *.el *** pub/qgnus/texi/gnus.texi Sun Sep 14 00:30:45 1997 --- qgnus/texi/gnus.texi Sun Sep 14 21:25:56 1997 *************** *** 1,7 **** \input texinfo @c -*-texinfo-*- @setfilename gnus ! @settitle Quassia Gnus 0.2 Manual @synindex fn cp @synindex vr cp @synindex pg cp --- 1,7 ---- \input texinfo @c -*-texinfo-*- @setfilename gnus ! @settitle Quassia Gnus 0.3 Manual @synindex fn cp @synindex vr cp @synindex pg cp *************** *** 309,315 **** @tex @titlepage ! @title Quassia Gnus 0.2 Manual @author by Lars Magne Ingebrigtsen @page --- 309,315 ---- @tex @titlepage ! @title Quassia Gnus 0.3 Manual @author by Lars Magne Ingebrigtsen @page *************** *** 345,351 **** 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. @end ifinfo --- 345,351 ---- spool or your mbox file. All at the same time, if you want to push your luck. ! This manual corresponds to Quassia Gnus 0.3. @end ifinfo *************** *** 7689,7697 **** * 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? @end menu Also see @pxref{Canceling and Superseding} for information on how to --- 7689,7696 ---- * 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. ! * 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 *************** *** 8015,8104 **** @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 Select Methods @chapter Select Methods --- 8014,8103 ---- @c (signature . "~/.mail-signature")))) @c @end lisp ! @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 *************** *** 8137,8142 **** --- 8136,8142 ---- * 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 *************** *** 10714,10719 **** --- 10714,11147 ---- Articles marked as read in the @code{nnkiboze} group will have 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 *** pub/qgnus/texi/message.texi Sun Sep 14 00:30:46 1997 --- qgnus/texi/message.texi Sun Sep 14 21:25:57 1997 *************** *** 1,7 **** \input texinfo @c -*-texinfo-*- @setfilename message ! @settitle Message 0.2 Manual @synindex fn cp @synindex vr cp @synindex pg cp --- 1,7 ---- \input texinfo @c -*-texinfo-*- @setfilename message ! @settitle Message 0.3 Manual @synindex fn cp @synindex vr cp @synindex pg cp *************** *** 39,45 **** @tex @titlepage ! @title Message 0.2 Manual @author by Lars Magne Ingebrigtsen @page --- 39,45 ---- @tex @titlepage ! @title Message 0.3 Manual @author by Lars Magne Ingebrigtsen @page *************** *** 79,85 **** * Key Index:: List of Message mode keys. @end menu ! This manual corresponds to Message 0.2. Message is distributed with the Gnus distribution bearing the same version number as this manual has. --- 79,85 ---- * Key Index:: List of Message mode keys. @end menu ! This manual corresponds to Message 0.3. Message is distributed with the Gnus distribution bearing the same version number as this manual has. *** pub/qgnus/texi/dir Wed Jun 18 00:54:19 1997 --- qgnus/texi/dir Sat Jul 12 19:54:27 1997 *************** *** 0 **** --- 1,11 ---- + -*- Text -*- + The Gnus-related top node. +  + File: dir Node: Top This is the Gnus Info tree + + * Menu: + + * Gnus: (gnus). The news reader Gnus. + * Message: (message). The Message sending thingamabob. + * Widget: (widget). The Widget library. + * Custom: (custom). The Custom library.