*** pub/sgnus/lisp/gnus-cus.el Thu Sep 21 01:16:40 1995 --- sgnus/lisp/gnus-cus.el Fri Sep 22 14:45:49 1995 *************** *** 60,66 **** If `visual' is disabled, there will be no menus and few faces. Most of the visual customization options below will be ignored. GNUS will use less space and be faster as a result.") ! (default . t) (name . gnus-visual) (type . toggle)) ((tag . "WWW Browser") --- 60,70 ---- If `visual' is disabled, there will be no menus and few faces. Most of the visual customization options below will be ignored. GNUS will use less space and be faster as a result.") ! (default . ! (summary-highlight ! article-highlight ! summary-menu group-menu article-menu ! browse-menu server-menu)) (name . gnus-visual) (type . toggle)) ((tag . "WWW Browser") *** pub/sgnus/lisp/gnus-mh.el Thu Sep 21 01:16:41 1995 --- sgnus/lisp/gnus-mh.el Fri Sep 22 01:08:32 1995 *************** *** 75,207 **** (kill-buffer errbuf)))) (setq gnus-newsgroup-last-folder folder))) ! (defun gnus-mail-reply-using-mhe (&optional yank) ! "Compose reply mail using mh-e. ! Optional argument YANK means yank original article. ! The command \\[mh-yank-cur-msg] yank the original message into current buffer." ! (let (from cc subject date to reply-to to-userid orig-to ! references message-id ! (config (current-window-configuration)) ! buffer) ! (pop-to-buffer gnus-article-buffer) ! (setq buffer (current-buffer)) ! (save-excursion ! (save-restriction ! (or gnus-user-login-name ; we need this ! (setq gnus-user-login-name (or (getenv "USER") ! (getenv "LOGNAME")))) ! ! (gnus-article-show-all-headers);; so colors are happy ! ;; lots of junk to avoid mh-send deleting other windows ! (setq from (or (gnus-fetch-field "from") "") ! subject (let ((subject (or (gnus-fetch-field "subject") ! "(None)"))) ! (if (and subject ! (not (string-match "^[Rr][Ee]:.+$" subject))) ! (concat "Re: " subject) subject)) ! reply-to (gnus-fetch-field "reply-to") ! cc (gnus-fetch-field "cc") ! orig-to (or (gnus-fetch-field "to") "") ! date (gnus-fetch-field "date") ! references (gnus-fetch-field "references") ! message-id (gnus-fetch-field "message-id")) ! (setq to (or reply-to from)) ! (setq to-userid (mail-strip-quoted-names orig-to)) ! (if (or (string-match "," orig-to) ! (not (string-match (substring to-userid 0 ! (string-match "@" to-userid)) ! gnus-user-login-name))) ! (setq cc (concat (if cc (concat cc ", ") "") orig-to))) ! ;; mh-yank-cur-msg needs to have mh-show-buffer set in the ! ;; *Article* buffer ! (setq mh-show-buffer buffer))) ! (mh-find-path) ! (mh-send-sub (or to "") (or cc "") ! (or subject "(None)") config);; Erik Selberg 1/23/94 ! ! (let ((draft (current-buffer)) ! (gnus-mail-buffer (current-buffer)) ! mail-buf) ! (if (not yank) ! (gnus-configure-windows 'reply) ! (gnus-configure-windows 'reply-yank)) ! (setq mail-buf gnus-mail-buffer) ! (pop-to-buffer mail-buf);; always in the display, so won't have window probs ! (switch-to-buffer draft)) ! ! ;; (mh-send to (or cc "") subject);; shouldn't use according to mhe ! ! ;; note - current buffer is now draft! ! (save-excursion ! (mh-insert-fields ! "In-reply-to:" ! (concat ! (substring from 0 (string-match " *at \\| *@ \\| *(\\| *<" from)) ! "'s message of " date)) ! (nnheader-insert-references references message-id)) ! ! ;; need this for mh-yank-cur-msg ! (setq mh-sent-from-folder buffer) (setq mh-sent-from-msg 1) ! (setq mh-show-buffer buffer) ! (setq mh-previous-window-config config)) ! ! ;; Then, yank original article if requested. ! (if yank ! (let ((last (point))) ! (mh-yank-cur-msg) ! (goto-char last))) ! ! (run-hooks 'gnus-mail-hook)) ! ! ! ;; gnus-mail-forward-using-mhe is contributed by Jun-ichiro Itoh ! ;; ! ! (defun gnus-mail-forward-using-mhe (&optional buffer) ! "Forward the current message to another user using mh-e." ! ;; First of all, prepare mhe mail buffer. ! (let* ((to (read-string "To: ")) ! (cc (read-string "Cc: ")) ! (buffer (or buffer gnus-article-buffer)) ! (config (current-window-configuration));; need to add this - erik ! (subject (gnus-forward-make-subject buffer))) ! (setq mh-show-buffer buffer) ! (mh-find-path) ! (mh-send-sub to (or cc "") (or subject "(None)") config);; Erik Selberg 1/23/94 ! (let ((draft (current-buffer)) ! (gnus-mail-buffer (current-buffer)) ! mail-buf) ! (gnus-configure-windows 'reply-yank) ! (setq mail-buf (eval (cdr (assq 'mail gnus-window-to-buffer)))) ! (pop-to-buffer mail-buf);; always in the display, so won't have window probs ! (switch-to-buffer draft) ! ) ! (save-excursion ! (goto-char (point-max)) ! (insert "\n------- Forwarded Message\n\n") ! (insert-buffer buffer) ! (goto-char (point-max)) ! (insert "\n------- End of Forwarded Message\n") ! (setq mh-sent-from-folder buffer) ! (setq mh-sent-from-msg 1) ! (setq mh-previous-window-config config) ! (run-hooks 'gnus-mail-hook) ! ))) ! ! (defun gnus-mail-other-window-using-mhe () ! "Compose mail other window using mh-e." ! (let ((to (read-string "To: ")) ! (cc (read-string "Cc: ")) ! (subject (read-string "Subject: "))) ! (gnus-article-show-all-headers) ;I don't think this is really needed. ! (setq mh-show-buffer (current-buffer)) ! (mh-find-path) ! (mh-send-other-window to cc subject) ! (setq mh-sent-from-folder (current-buffer)) ! (setq mh-sent-from-msg 1) ! (run-hooks 'gnus-mail-hook))) (defun gnus-Folder-save-name (newsgroup headers &optional last-folder) "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER. --- 75,90 ---- (kill-buffer errbuf)))) (setq gnus-newsgroup-last-folder folder))) ! (defun gnus-mh-mail-setup (to subject in-reply-to cc replybuffer actions) ! (let ((config (current-window-configuration))) ! (setq mh-show-buffer gnus-article-copy) (mh-find-path) ! (mh-send-sub (or to "") (or cc "") (or subject "(None)") config) ! (goto-char (point-min)) ! (insert "In-Reply-To: " in-reply-to "\n") ! (setq mh-sent-from-folder gnus-article-copy) (setq mh-sent-from-msg 1) ! (setq mh-previous-window-config config))) (defun gnus-Folder-save-name (newsgroup headers &optional last-folder) "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER. *** pub/sgnus/lisp/gnus-msg.el Thu Sep 21 01:16:42 1995 --- sgnus/lisp/gnus-msg.el Fri Sep 22 22:22:34 1995 *************** *** 265,271 **** (defvar gnus-reply-subject nil) (eval-and-compile ! (autoload 'gnus-uu-post-news "gnus-uu" nil t)) ;;; --- 265,273 ---- (defvar gnus-reply-subject nil) (eval-and-compile ! (autoload 'gnus-uu-post-news "gnus-uu" nil t) ! (autoload 'news-setup "rnewspost") ! (autoload 'news-mode "rnewspost")) ;;; *************** *** 306,312 **** (defun gnus-group-mail () "Start composing a mail." (interactive) ! (funcall gnus-mail-other-window-method)) (defun gnus-group-post-news () "Post an article." --- 308,314 ---- (defun gnus-group-mail () "Start composing a mail." (interactive) ! (gnus-new-mail)) (defun gnus-group-post-news () "Post an article." *************** *** 444,585 **** "Begin editing a new USENET news article to be posted. Type \\[describe-mode] in the buffer to get a list of commands." (interactive (list t)) ! (gnus-copy-article-buffer article-buffer) ! (if (or (not gnus-novice-user) ! gnus-expert-user ! (not (eq 'post ! (nth 1 (assoc ! (format "%s" (car (gnus-find-method-for-group ! gnus-newsgroup-name))) ! gnus-valid-select-methods)))) ! (and group ! (assq 'to-address ! (nth 5 (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))) ! (gnus-y-or-n-p "Are you sure you want to post to all of USENET? ")) ! (let ((sumart (if (not post) ! (save-excursion ! (set-buffer gnus-summary-buffer) ! (cons (current-buffer) gnus-current-article)))) ! (from (and header (mail-header-from header))) ! (winconf (current-window-configuration)) ! real-group) ! (and gnus-interactive-post ! (not gnus-expert-user) ! post (not group) ! (progn ! (setq gnus-newsgroup-name ! (setq group ! (completing-read "Group: " gnus-active-hashtb))) ! (or subject ! (setq subject (read-string "Subject: "))))) ! (setq mail-reply-buffer gnus-article-copy) ! ! (let ((newsgroup-name (or group gnus-newsgroup-name ""))) ! (setq real-group (and group (gnus-group-real-name group))) ! (setq gnus-post-news-buffer ! (gnus-request-post-buffer ! post real-group subject header gnus-article-copy ! (nth 2 (and group (gnus-gethash group gnus-newsrc-hashtb))) ! (or (cdr (assq 'to-group ! (nth 5 (nth 2 (gnus-gethash ! newsgroup-name ! gnus-newsrc-hashtb))))) ! (if (and (boundp 'gnus-followup-to-function) ! gnus-followup-to-function ! gnus-article-copy) ! (save-excursion ! (set-buffer gnus-article-copy) ! (funcall gnus-followup-to-function group)))) ! gnus-use-followup-to)) ! (if post ! (gnus-configure-windows 'post 'force) ! (if yank ! (gnus-configure-windows 'followup-yank 'force) ! (gnus-configure-windows 'followup 'force))) ! (gnus-overload-functions) ! (make-local-variable 'gnus-article-reply) ! (make-local-variable 'gnus-article-check-size) ! (make-local-variable 'gnus-reply-subject) ! (setq gnus-reply-subject (and header (mail-header-subject header))) ! (setq gnus-article-reply sumart) ! ;; Handle `gnus-auto-mail-to-author'. ! ;; Suggested by Daniel Quinlan . ! ;; Revised to respect Reply-To by Ulrik Dickow . ! (let ((to (and (not post) ! (if (if (eq gnus-auto-mail-to-author 'ask) ! (y-or-n-p "Also send mail to author? ") ! gnus-auto-mail-to-author) ! (or (save-excursion ! (set-buffer gnus-article-copy) ! (gnus-fetch-field "reply-to")) ! from))))) ! (if to ! (if (mail-fetch-field "To") ! (progn ! (beginning-of-line) ! (insert "Cc: " to "\n")) ! (mail-position-on-field "To") ! (insert to)))) ! ;; Handle author copy using BCC field. ! (if (and gnus-mail-self-blind ! (not (mail-fetch-field "bcc"))) ! (progn ! (mail-position-on-field "Bcc") ! (insert (if (stringp gnus-mail-self-blind) ! gnus-mail-self-blind ! (user-login-name))))) ! ;; Handle author copy using FCC field. ! (if gnus-author-copy ! (progn ! (mail-position-on-field "Fcc") ! (insert gnus-author-copy))) ! (goto-char (point-min)) ! (if post ! (cond ((not group) ! (re-search-forward "^Newsgroup:" nil t) ! (end-of-line)) ! ((not subject) ! (re-search-forward "^Subject:" nil t) ! (end-of-line)) ! (t ! (re-search-forward ! (concat "^" (regexp-quote mail-header-separator) "$")) ! (forward-line 1))) ! (re-search-forward ! (concat "^" (regexp-quote mail-header-separator) "$")) ! (forward-line 1) ! (if (not yank) ! () ! (save-excursion ! (if (not (listp yank)) ! (news-reply-yank-original nil) ! (setq yank (reverse yank)) ! (while yank ! (save-excursion ! (save-window-excursion ! (set-buffer gnus-summary-buffer) ! (gnus-summary-select-article nil nil nil (car yank)) ! (gnus-summary-remove-process-mark (car yank))) ! (let ((mail-reply-buffer gnus-article-copy)) ! (gnus-copy-article-buffer) ! (let ((news-reply-yank-message-id ! (save-excursion ! (set-buffer gnus-article-copy) ! (mail-fetch-field "message-id"))) ! (news-reply-yank-from ! (save-excursion ! (set-buffer gnus-article-copy) ! (mail-fetch-field "from")))) ! (news-reply-yank-original nil)) ! (setq yank (cdr yank))))))))) ! (if gnus-post-prepare-function ! (funcall gnus-post-prepare-function group)) ! (run-hooks 'gnus-post-prepare-hook) ! (make-local-variable 'gnus-prev-winconf) ! (setq gnus-prev-winconf winconf)))) ! (setq gnus-article-check-size (cons (buffer-size) (gnus-article-checksum))) ! (message "") ! t) (defun gnus-inews-news (&optional use-group-method) "Send a news message. --- 446,463 ---- "Begin editing a new USENET news article to be posted. Type \\[describe-mode] in the buffer to get a list of commands." (interactive (list t)) ! (let* ((group (or group gnus-newsgroup-name)) ! (to-address ! (assq 'to-address ! (nth 5 (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))))) ! (if (and (gnus-member-of-valid 'post (or group gnus-newsgroup-name)) ! (not to-address)) ! (if post ! (gnus-new-news group) ! (gnus-news-followup yank group)) ! (if post ! (gnus-new-mail) ! (gnus-mail-reply yank (and to-address (cdr to-address)) 'followup))))) (defun gnus-inews-news (&optional use-group-method) "Send a news message. *************** *** 1480,1488 **** (gnus-set-global-variables) (if yank-articles (gnus-summary-goto-subject (car yank-articles))) (gnus-summary-select-article) ! (let ((gnus-newsgroup-name gnus-newsgroup-name)) ! (bury-buffer gnus-article-buffer) ! (funcall gnus-mail-reply-method (or yank-articles (not (not yank)))))) (defun gnus-summary-reply-with-original (n) "Reply mail to news author with original article. --- 1358,1365 ---- (gnus-set-global-variables) (if yank-articles (gnus-summary-goto-subject (car yank-articles))) (gnus-summary-select-article) ! (bury-buffer gnus-article-buffer) ! (gnus-mail-reply (or yank-articles (not (not yank))))) (defun gnus-summary-reply-with-original (n) "Reply mail to news author with original article. *************** *** 1497,1506 **** (gnus-set-global-variables) (gnus-summary-select-article) (gnus-copy-article-buffer) ! (let ((gnus-newsgroup-name gnus-newsgroup-name)) ! (if post ! (gnus-forward-using-post gnus-article-copy) ! (funcall gnus-mail-forward-method gnus-article-copy)))) (defun gnus-summary-post-forward () "Forward the current article to a newsgroup." --- 1374,1382 ---- (gnus-set-global-variables) (gnus-summary-select-article) (gnus-copy-article-buffer) ! (if post ! (gnus-forward-using-post gnus-article-copy) ! (gnus-mail-forward gnus-article-copy))) (defun gnus-summary-post-forward () "Forward the current article to a newsgroup." *************** *** 1530,1556 **** mailer." (interactive) (gnus-set-global-variables) ! (let ((gnus-newsgroup-name gnus-newsgroup-name)) ! (funcall gnus-mail-other-window-method))) ! (defun gnus-mail-reply-using-mail (&optional yank to-address) (save-excursion (set-buffer gnus-summary-buffer) (let ((group (gnus-group-real-name gnus-newsgroup-name)) (cur (cons (current-buffer) (cdr gnus-article-current))) (winconf (current-window-configuration)) ! from subject date reply-to message-of ! references message-id sender follow-to sendto elt) (set-buffer (get-buffer-create gnus-mail-buffer)) (mail-mode) - (make-local-variable 'gnus-article-reply) - (setq gnus-article-reply cur) - (make-local-variable 'gnus-prev-winconf) - (setq gnus-prev-winconf winconf) (if (and (buffer-modified-p) (> (buffer-size) 0) (not (gnus-y-or-n-p ! "Unsent article being composed; erase it? "))) () (erase-buffer) (save-excursion --- 1406,1432 ---- mailer." (interactive) (gnus-set-global-variables) ! (gnus-new-mail)) ! (defun gnus-new-mail () ! (pop-to-buffer gnus-mail-buffer) ! (erase-buffer) ! (gnus-mail-setup nil nil nil nil nil nil)) ! ! (defun gnus-mail-reply (&optional yank to-address followup) (save-excursion (set-buffer gnus-summary-buffer) (let ((group (gnus-group-real-name gnus-newsgroup-name)) (cur (cons (current-buffer) (cdr gnus-article-current))) (winconf (current-window-configuration)) ! from subject date reply-to message-of to cc ! references message-id sender follow-to sendto elt new-cc) (set-buffer (get-buffer-create gnus-mail-buffer)) (mail-mode) (if (and (buffer-modified-p) (> (buffer-size) 0) (not (gnus-y-or-n-p ! "Unsent message being composed; erase it? "))) () (erase-buffer) (save-excursion *************** *** 1558,1566 **** (save-restriction (set-buffer gnus-article-copy) (gnus-narrow-to-headers) ! (if (and (boundp 'gnus-reply-to-function) ! gnus-reply-to-function) ! (setq follow-to (funcall gnus-reply-to-function group))) (setq from (mail-fetch-field "from")) (setq date (or (mail-fetch-field "date") (mail-header-date gnus-current-headers))) --- 1434,1450 ---- (save-restriction (set-buffer gnus-article-copy) (gnus-narrow-to-headers) ! (if (not followup) ! ;; This is a regular reply. ! (if (and (symbolp gnus-reply-to-function) ! (fboundp gnus-reply-to-function)) ! (setq follow-to (funcall gnus-reply-to-function group))) ! ;; This is a followup. ! (if (and (symbolp gnus-followup-to-function) ! (fboundp gnus-followup-to-function)) ! (save-excursion ! (setq follow-to ! (funcall gnus-followup-to-function group))))) (setq from (mail-fetch-field "from")) (setq date (or (mail-fetch-field "date") (mail-header-date gnus-current-headers))) *************** *** 1571,1585 **** (concat (if stop-pos (substring from 0 stop-pos) from) "'s message of " date)))) (setq sender (mail-fetch-field "sender")) ! (setq subject (or (mail-fetch-field "subject") ! "Re: none")) ! (or (string-match "^[Rr][Ee]:" subject) ! (setq subject (concat "Re: " subject))) (setq reply-to (mail-fetch-field "reply-to")) (setq references (mail-fetch-field "references")) (setq message-id (mail-fetch-field "message-id")) ! (widen)) ! (setq news-reply-yank-from (or from "(nobody)"))) (setq news-reply-yank-message-id (or message-id "(unknown Message-ID)")) --- 1455,1486 ---- (concat (if stop-pos (substring from 0 stop-pos) from) "'s message of " date)))) (setq sender (mail-fetch-field "sender")) ! (setq subject (or (mail-fetch-field "subject") "none")) ! ;; Remove any (buggy) Re:'s that are present and make a ! ;; proper one. ! (and (string-match "^[ \t]*[Re][Ee]:[ \t]*" subject) ! (setq subject (substring subject (match-end 0)))) ! (setq subject (concat "Re: " subject)) ! (setq to (mail-fetch-field "to")) ! (setq to (mail-fetch-field "cc")) (setq reply-to (mail-fetch-field "reply-to")) (setq references (mail-fetch-field "references")) (setq message-id (mail-fetch-field "message-id")) ! ! (if (not followup) ! () ! ;; When we followup, we want all the headers, I would think. ! (setq new-cc (rmail-dont-reply-to ! (concat (or to "") ! (if cc (concat (if to ", " "") cc) "")))) ! (let ((rmail-dont-reply-to-names ! (regexp-quote (mail-strip-quoted-names ! (or to-address reply-to from ""))))) ! (setq new-cc (rmail-dont-reply-to new-cc)))) ! ! (widen))) ! ! (setq news-reply-yank-from (or from "(nobody)")) (setq news-reply-yank-message-id (or message-id "(unknown Message-ID)")) *************** *** 1590,1599 **** (setq sendto (concat sendto (and sendto ", ") (cdr elt))) (setq follow-to (delq elt follow-to)))) ! (mail-setup (or to-address ! (if (and follow-to (not (stringp follow-to))) sendto ! (or follow-to reply-to from sender ""))) ! subject message-of nil gnus-article-copy nil) (auto-save-mode auto-save-default) (gnus-inews-modify-mail-mode-map) --- 1491,1508 ---- (setq sendto (concat sendto (and sendto ", ") (cdr elt))) (setq follow-to (delq elt follow-to)))) ! (gnus-mail-setup ! (or to-address ! (if (and follow-to (not (stringp follow-to))) sendto ! (or follow-to reply-to from sender ""))) ! subject message-of ! (if (zerop (length new-cc)) nil new-cc) ! gnus-article-copy nil) ! ! (make-local-variable 'gnus-article-reply) ! (setq gnus-article-reply cur) ! (make-local-variable 'gnus-prev-winconf) ! (setq gnus-prev-winconf winconf) (auto-save-mode auto-save-default) (gnus-inews-modify-mail-mode-map) *************** *** 1608,1613 **** --- 1517,1524 ---- (insert (car (car follow-to)) ": " (cdr (car follow-to)) "\n") (setq follow-to (cdr follow-to))))) (nnheader-insert-references references message-id) + + ;; Now the headers should be ok, so we do the yanking. (goto-char (point-min)) (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) *************** *** 1639,1644 **** --- 1550,1747 ---- (gnus-configure-windows 'reply-yank 'force)) (run-hooks 'gnus-mail-hook))))) + (defun gnus-new-news (&optional group) + (let (subject) + (and gnus-interactive-post + (not gnus-expert-user) + (not group) + (progn + (setq gnus-newsgroup-name + (setq group + (completing-read "Group: " gnus-active-hashtb))) + (setq subject (read-string "Subject: ")))) + (pop-to-buffer "*post-news*") + (erase-buffer) + (news-reply-mode) + (news-setup nil subject nil group nil) + (local-set-key "\C-c\C-c" 'gnus-inews-news))) + + (defun gnus-news-followup (&optional yank group) + (save-excursion + (set-buffer gnus-summary-buffer) + (if (not (or (not gnus-novice-user) + gnus-expert-user + (gnus-y-or-n-p + "Are you sure you want to post to all of USENET? "))) + () + (let ((group (or group (gnus-group-real-name gnus-newsgroup-name))) + (cur (cons (current-buffer) (cdr gnus-article-current))) + (winconf (current-window-configuration)) + from subject date reply-to message-of + references message-id sender follow-to sendto elt + followup-to distribution) + (set-buffer (get-buffer-create gnus-mail-buffer)) + (news-mode) + (if (and (buffer-modified-p) + (> (buffer-size) 0) + (not (gnus-y-or-n-p + "Unsent message being composed; erase it? "))) + () + (erase-buffer) + (save-excursion + (gnus-copy-article-buffer) + (save-restriction + (set-buffer gnus-article-copy) + (gnus-narrow-to-headers) + (if (and (symbolp gnus-followup-to-function) + (fboundp gnus-followup-to-function)) + (save-excursion + (setq follow-to + (funcall gnus-followup-to-function group)))) + (setq from (mail-fetch-field "from")) + (setq date (or (mail-fetch-field "date") + (mail-header-date gnus-current-headers))) + (and from + (let ((stop-pos + (string-match " *at \\| *@ \\| *(\\| *<" from))) + (setq message-of + (concat + (if stop-pos (substring from 0 stop-pos) from) + "'s message of " date)))) + (setq subject (or (mail-fetch-field "subject") "none")) + ;; Remove any (buggy) Re:'s that are present and make a + ;; proper one. + (and (string-match "^[ \t]*[Re][Ee]:[ \t]*" subject) + (setq subject (substring subject (match-end 0)))) + (setq subject (concat "Re: " subject)) + (setq references (mail-fetch-field "references")) + (setq message-id (mail-fetch-field "message-id")) + (setq followup-to (mail-fetch-field "followup-to")) + (setq distribution (mail-fetch-field "distribution")) + ;; Remove bogus distribution. + (and (stringp distribution) + (string-match "world" distribution) + (setq distribution nil)) + (widen))) + + (setq news-reply-yank-from (or from "(nobody)")) + (setq news-reply-yank-message-id + (or message-id "(unknown Message-ID)")) + + ;; Gather the "to" addresses out of the follow-to list and remove + ;; them as we go. + (if (and follow-to (listp follow-to)) + (while (setq elt (assoc "Newsgroups" follow-to)) + (setq sendto (concat sendto (and sendto ", ") (cdr elt))) + (setq follow-to (delq elt follow-to)))) + + (news-setup nil subject message-of + (or group sendto + (and follow-to + gnus-use-followup-to + (or (not (eq gnus-use-followup-to 'ask)) + (gnus-y-or-n-p + (format + "Use Followup-To %s? " follow-to)))) + group "") + gnus-article-copy) + + (make-local-variable 'gnus-article-reply) + (setq gnus-article-reply cur) + (make-local-variable 'gnus-prev-winconf) + (setq gnus-prev-winconf winconf) + (make-local-variable 'gnus-reply-subject) + (setq gnus-reply-subject (mail-header-subject gnus-current-headers)) + + (auto-save-mode auto-save-default) + (gnus-inews-modify-mail-mode-map) + (local-set-key "\C-c\C-c" 'gnus-inews-news) + + (if (and follow-to (listp follow-to)) + (progn + (goto-char (point-min)) + (and (re-search-forward "^Newsgroups:" nil t) + (forward-line 1)) + (while follow-to + (insert (car (car follow-to)) ": " + (cdr (car follow-to)) "\n") + (setq follow-to (cdr follow-to))))) + + ;; If a distribution existed, we use it. + (if distribution + (progn + (mail-position-on-field "Distribution") + (insert distribution))) + + (nnheader-insert-references references message-id) + + ;; Handle `gnus-auto-mail-to-author'. + ;; Suggested by Daniel Quinlan . + ;; Revised to respect Reply-To by Ulrik Dickow . + (let ((to (if (if (eq gnus-auto-mail-to-author 'ask) + (y-or-n-p "Also send mail to author? ") + gnus-auto-mail-to-author) + (or (save-excursion + (set-buffer gnus-article-copy) + (gnus-fetch-field "reply-to")) + from)))) + (if to + (if (mail-fetch-field "To") + (progn + (beginning-of-line) + (insert "Cc: " to "\n")) + (mail-position-on-field "To") + (insert to)))) + + ;; Handle author copy using BCC field. + (if (and gnus-mail-self-blind + (not (mail-fetch-field "bcc"))) + (progn + (mail-position-on-field "Bcc") + (insert (if (stringp gnus-mail-self-blind) + gnus-mail-self-blind + (user-login-name))))) + ;; Handle author copy using FCC field. + (if gnus-author-copy + (progn + (mail-position-on-field "Fcc") + (insert gnus-author-copy))) + + ;; Now the headers should be ok, so we do the yanking. + (goto-char (point-min)) + (re-search-forward + (concat "^" (regexp-quote mail-header-separator) "$")) + (forward-line 1) + (if (not yank) + (gnus-configure-windows 'reply 'force) + (let ((last (point)) + end) + (if (not (listp yank)) + (progn + (save-excursion + (mail-yank-original nil)) + (or mail-yank-hooks mail-citation-hook + (run-hooks 'news-reply-header-hook))) + (while yank + (save-window-excursion + (set-buffer gnus-summary-buffer) + (gnus-summary-select-article nil nil nil (car yank)) + (gnus-summary-remove-process-mark (car yank))) + (save-excursion + (gnus-copy-article-buffer) + (mail-yank-original nil) + (setq end (point))) + (or mail-yank-hooks mail-citation-hook + (run-hooks 'news-reply-header-hook)) + (goto-char end) + (setq yank (cdr yank)))) + (goto-char last)) + (gnus-configure-windows 'reply-yank 'force)) + + (make-local-variable 'gnus-article-check-size) + (setq gnus-article-check-size + (cons (buffer-size) (gnus-article-checksum)))))))) + (defun gnus-mail-yank-original () (interactive) (save-excursion *************** *** 1727,1739 **** (point) 'invisible) (point-max)))))) ! (defun gnus-mail-forward-using-mail (&optional buffer) "Forward the current message to another user using mail." ;; This is almost a carbon copy of rmail-forward in rmail.el. (let* ((forward-buffer (or buffer (current-buffer))) (winconf (current-window-configuration)) (subject (gnus-forward-make-subject forward-buffer))) (set-buffer forward-buffer) (mail nil nil subject) (gnus-inews-modify-mail-mode-map) (make-local-variable 'gnus-prev-winconf) --- 1830,1843 ---- (point) 'invisible) (point-max)))))) ! (defun gnus-mail-forward (&optional buffer) "Forward the current message to another user using mail." ;; This is almost a carbon copy of rmail-forward in rmail.el. (let* ((forward-buffer (or buffer (current-buffer))) (winconf (current-window-configuration)) (subject (gnus-forward-make-subject forward-buffer))) (set-buffer forward-buffer) + (gnus-mail-setup nil subject nil nil nil nil 'forward) (mail nil nil subject) (gnus-inews-modify-mail-mode-map) (make-local-variable 'gnus-prev-winconf) *************** *** 1778,1784 **** (and address (progn (switch-to-buffer gnus-summary-buffer) ! (funcall gnus-mail-reply-method yank address))))) (defun gnus-bug () "Send a bug report to the Gnus maintainers." --- 1882,1888 ---- (and address (progn (switch-to-buffer gnus-summary-buffer) ! (gnus-mail-reply yank address))))) (defun gnus-bug () "Send a bug report to the Gnus maintainers." *************** *** 1889,1895 **** (interactive) (gnus-summary-select-article t) ;; Create a mail buffer. ! (funcall gnus-mail-other-window-method) (erase-buffer) (insert-buffer gnus-article-buffer) (goto-char (point-min)) --- 1993,1999 ---- (interactive) (gnus-summary-select-article t) ;; Create a mail buffer. ! (gnus-new-mail) (erase-buffer) (insert-buffer gnus-article-buffer) (goto-char (point-min)) *************** *** 1929,1943 **** (save-restriction (widen) (gnus-inews-narrow-to-headers) ! (let (gnus-deletable-headers) ! (gnus-inews-insert-headers gnus-required-mail-headers)) ! (widen))) ;; Run final inews hooks. This hook may do FCC. (run-hooks 'gnus-inews-article-hook) (gnus-inews-do-gcc) ! (gnus-inews-narrow-to-headers) (nnheader-remove-header "^[gf]cc:" t) (widen) (mail-send) (run-hooks 'gnus-message-sent-hook)) --- 2033,2056 ---- (save-restriction (widen) (gnus-inews-narrow-to-headers) ! (gnus-inews-remove-headers) ! (gnus-inews-insert-headers gnus-required-mail-headers))) ! (widen) ! ;; Remove the header separator. ! (goto-char (point-min)) ! (and (re-search-forward ! (concat "^" (regexp-quote mail-header-separator) "$") nil t) ! (replace-match "" t t)) ;; Run final inews hooks. This hook may do FCC. (run-hooks 'gnus-inews-article-hook) (gnus-inews-do-gcc) ! (gnus-narrow-to-headers) (nnheader-remove-header "^[gf]cc:" t) (widen) + (goto-char (point-min)) + (search-forward "\n\n") + (forward-char -1) + (insert mail-header-separator) (mail-send) (run-hooks 'gnus-message-sent-hook)) *************** *** 1946,1951 **** --- 2059,2092 ---- (local-set-key "\C-c\C-c" 'gnus-mail-send-and-exit) (local-set-key "\C-c\C-p" 'gnus-put-message) (local-set-key "\C-c\C-d" 'gnus-enter-into-draft-group)) + + (defun gnus-mail-setup (to subject in-reply-to cc replybuffer actions + &optional type) + (funcall + (cond + ((or + (and (eq type 'reply) + (eq gnus-mail-reply-method 'gnus-mail-reply-using-mhe)) + (and (eq type 'forward) + (eq gnus-mail-forward-method 'gnus-mail-forward-using-mhe)) + (and (eq type 'new) + (eq gnus-mail-other-window-method + 'gnus-mail-other-window-using-mhe))) + 'gnus-mh-mail-setup) + ((or + (and (eq type 'reply) + (eq gnus-mail-reply-method 'gnus-mail-reply-using-vm)) + (and (eq type 'forward) + (eq gnus-mail-forward-method 'gnus-mail-forward-using-vm)) + (and (eq type 'new) + (eq gnus-mail-other-window-method + 'gnus-mail-other-window-using-vm))) + 'gnus-vm-mail-setup) + (t 'gnus-sendmail-mail-setup)) + to subject in-reply-to cc replybuffer actions)) + + (defun gnus-sendmail-mail-setup (to subject in-reply-to cc replybuffer actions) + (mail-setup to subject in-reply-to cc replybuffer actions)) ;;; Gcc handling. *** pub/sgnus/lisp/gnus-score.el Thu Sep 21 01:16:42 1995 --- sgnus/lisp/gnus-score.el Thu Sep 21 16:15:32 1995 *************** *** 1648,1653 **** --- 1648,1657 ---- (goto-char (point-min)) (pop-to-buffer buf))) + (defun gnus-score-flush-cache () + "Flush the cache of score files." + (interactive) + (setq gnus-score-cache nil)) (provide 'gnus-score) *** pub/sgnus/lisp/gnus-uu.el Thu Sep 21 01:16:43 1995 --- sgnus/lisp/gnus-uu.el Thu Sep 21 14:42:30 1995 *************** *** 263,268 **** --- 263,269 ---- (defconst gnus-uu-output-buffer-name " *Gnus UU Output*") (defvar gnus-uu-default-dir default-directory) + (defvar gnus-uu-digest-from-subject nil) ;; Keymaps *************** *** 435,441 **** (interactive "P") (let ((gnus-uu-save-in-digest t) (file (make-temp-name (concat gnus-uu-tmp-dir "forward"))) ! buf) (gnus-uu-decode-save n file) (gnus-uu-add-file file) (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*"))) --- 436,443 ---- (interactive "P") (let ((gnus-uu-save-in-digest t) (file (make-temp-name (concat gnus-uu-tmp-dir "forward"))) ! buf subject from) ! (setq gnus-uu-digest-from-subject nil) (gnus-uu-decode-save n file) (gnus-uu-add-file file) (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*"))) *************** *** 443,463 **** (erase-buffer) (delete-other-windows) (insert-file file) (goto-char (point-min)) (and (re-search-forward "^Subject: ") (progn (delete-region (point) (gnus-point-at-eol)) ! (insert "Digested Articles"))) (goto-char (point-min)) (and (re-search-forward "^From: ") (progn (delete-region (point) (gnus-point-at-eol)) ! (insert "Various"))) (if post (gnus-forward-using-post) (funcall gnus-mail-forward-method)) (delete-file file) ! (kill-buffer buf))) (defun gnus-uu-digest-post-forward (n) "Digest and forward to a newsgroup." --- 445,483 ---- (erase-buffer) (delete-other-windows) (insert-file file) + (let ((fs gnus-uu-digest-from-subject)) + (if (not fs) + () + (setq from (car (car fs)) + subject (gnus-simplify-subject-fuzzy (cdr (car fs))) + fs (cdr fs)) + (while (and fs (or from subject)) + (and from + (or (string= from (car (car fs))) + (setq from nil))) + (and subject + (or (string= (gnus-simplify-subject-fuzzy (cdr (car fs))) + subject) + (setq subject nil))) + (setq fs (cdr fs)))) + (or subject (setq subject "Digested Articles")) + (or from (setq from "Various"))) (goto-char (point-min)) (and (re-search-forward "^Subject: ") (progn (delete-region (point) (gnus-point-at-eol)) ! (insert subject))) (goto-char (point-min)) (and (re-search-forward "^From: ") (progn (delete-region (point) (gnus-point-at-eol)) ! (insert from))) (if post (gnus-forward-using-post) (funcall gnus-mail-forward-method)) (delete-file file) ! (kill-buffer buf) ! (setq gnus-uu-digest-from-subject nil))) (defun gnus-uu-digest-post-forward (n) "Digest and forward to a newsgroup." *************** *** 673,678 **** --- 693,703 ---- ((eq in-state 'last) (list 'end)) (t (list 'middle))))) (t + (let ((header (gnus-summary-article-header))) + (setq gnus-uu-digest-from-subject + (cons (cons (mail-header-from header) + (mail-header-subject header)) + gnus-uu-digest-from-subject))) (let ((name (file-name-nondirectory gnus-uu-saved-article-name)) beg subj headers headline sorthead body end-string state) (if (or (eq in-state 'first) *************** *** 719,726 **** (1- (point))) (progn (forward-line 1) (point))))))))) (widen))) ! (insert sorthead)(goto-char (point-max)) ! (insert body)(goto-char (point-max)) (insert (concat "\n" (make-string 30 ?-) "\n\n")) (goto-char beg) (if (re-search-forward "^Subject: \\(.*\\)$" nil t) --- 744,751 ---- (1- (point))) (progn (forward-line 1) (point))))))))) (widen))) ! (insert sorthead) (goto-char (point-max)) ! (insert body) (goto-char (point-max)) (insert (concat "\n" (make-string 30 ?-) "\n\n")) (goto-char beg) (if (re-search-forward "^Subject: \\(.*\\)$" nil t) *** pub/sgnus/lisp/gnus-vis.el Thu Sep 21 01:16:43 1995 --- sgnus/lisp/gnus-vis.el Thu Sep 21 16:20:05 1995 *************** *** 293,298 **** --- 293,299 ---- ["Edit kill file" gnus-group-edit-local-kill t] ["Expire articles" gnus-group-expire-articles t] ["Set group level" gnus-group-set-current-level t] + ["Select quick" gnus-group-quick-select-group t] )) (easy-menu-define *************** *** 309,315 **** ["Describe all groups" gnus-group-describe-all-groups t] ["Group apropos" gnus-group-apropos t] ["Group and description apropos" gnus-group-description-apropos t] ! ["List groups matching..." gnus-group-list-matching t]) ("Mark" ["Mark group" gnus-group-mark-group t] ["Unmark group" gnus-group-unmark-group t] --- 310,317 ---- ["Describe all groups" gnus-group-describe-all-groups t] ["Group apropos" gnus-group-apropos t] ["Group and description apropos" gnus-group-description-apropos t] ! ["List groups matching..." gnus-group-list-matching t] ! ["List active file" gnus-group-list-active t]) ("Mark" ["Mark group" gnus-group-mark-group t] ["Unmark group" gnus-group-unmark-group t] *************** *** 331,336 **** --- 333,340 ---- ["Parameters" gnus-group-edit-group-parameters t] ["Select method" gnus-group-edit-group-method t] ["Info" gnus-group-edit-group t]) + ("Score file" + ["Flush cache" gnus-score-flush-cache t]) ["Read a directory as a group" gnus-group-enter-directory t] ["Jump to group" gnus-group-jump-to-group t] ["Best unread group" gnus-group-best-unread-group t] *************** *** 458,464 **** ["Mark all" gnus-uu-mark-all t] ["Mark buffer" gnus-uu-mark-buffer t] ["Mark sparse" gnus-uu-mark-sparse t] ! ["Mark thread" gnus-uu-mark-thread t])) ("Move" ["Scroll article forwards" gnus-summary-next-page t] ["Next unread article" gnus-summary-next-unread-article t] --- 462,469 ---- ["Mark all" gnus-uu-mark-all t] ["Mark buffer" gnus-uu-mark-buffer t] ["Mark sparse" gnus-uu-mark-sparse t] ! ["Mark thread" gnus-uu-mark-thread t] ! ["Unmark thread" gnus-uu-unmark-thread t])) ("Move" ["Scroll article forwards" gnus-summary-next-page t] ["Next unread article" gnus-summary-next-unread-article t] *************** *** 726,731 **** --- 731,739 ---- ["Reply & followup" gnus-summary-followup-and-reply t] ["Reply & followup and yank" gnus-summary-followup-and-reply-with-original t] ["Uuencode and post" gnus-uu-post-news t] + ("Draft" + ["Send" gnus-summary-send-draft t] + ["Send bounced" gnus-resend-bounced-mail t]) )) (run-hooks 'gnus-summary-menu-hook) ))) *** pub/sgnus/lisp/gnus-vm.el Thu Sep 21 01:16:43 1995 --- sgnus/lisp/gnus-vm.el Fri Sep 22 01:08:32 1995 *************** *** 110,115 **** --- 110,119 ---- ;; Remember the directory name to save articles. (setq gnus-newsgroup-last-mail folder))) + (defun gnus-vm-mail-setup (to subject in-reply-to cc replybuffer actions) + (gnus-sendmail-mail-setup to subject in-reply-to cc replybuffer actions) + ) + (defun gnus-mail-forward-using-vm (&optional buffer) "Forward the current message to another user using vm." (let* ((gnus-buffer (or buffer (current-buffer))) *** pub/sgnus/lisp/gnus.el Thu Sep 21 01:16:45 1995 --- sgnus/lisp/gnus.el Fri Sep 22 22:58:53 1995 *************** *** 194,204 **** instead.") (defvar gnus-group-faq-directory ! "/ftp@mirrors.aol.com:/pub/rtfm/usenet/" "*Directory where the group FAQs are stored. This will most commonly be on a remote machine, and the file will be fetched by ange-ftp. Note that Gnus uses an aol machine as the default directory. If this feels fundamentally unclean, just think of it as a way to finally get something of value back from them. --- 194,217 ---- instead.") (defvar gnus-group-faq-directory ! '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/" ! "/ftp@ftp.uu.net:/usenet/news.answers/" ! "/ftp@ftp.seas.gwu.edu:/pub/rtfm/" ! "/ftp@rtfm.mit.edu:/pub/usenet/news.answers/" ! "/ftp@ftp.uni-paderborn.de:/pub/FAQ/" ! "/ftp@ftp.Germany.EU.net:/pub/newsarchive/news.answers/" ! "/ftp@ftp.sunet.se:/pub/usenet/" ! "/ftp@nctuccca.edu.tw:/USENET/FAQ/" ! "/ftp@hwarang.postech.ac.kr:/pub/usenet/news.answers/" ! "/ftp@ftp.hk.super.net:/mirror/faqs/") "*Directory where the group FAQs are stored. This will most commonly be on a remote machine, and the file will be fetched by ange-ftp. + This variable can also be a list of directories. In that case, the + first element in the list will be used by default, and the others will + be used as backup sites. + Note that Gnus uses an aol machine as the default directory. If this feels fundamentally unclean, just think of it as a way to finally get something of value back from them. *************** *** 271,277 **** These score files are loaded in addition to any files returned by gnus-score-find-score-files-function (which see).") - (defvar gnus-score-file-suffix "SCORE" "*Suffix of the score files.") --- 284,289 ---- *************** *** 1387,1393 **** "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "September Gnus v0.01" "Version number for this version of Gnus.") (defvar gnus-info-nodes --- 1399,1405 ---- "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "September Gnus v0.02" "Version number for this version of Gnus.") (defvar gnus-info-nodes *************** *** 1406,1411 **** --- 1418,1425 ---- (defvar gnus-work-buffer " *gnus work*") + (defvar gnus-original-article-buffer " *Original Article*") + (defvar gnus-buffer-list nil "Gnus buffers that should be killed on exit.") *************** *** 1422,1432 **** gnus-killed-list gnus-zombie-list) "Gnus variables saved in the quick startup file.") - (defvar gnus-overload-functions - '((news-inews gnus-inews-news "rnewspost")) - "Functions overloaded by gnus. - It is a list of `(original overload &optional file)'.") - (defvar gnus-newsrc-options nil "Options line in the .newsrc file.") --- 1436,1441 ---- *************** *** 1722,1727 **** --- 1731,1737 ---- (autoload 'gnus-score-adaptive "gnus-score") (autoload 'gnus-score-remove-lines-adaptive "gnus-score") (autoload 'gnus-score-find-trace "gnus-score") + (autoload 'gnus-score-flush-cache "gnus-score" nil t) ;; gnus-edit (autoload 'gnus-score-customize "gnus-edit" nil t) *************** *** 2755,2775 **** (gnus-configure-windows 'info) (Info-goto-node (car (cdr (assq mode gnus-info-nodes)))))) - (defun gnus-overload-functions (&optional overloads) - "Overload functions specified by optional argument OVERLOADS. - If nothing is specified, use the variable gnus-overload-functions." - (let ((defs nil) - (overloads (or overloads gnus-overload-functions))) - (while overloads - (setq defs (car overloads)) - (setq overloads (cdr overloads)) - ;; Load file before overloading function if necessary. Make - ;; sure we cannot use `require' always. - (and (not (fboundp (car defs))) - (car (cdr (cdr defs))) - (load (car (cdr (cdr defs))) nil 'nomessage)) - (fset (car defs) (car (cdr defs)))))) - (defun gnus-replace-chars-in-string (string &rest pairs) "Replace characters in STRING from FROM to TO." (let ((string (substring string 0)) ;Copy string. --- 2765,2770 ---- *************** *** 2938,2943 **** --- 2933,2948 ---- (setq name (concat leaf "<" (int-to-string (setq num (1+ num))) ">"))) name)) + ;; Find out whether the gnus-visual TYPE is wanted. + (defun gnus-visual-p (&optional type class) + (and gnus-visual ; Has to be non-nil, at least. + (if (not type) ; We don't care about type. + gnus-visual + (if (listp gnus-visual) ; It's a list, so we check it. + (or (memq type gnus-visual) + (memq class gnus-visual)) + t)))) + ;;; List and range functions (defun gnus-last-element (list) *************** *** 3175,3180 **** --- 3180,3186 ---- (defvar gnus-group-mark-map nil) (defvar gnus-group-list-map nil) (defvar gnus-group-sub-map nil) + (defvar gnus-group-score-map nil) (put 'gnus-group-mode 'mode-class 'special) (if gnus-group-mode-map *************** *** 3184,3189 **** --- 3190,3196 ---- (define-key gnus-group-mode-map " " 'gnus-group-read-group) (define-key gnus-group-mode-map "=" 'gnus-group-select-group) (define-key gnus-group-mode-map "\r" 'gnus-group-select-group) + (define-key gnus-group-mode-map "\M-\r" 'gnus-group-quick-select-group) (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group) (define-key gnus-group-mode-map "n" 'gnus-group-next-unread-group) (define-key gnus-group-mode-map "p" 'gnus-group-prev-unread-group) *************** *** 3275,3285 **** --- 3282,3297 ---- (define-key gnus-group-list-map "z" 'gnus-group-list-zombies) (define-key gnus-group-list-map "s" 'gnus-group-list-groups) (define-key gnus-group-list-map "u" 'gnus-group-list-all-groups) + (define-key gnus-group-list-map "A" 'gnus-group-list-active) (define-key gnus-group-list-map "a" 'gnus-group-apropos) (define-key gnus-group-list-map "d" 'gnus-group-description-apropos) (define-key gnus-group-list-map "m" 'gnus-group-list-matching) (define-key gnus-group-list-map "M" 'gnus-group-list-all-matching) + (define-prefix-command 'gnus-group-score-map) + (define-key gnus-group-mode-map "W" 'gnus-group-score-map) + (define-key gnus-group-score-map "f" 'gnus-score-flush-cache) + (define-prefix-command 'gnus-group-sub-map) (define-key gnus-group-mode-map "S" 'gnus-group-sub-map) (define-key gnus-group-sub-map "l" 'gnus-group-set-current-level) *************** *** 3308,3314 **** \\{gnus-group-mode-map}" (interactive) ! (if gnus-visual (gnus-group-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) --- 3320,3326 ---- \\{gnus-group-mode-map}" (interactive) ! (if (gnus-visual-p 'group-menu 'menu) (gnus-group-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) *************** *** 4044,4049 **** --- 4056,4071 ---- (interactive "P") (gnus-group-read-group all t)) + (defun gnus-group-quick-select-group (&optional all) + "Select the current group \"quickly\". + This means that no highlights or scoring will be performed." + (interactive "P") + (let (gnus-visual + gnus-score-find-score-files-function + gnus-apply-kill-hook + gnus-summary-expunge-below) + (gnus-group-read-group all t))) + (defun gnus-group-select-group-all () "Select the current group and display all articles in it." (interactive) *************** *** 4610,4616 **** (defun gnus-group-set-current-level (n level) "Set the level of the next N groups to LEVEL." ! (interactive "P\nnLevel: ") (or (and (>= level 1) (<= level gnus-level-killed)) (error "Illegal level: %d" level)) (let ((groups (gnus-group-process-prefix n)) --- 4632,4643 ---- (defun gnus-group-set-current-level (n level) "Set the level of the next N groups to LEVEL." ! (interactive ! (list ! (prefix-numeric-value current-prefix-arg) ! (string-to-int ! (read-string (format "Level (default %s): " (gnus-group-group-level)) ! (int-to-string (gnus-group-group-level)))))) (or (and (>= level 1) (<= level gnus-level-killed)) (error "Illegal level: %d" level)) (let ((groups (gnus-group-process-prefix n)) *************** *** 4807,4818 **** (goto-char (point-min))) (gnus-group-position-point)) (defun gnus-group-get-new-news (&optional arg) "Get newly arrived articles. ! If ARG is non-nil, it should be a number between one and nine to ! specify which levels you are interested in re-scanning." (interactive "P") (run-hooks 'gnus-get-new-news-hook) (setq arg (gnus-group-default-level arg t)) (if (and gnus-read-active-file (not arg)) (progn --- 4834,4878 ---- (goto-char (point-min))) (gnus-group-position-point)) + (defun gnus-group-list-active () + "List all groups that are available from the server(s)." + (interactive) + ;; First we make sure that we have really read the active file. + (or gnus-have-read-active-file + (gnus-read-active-file)) + ;; Find all groups and sort them. + (let ((groups + (sort + (let (list) + (mapatoms + (lambda (sym) + (and (symbol-value sym) + (setq list (cons (symbol-name sym) list)))) + gnus-active-hashtb) + list) + 'string<)) + (buffer-read-only nil)) + (erase-buffer) + (while groups + (gnus-group-insert-group-line-info (car groups)) + (setq groups (cdr groups))) + (goto-char (point-min)))) + (defun gnus-group-get-new-news (&optional arg) "Get newly arrived articles. ! If ARG is a number, it specifies which levels you are interested in ! re-scanning. If ARG is non-nil and not a number, this will force ! \"hard\" re-reading of the active files from all servers." (interactive "P") (run-hooks 'gnus-get-new-news-hook) + ;; If ARG is not a number, then we read the active file. + (and arg + (not (numberp arg)) + (progn + (let ((gnus-read-active-file t)) + (gnus-read-active-file)) + (setq arg nil))) + (setq arg (gnus-group-default-level arg t)) (if (and gnus-read-active-file (not arg)) (progn *************** *** 4853,4863 **** (gnus-group-update-group-line) t))) ! (defun gnus-group-fetch-faq (group) "Fetch the FAQ for the current group." ! (interactive (list (gnus-group-real-name (gnus-group-group-name)))) (or group (error "No group name given")) ! (let ((file (concat gnus-group-faq-directory (gnus-group-real-name group)))) (if (not (file-exists-p file)) (error "No such file: %s" file) (find-file file)))) --- 4913,4934 ---- (gnus-group-update-group-line) t))) ! (defun gnus-group-fetch-faq (group &optional faq-dir) "Fetch the FAQ for the current group." ! (interactive ! (list ! (gnus-group-real-name (gnus-group-group-name)) ! (cond (current-prefix-arg ! (completing-read ! "Faq dir: " (and (listp gnus-group-faq-directory) ! gnus-group-faq-directory)))))) ! (or faq-dir ! (if (listp gnus-group-faq-directory) ! (car gnus-group-faq-directory) ! gnus-group-faq-directory)) (or group (error "No group name given")) ! (let ((file (concat (file-name-as-directory faq-dir) ! (gnus-group-real-name group)))) (if (not (file-exists-p file)) (error "No such file: %s" file) (find-file file)))) *************** *** 5253,5259 **** 3) `\\[gnus-browse-exit]' to return to the group buffer." (interactive) (kill-all-local-variables) ! (if gnus-visual (gnus-browse-make-menu-bar)) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) (setq mode-line-format (copy-sequence mode-line-format)) --- 5324,5330 ---- 3) `\\[gnus-browse-exit]' to return to the group buffer." (interactive) (kill-all-local-variables) ! (if (gnus-visual-p 'browse-menu 'menu) (gnus-browse-make-menu-bar)) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) (setq mode-line-format (copy-sequence mode-line-format)) *************** *** 5720,5726 **** \\{gnus-summary-mode-map}" (interactive) ! (if gnus-visual (gnus-summary-make-menu-bar)) (kill-all-local-variables) (let ((locals gnus-summary-local-variables)) (while locals --- 5791,5797 ---- \\{gnus-summary-mode-map}" (interactive) ! (if (gnus-visual-p 'summary-menu 'menu) (gnus-summary-make-menu-bar)) (kill-all-local-variables) (let ((locals gnus-summary-local-variables)) (while locals *************** *** 5845,5853 **** (while (cdr data) (and (= (gnus-data-number (car (cdr data))) article) (progn (setcdr data (cdr (cdr data))) (setq data nil ! gnus-newsgroup-data-reverse nil))))))) (defmacro gnus-data-list (backward) (` (if (, backward) --- 5916,5926 ---- (while (cdr data) (and (= (gnus-data-number (car (cdr data))) article) (progn + (set-marker (gnus-data-pos (car (cdr data))) nil) (setcdr data (cdr (cdr data))) (setq data nil ! gnus-newsgroup-data-reverse nil))) ! (setq data (cdr data)))))) (defmacro gnus-data-list (backward) (` (if (, backward) *************** *** 5967,5972 **** --- 6040,6046 ---- (marked gnus-newsgroup-marked) (unread gnus-newsgroup-unreads) (headers gnus-current-headers) + (data gnus-newsgroup-data) (score-file gnus-current-score-file)) (save-excursion (set-buffer gnus-group-buffer) *************** *** 5974,5979 **** --- 6048,6054 ---- (setq gnus-newsgroup-marked marked) (setq gnus-newsgroup-unreads unread) (setq gnus-current-headers headers) + (setq gnus-newsgroup-data data) (setq gnus-current-score-file score-file)))))) (defun gnus-summary-insert-dummy-line (sformat subject number) *************** *** 6051,6057 **** (gnus-summary-mark-article-as-read gnus-low-score-mark)) (and (eq (gnus-summary-article-mark) gnus-low-score-mark) (gnus-summary-mark-article-as-unread gnus-unread-mark)))) ! (and gnus-visual (run-hooks 'gnus-summary-update-hook)))))) (defun gnus-summary-update-lines (&optional beg end) --- 6126,6132 ---- (gnus-summary-mark-article-as-read gnus-low-score-mark)) (and (eq (gnus-summary-article-mark) gnus-low-score-mark) (gnus-summary-mark-article-as-unread gnus-unread-mark)))) ! (and (gnus-visual-p 'summary-highlight 'highlight) (run-hooks 'gnus-summary-update-hook)))))) (defun gnus-summary-update-lines (&optional beg end) *************** *** 6084,6090 **** gnus-low-score-mark) (gnus-summary-mark-article-as-unread gnus-unread-mark))) ;; Do the visual highlights at the same time. ! (and gnus-visual (run-hooks 'gnus-summary-update-hook)) (forward-line 1))))))) (defvar gnus-tmp-gathered nil) --- 6159,6166 ---- gnus-low-score-mark) (gnus-summary-mark-article-as-unread gnus-unread-mark))) ;; Do the visual highlights at the same time. ! (and (gnus-visual-p 'summary-highlight 'highlight) ! (run-hooks 'gnus-summary-update-hook)) (forward-line 1))))))) (defvar gnus-tmp-gathered nil) *************** *** 6120,6129 **** (set (car elem) (eval (nth 1 elem)))))))) (defun gnus-summary-read-group ! (group &optional show-all no-article kill-buffer) "Start reading news in newsgroup GROUP. If SHOW-ALL is non-nil, already read articles are also listed. ! If NO-ARTICLE is non-nil, no article is selected initially." (gnus-message 5 "Retrieving newsgroup: %s..." group) (let* ((new-group (gnus-summary-setup-buffer group)) (quit-config (nth 1 (assoc 'quit-config (gnus-find-method-for-group --- 6196,6206 ---- (set (car elem) (eval (nth 1 elem)))))))) (defun gnus-summary-read-group ! (group &optional show-all no-article kill-buffer no-display) "Start reading news in newsgroup GROUP. If SHOW-ALL is non-nil, already read articles are also listed. ! If NO-ARTICLE is non-nil, no article is selected initially. ! If NO-DISPLAY, don't generate a summary buffer." (gnus-message 5 "Retrieving newsgroup: %s..." group) (let* ((new-group (gnus-summary-setup-buffer group)) (quit-config (nth 1 (assoc 'quit-config (gnus-find-method-for-group *************** *** 6188,6194 **** (and gnus-use-scoring (gnus-possibly-score-headers)) (gnus-update-format-specifications) ;; Generate the summary buffer. ! (gnus-summary-prepare) (if (zerop (buffer-size)) (cond (gnus-newsgroup-dormant (gnus-summary-limit-include-dormant)) --- 6265,6272 ---- (and gnus-use-scoring (gnus-possibly-score-headers)) (gnus-update-format-specifications) ;; Generate the summary buffer. ! (or no-display ! (gnus-summary-prepare)) (if (zerop (buffer-size)) (cond (gnus-newsgroup-dormant (gnus-summary-limit-include-dormant)) *************** *** 6349,6355 **** ;; This function makes a sub-tree for a node in the tree. (let ((children (reverse (cdr (gnus-gethash (downcase (mail-header-id root)) gnus-newsgroup-dependencies))))) ! (cons root (mapcar 'gnus-make-sub-thread children)))) (defun gnus-build-old-threads () ;; Look at all the articles that refer back to old articles, and --- 6427,6433 ---- ;; This function makes a sub-tree for a node in the tree. (let ((children (reverse (cdr (gnus-gethash (downcase (mail-header-id root)) gnus-newsgroup-dependencies))))) ! (cons root (mapcar (lambda (c) (gnus-make-sub-thread (car c))) children)))) (defun gnus-build-old-threads () ;; Look at all the articles that refer back to old articles, and *************** *** 6363,6369 **** (progn (setq heads (cdr (symbol-value refs))) (while heads ! (if (not (memq (mail-header-number (car heads)) gnus-newsgroup-dormant)) (progn (setq id (symbol-name refs)) --- 6441,6447 ---- (progn (setq heads (cdr (symbol-value refs))) (while heads ! (if (not (memq (mail-header-number (car (car heads))) gnus-newsgroup-dormant)) (progn (setq id (symbol-name refs)) *************** *** 6408,6415 **** (defun gnus-rebuild-thread (id) (let ((dep gnus-newsgroup-dependencies) (buffer-read-only nil) ! (current (gnus-summary-article-number)) ! parent headers refs thread art data) (while (and id (setq headers (car (setq art (gnus-gethash (downcase id) dep))))) (setq parent art) --- 6486,6492 ---- (defun gnus-rebuild-thread (id) (let ((dep gnus-newsgroup-dependencies) (buffer-read-only nil) ! current parent headers refs thread art data) (while (and id (setq headers (car (setq art (gnus-gethash (downcase id) dep))))) (setq parent art) *************** *** 6419,6424 **** --- 6496,6504 ---- (setq thread (gnus-make-sub-thread (car parent))) (gnus-rebuild-remove-articles thread) (let ((beg (point))) + (setq current (save-excursion + (forward-line -1) + (gnus-summary-article-number))) (let (gnus-newsgroup-data) (gnus-summary-prepare-threads (list thread)) (setq data (nreverse gnus-newsgroup-data))) *************** *** 6620,6627 **** ((and (null gnus-thread-ignore-subject) (not (zerop level)) gnus-tmp-prev-subject ! (not (string= gnus-tmp-prev-subject ! (gnus-simplify-subject-re subject)))) (setq new-roots (if (cdr (car thread)) (nconc new-roots (list (car thread))) new-roots) --- 6700,6706 ---- ((and (null gnus-thread-ignore-subject) (not (zerop level)) gnus-tmp-prev-subject ! (not (gnus-subject-equal gnus-tmp-prev-subject subject))) (setq new-roots (if (cdr (car thread)) (nconc new-roots (list (car thread))) new-roots) *************** *** 6668,6676 **** ((memq number gnus-newsgroup-expirable) gnus-expirable-mark) (t (or (cdr (assq number gnus-newsgroup-reads)) gnus-ancient-mark)))) - (setq gnus-newsgroup-data - (cons (gnus-data-make number mark (point) header level) - gnus-newsgroup-data)) (inline (gnus-summary-insert-line nil header level nil mark --- 6747,6752 ---- *************** *** 6679,6687 **** (cond ((and gnus-thread-ignore-subject gnus-tmp-prev-subject ! (not (string= ! gnus-tmp-prev-subject ! (gnus-simplify-subject-re subject)))) subject) ((zerop level) (if (and (eq gnus-summary-make-false-root 'empty) --- 6755,6762 ---- (cond ((and gnus-thread-ignore-subject gnus-tmp-prev-subject ! (not (gnus-subject-equal ! gnus-tmp-prev-subject subject))) subject) ((zerop level) (if (and (eq gnus-summary-make-false-root 'empty) *************** *** 6694,6699 **** --- 6769,6779 ---- (memq number gnus-tmp-gathered)) (cdr (assq number gnus-newsgroup-scored)))) + (setq gnus-newsgroup-data + (cons (gnus-data-make number mark (- (point) 4) + header level) + gnus-newsgroup-data)) + (setq gnus-tmp-prev-subject (gnus-simplify-subject-re subject))))) *************** *** 6739,6745 **** (t (or (cdr (assq number gnus-newsgroup-reads)) gnus-ancient-mark)))) (setq gnus-newsgroup-data ! (cons (gnus-data-make number mark (point) header 0) gnus-newsgroup-data)) (gnus-summary-insert-line nil header 0 nil mark (memq number gnus-newsgroup-replied) --- 6819,6825 ---- (t (or (cdr (assq number gnus-newsgroup-reads)) gnus-ancient-mark)))) (setq gnus-newsgroup-data ! (cons (gnus-data-make number mark (1+ (point)) header 0) gnus-newsgroup-data)) (gnus-summary-insert-line nil header 0 nil mark (memq number gnus-newsgroup-replied) *************** *** 7238,7244 **** (defun gnus-get-newsgroup-headers () (setq gnus-article-internal-prepare-hook nil) (let ((cur nntp-server-buffer) ! (dependencies gnus-newsgroup-dependencies) headers id id-dep ref-dep end ref) (save-excursion (set-buffer nntp-server-buffer) --- 7318,7325 ---- (defun gnus-get-newsgroup-headers () (setq gnus-article-internal-prepare-hook nil) (let ((cur nntp-server-buffer) ! (dependencies (save-excursion (set-buffer gnus-summary-buffer) ! gnus-newsgroup-dependencies)) headers id id-dep ref-dep end ref) (save-excursion (set-buffer nntp-server-buffer) *************** *** 7265,7271 **** (forward-line 1) (setq p (point)) (narrow-to-region (point) ! (or (search-forward "\n.\n" nil t) (point)))) ;; Subject. (progn --- 7346,7353 ---- (forward-line 1) (setq p (point)) (narrow-to-region (point) ! (or (and (search-forward "\n.\n" nil t) ! (- (point) 2)) (point)))) ;; Subject. (progn *************** *** 7514,7557 **** (progn (end-of-line) (point)))) (mail-header-set-xref headers xref)))))))) ! (defun gnus-more-header-backward () ! "Find new header backward." ! (let ((first (car (gnus-gethash gnus-newsgroup-name gnus-active-hashtb))) ! (artnum gnus-newsgroup-begin) ! (header nil)) ! (while (and (not header) ! (> artnum first)) ! (setq artnum (1- artnum)) ! (setq header (gnus-read-header artnum))) ! header)) ! ! (defun gnus-more-header-forward (&optional backward) ! "Find new header forward. ! If BACKWARD, find new header backward instead." ! (if backward ! (gnus-more-header-backward) ! (let ((last (cdr (gnus-gethash gnus-newsgroup-name gnus-active-hashtb))) ! (artnum gnus-newsgroup-end) ! (header nil)) ! (while (and (not header) ! (< artnum last)) ! (setq artnum (1+ artnum)) ! (setq header (gnus-read-header artnum))) ! header))) ! ! (defun gnus-extend-newsgroup (header &optional backward) ! "Extend newsgroup selection with HEADER. ! Optional argument BACKWARD means extend toward backward." ! (if header ! (let ((artnum (mail-header-number header))) ! (setq gnus-newsgroup-headers ! (if backward ! (cons header gnus-newsgroup-headers) ! (nconc gnus-newsgroup-headers (list header)))) ! (setq gnus-newsgroup-unselected ! (delq artnum gnus-newsgroup-unselected)) ! (setq gnus-newsgroup-begin (min gnus-newsgroup-begin artnum)) ! (setq gnus-newsgroup-end (max gnus-newsgroup-end artnum))))) (defun gnus-summary-work-articles (n) "Return a list of articles to be worked upon. The prefix argument, --- 7596,7619 ---- (progn (end-of-line) (point)))) (mail-header-set-xref headers xref)))))))) ! ;; Insert article ID in the summary buffer and select it as well. ! (defun gnus-summary-insert-article (id) ! (let ((header (gnus-read-header id)) ! number) ! (if (not header) ! () ; We couldn't fetch ID. ! (gnus-rebuild-thread (mail-header-id header)) ! (gnus-summary-goto-subject (setq number (mail-header-number header))) ! (and (> number 0) ! (progn ! ;; We have to update the boundaries, possibly. ! (and (> number gnus-newsgroup-end) ! (setq gnus-newsgroup-end number)) ! (and (< number gnus-newsgroup-begin) ! (setq gnus-newsgroup-begin number)) ! (setq gnus-newsgroup-unselected ! (delq number gnus-newsgroup-unselected)))) ! (gnus-summary-show-article)))) (defun gnus-summary-work-articles (n) "Return a list of articles to be worked upon. The prefix argument, *************** *** 7945,7955 **** (gnus-configure-windows (cdr quit-config))))))))) ;; Suggested by Andrew Eskilsson . ! (defun gnus-summary-fetch-faq (group) ! "Fetch the FAQ for the current group." ! (interactive (list gnus-newsgroup-name)) (let (gnus-faq-buffer) ! (and (setq gnus-faq-buffer (gnus-group-fetch-faq group)) (gnus-configure-windows 'summary-faq)))) ;; Suggested by Per Abrahamsen . --- 8007,8025 ---- (gnus-configure-windows (cdr quit-config))))))))) ;; Suggested by Andrew Eskilsson . ! (defun gnus-summary-fetch-faq (&optional faq-dir) ! "Fetch the FAQ for the current group. ! If FAQ-DIR (the prefix), prompt for a directory to search for the faq ! in." ! (interactive ! (list ! (if current-prefix-arg ! (completing-read ! "Faq dir: " (and (listp gnus-group-faq-directory) ! gnus-group-faq-directory))))) (let (gnus-faq-buffer) ! (and (setq gnus-faq-buffer ! (gnus-group-fetch-faq gnus-newsgroup-name faq-dir)) (gnus-configure-windows 'summary-faq)))) ;; Suggested by Per Abrahamsen . *************** *** 8147,8153 **** (interactive "p") (gnus-summary-next-subject (- n) t)) ! (defun gnus-summary-goto-subject (article) "Go the subject line of ARTICLE." (interactive (list --- 8217,8223 ---- (interactive "p") (gnus-summary-next-subject (- n) t)) ! (defun gnus-summary-goto-subject (article &optional force) "Go the subject line of ARTICLE." (interactive (list *************** *** 8163,8180 **** (let ((b (point)) (data (gnus-data-find article))) (if (not data) ! () ! (goto-char (gnus-data-pos data)) ! (gnus-summary-show-thread) ! ;; Skip dummy articles. ! (if (eq (gnus-summary-article-mark) gnus-dummy-mark) ! (gnus-summary-find-next)) ! (prog1 ! (if (not (eobp)) ! article ! (goto-char b) ! nil) ! (gnus-summary-position-point))))) ;; Walking around summary lines with displaying articles. --- 8233,8254 ---- (let ((b (point)) (data (gnus-data-find article))) (if (not data) ! (progn ! (and (gnus-summary-insert-article article) ! (setq data (gnus-data-find article)))) ! (if (not data) ! (message "Can't find article %d" article) ! (goto-char (gnus-data-pos data)) ! (gnus-summary-show-thread) ! ;; Skip dummy articles. ! (if (eq (gnus-summary-article-mark) gnus-dummy-mark) ! (gnus-summary-find-next)) ! (prog1 ! (if (not (eobp)) ! article ! (goto-char b) ! nil) ! (gnus-summary-position-point)))))) ;; Walking around summary lines with displaying articles. *************** *** 8265,8278 **** (gnus-message 6 "Wrapped")) ;; Try to get next/previous article not displayed in this group. ((and gnus-auto-extend-newsgroup ! (not unread) (not subject) ! (setq header (gnus-more-header-forward backward))) ! (gnus-extend-newsgroup header backward) ! (let ((buffer-read-only nil)) ! (goto-char (if backward (point-min) (point-max))) ! (gnus-summary-prepare-threads (list header))) ! (gnus-summary-goto-article (if backward gnus-newsgroup-begin ! gnus-newsgroup-end))) ;; Go to next/previous group. (t (or (assoc 'quit-config (gnus-find-method-for-group gnus-newsgroup-name)) --- 8339,8348 ---- (gnus-message 6 "Wrapped")) ;; Try to get next/previous article not displayed in this group. ((and gnus-auto-extend-newsgroup ! (not unread) (not subject)) ! (gnus-summary-goto-article ! (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end)) ! nil t)) ;; Go to next/previous group. (t (or (assoc 'quit-config (gnus-find-method-for-group gnus-newsgroup-name)) *************** *** 8479,8485 **** (error "No unread articles")) (gnus-summary-position-point))) ! (defun gnus-summary-goto-article (article &optional all-headers) "Fetch ARTICLE and display it if it exists. If ALL-HEADERS is non-nil, no header lines are hidden." (interactive --- 8549,8555 ---- (error "No unread articles")) (gnus-summary-position-point))) ! (defun gnus-summary-goto-article (article &optional all-headers force) "Fetch ARTICLE and display it if it exists. If ALL-HEADERS is non-nil, no header lines are hidden." (interactive *************** *** 8492,8498 **** gnus-newsgroup-headers) nil 'require-match)))) (prog1 ! (and (gnus-summary-goto-subject article) (gnus-summary-display-article article all-headers)) (gnus-summary-position-point))) --- 8562,8568 ---- gnus-newsgroup-headers) nil 'require-match)))) (prog1 ! (and (gnus-summary-goto-subject article force) (gnus-summary-display-article article all-headers)) (gnus-summary-position-point))) *************** *** 8736,8750 **** (let ((header (car (gnus-gethash (downcase message-id) gnus-newsgroup-dependencies)))) (if header ! (or (gnus-summary-goto-article (mail-header-number header)) ! ;; The header has been read, but the article had been ! ;; expunged, so we insert it again. ! (progn ! (gnus-summary-insert-line ! nil header 0 nil gnus-read-mark nil nil ! (mail-header-subject header)) ! (forward-line -1) ! (mail-header-number header))) (let ((gnus-override-method gnus-refer-article-method) (gnus-ancient-mark gnus-read-mark) (tmp-point (window-start --- 8806,8814 ---- (let ((header (car (gnus-gethash (downcase message-id) gnus-newsgroup-dependencies)))) (if header ! ;; The article is present in the buffer, to we just go to it. ! (gnus-summary-goto-article (mail-header-number header) nil t) ! ;; We fetch the article (let ((gnus-override-method gnus-refer-article-method) (gnus-ancient-mark gnus-read-mark) (tmp-point (window-start *************** *** 8752,8787 **** number tmp-buf) (and gnus-refer-article-method (gnus-check-server gnus-refer-article-method)) ! ;; Save the old article buffer. ! (save-excursion ! (set-buffer (gnus-article-setup-buffer)) ! (gnus-kill-buffer " *temp Article*") ! (setq tmp-buf (rename-buffer " *temp Article*"))) ! (prog1 ! (if (gnus-article-prepare ! message-id nil (gnus-read-header message-id)) ! (progn ! (setq number (mail-header-number gnus-current-headers)) ! (gnus-rebuild-thread message-id) ! (gnus-summary-goto-subject number) ! (if (null gnus-use-full-window) ! (progn ! (delete-windows-on tmp-buf) ! (gnus-configure-windows 'article 'force))) ! (gnus-summary-recenter) ! (gnus-article-set-window-start ! (cdr (assq number gnus-newsgroup-bookmarks))) ! message-id) ! ;; We restore the old article buffer. ! (save-excursion ! (kill-buffer gnus-article-buffer) ! (set-buffer tmp-buf) ! (rename-buffer gnus-article-buffer) ! (let ((buffer-read-only nil)) ! (and tmp-point ! (set-window-start (get-buffer-window (current-buffer)) ! tmp-point))) ! nil)))))))) (defun gnus-summary-enter-digest-group () "Enter a digest group based on the current article." --- 8816,8822 ---- number tmp-buf) (and gnus-refer-article-method (gnus-check-server gnus-refer-article-method)) ! (gnus-summary-insert-article message-id)))))) (defun gnus-summary-enter-digest-group () "Enter a digest group based on the current article." *************** *** 8967,8977 **** (recenter -3) (and gnus-break-pages (gnus-narrow-to-page)))) ! (defun gnus-summary-show-article () ! "Force re-fetching of the current article." ! (interactive) (gnus-set-global-variables) ! (gnus-summary-select-article nil 'force) (gnus-configure-windows 'article) (gnus-summary-position-point)) --- 9002,9022 ---- (recenter -3) (and gnus-break-pages (gnus-narrow-to-page)))) ! (defun gnus-summary-show-article (&optional arg) ! "Force re-fetching of the current article. ! If ARG (the prefix) is non-nil, show the raw article without any ! article massaging functions being run." ! (interactive "P") (gnus-set-global-variables) ! (if (not arg) ! ;; Select the article the normal way. ! (gnus-summary-select-article nil 'force) ! ;; Bind the article treatment functions to nil. ! (let ((gnus-have-all-headers t) ! gnus-article-display-hook ! gnus-article-prepare-hook ! gnus-visual) ! (gnus-summary-select-article nil 'force))) (gnus-configure-windows 'article) (gnus-summary-position-point)) *************** *** 9437,9443 **** (setq buffer-read-only t) (buffer-disable-undo (current-buffer)) (gnus-configure-windows 'summary)) ! (and gnus-visual (run-hooks 'gnus-visual-mark-article-hook))))) (defun gnus-summary-edit-article-postpone () "Postpone changes to the current article." --- 9482,9489 ---- (setq buffer-read-only t) (buffer-disable-undo (current-buffer)) (gnus-configure-windows 'summary)) ! (and (gnus-visual-p 'summary-highlight 'highlight) ! (run-hooks 'gnus-visual-mark-article-hook))))) (defun gnus-summary-edit-article-postpone () "Postpone changes to the current article." *************** *** 9447,9453 **** (setq buffer-read-only t) (buffer-disable-undo (current-buffer)) (gnus-configure-windows 'summary) ! (and gnus-visual (run-hooks 'gnus-visual-mark-article-hook))) (defun gnus-summary-respool-query () "Query where the respool algorithm would put this article." --- 9493,9500 ---- (setq buffer-read-only t) (buffer-disable-undo (current-buffer)) (gnus-configure-windows 'summary) ! (and (gnus-visual-p 'summary-highlight 'highlight) ! (run-hooks 'gnus-visual-mark-article-hook))) (defun gnus-summary-respool-query () "Query where the respool algorithm would put this article." *************** *** 10904,10910 **** \\[gnus-article-describe-briefly]\t Describe the current mode briefly \\[gnus-info-find-node]\t Go to the Gnus info node" (interactive) ! (if gnus-visual (gnus-article-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) --- 10951,10957 ---- \\[gnus-article-describe-briefly]\t Describe the current mode briefly \\[gnus-info-find-node]\t Go to the Gnus info node" (interactive) ! (if (gnus-visual-p 'article-menu 'menu) (gnus-article-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) *************** *** 10959,11019 **** (defun gnus-request-article-this-buffer (article group) "Get an article and insert it into this buffer." ! (setq group (or group gnus-newsgroup-name)) ! ;; Open server if it has closed. ! (gnus-check-server (gnus-find-method-for-group group)) ! ;; Using `gnus-request-article' directly will insert the article into ! ;; `nntp-server-buffer' - so we'll save some time by not having to ! ;; copy it from the server buffer into the article buffer. ! ! ;; We only request an article by message-id when we do not have the ! ;; headers for it, so we'll have to get those. ! (and (stringp article) ! (let ((gnus-override-method gnus-refer-article-method)) ! (gnus-read-header article))) ! ! ;; If the article number is negative, that means that this article ! ;; doesn't belong in this newsgroup (possibly), so we find its ! ;; message-id and request it by id instead of number. ! (if (not (numberp article)) ! () ! (save-excursion ! (set-buffer gnus-summary-buffer) ! (let ((header (gnus-summary-article-header article))) ! (if (< article 0) ! (if (vectorp header) ! ;; It's a real article. ! (setq article (mail-header-id header)) ! ;; It is an extracted pseudo-article. ! (setq article 'pseudo) ! (gnus-request-pseudo-article header))) ! (let ((method (gnus-find-method-for-group gnus-newsgroup-name))) ! (if (not (eq (car method) 'nneething)) ! () ! (let ((dir (concat (file-name-as-directory (nth 1 method)) ! (mail-header-subject header)))) ! (if (file-directory-p dir) ! (progn ! (setq article 'nneething) ! (gnus-group-enter-directory dir))))))))) ! ;; Check the cache. ! (if (and gnus-use-cache ! (numberp article) ! (gnus-cache-request-article article group)) ! 'article ! ;; Get the article and into the article buffer. ! (if (or (stringp article) (numberp article)) ! (progn ! (erase-buffer) ! (let ((gnus-override-method ! (and (stringp article) gnus-refer-article-method))) ! (and (gnus-request-article article group (current-buffer)) ! 'article))) ! article))) (defun gnus-read-header (id) "Read the headers of article ID and enter them into the Gnus system." --- 11006,11077 ---- (defun gnus-request-article-this-buffer (article group) "Get an article and insert it into this buffer." ! (prog1 ! (save-excursion ! (if (get-buffer gnus-original-article-buffer) ! (set-buffer (get-buffer gnus-original-article-buffer)) ! (set-buffer (get-buffer-create gnus-original-article-buffer)) ! (buffer-disable-undo (current-buffer)) ! (gnus-add-current-to-buffer-list)) ! (erase-buffer) ! (setq group (or group gnus-newsgroup-name)) ! ;; Open server if it has closed. ! (gnus-check-server (gnus-find-method-for-group group)) ! ;; Using `gnus-request-article' directly will insert the article into ! ;; `nntp-server-buffer' - so we'll save some time by not having to ! ;; copy it from the server buffer into the article buffer. ! ! ;; We only request an article by message-id when we do not have the ! ;; headers for it, so we'll have to get those. ! (and (stringp article) ! (let ((gnus-override-method gnus-refer-article-method)) ! (gnus-read-header article))) ! ! ;; If the article number is negative, that means that this article ! ;; doesn't belong in this newsgroup (possibly), so we find its ! ;; message-id and request it by id instead of number. ! (if (not (numberp article)) ! () ! (save-excursion ! (set-buffer gnus-summary-buffer) ! (let ((header (gnus-summary-article-header article))) ! (if (< article 0) ! (if (vectorp header) ! ;; It's a real article. ! (setq article (mail-header-id header)) ! ;; It is an extracted pseudo-article. ! (setq article 'pseudo) ! (gnus-request-pseudo-article header))) ! ! (let ((method (gnus-find-method-for-group gnus-newsgroup-name))) ! (if (not (eq (car method) 'nneething)) ! () ! (let ((dir (concat (file-name-as-directory (nth 1 method)) ! (mail-header-subject header)))) ! (if (file-directory-p dir) ! (progn ! (setq article 'nneething) ! (gnus-group-enter-directory dir))))))))) ! ;; Check the cache. ! (if (and gnus-use-cache ! (numberp article) ! (gnus-cache-request-article article group)) ! 'article ! ;; Get the article and into the article buffer. ! (if (or (stringp article) (numberp article)) ! (progn ! (erase-buffer) ! (let ((gnus-override-method ! (and (stringp article) gnus-refer-article-method))) ! (and (gnus-request-article article group (current-buffer)) ! 'article))) ! article))) ! (erase-buffer) ! (insert-buffer gnus-original-article-buffer))) (defun gnus-read-header (id) "Read the headers of article ID and enter them into the Gnus system." *************** *** 11030,11036 **** (goto-char (point-max)) (insert ".\n") (goto-char (point-min)) ! (insert "211 " (int-to-string (cdr where)) " Article retrieved.\n") (if (not (setq header (car (gnus-get-newsgroup-headers)))) () ; Malformed head. (if (and (stringp id) --- 11088,11103 ---- (goto-char (point-max)) (insert ".\n") (goto-char (point-min)) ! (insert "211 " ! (int-to-string ! (cond ! ((numberp id) ! id) ! ((cdr where) ! (cdr where)) ! (t ! gnus-reffed-article-number))) ! " Article retrieved.\n") (if (not (setq header (car (gnus-get-newsgroup-headers)))) () ; Malformed head. (if (and (stringp id) *************** *** 11039,11048 **** ;; If we fetched by Message-ID and the article came ;; from a different group, we fudge some bogus article ;; numbers for this article. ! (progn ! (mail-header-set-number header gnus-reffed-article-number) ! (setq gnus-reffed-article-number ! (1- gnus-reffed-article-number)))) (setq gnus-newsgroup-headers (cons header gnus-newsgroup-headers)) (setq gnus-current-headers header) header))))) --- 11106,11113 ---- ;; If we fetched by Message-ID and the article came ;; from a different group, we fudge some bogus article ;; numbers for this article. ! (mail-header-set-number header gnus-reffed-article-number)) ! (setq gnus-reffed-article-number (1- gnus-reffed-article-number)) (setq gnus-newsgroup-headers (cons header gnus-newsgroup-headers)) (setq gnus-current-headers header) header))))) *************** *** 11121,11127 **** (gnus-summary-show-thread) (run-hooks 'gnus-mark-article-hook) (gnus-set-mode-line 'summary) ! (and gnus-visual (run-hooks 'gnus-visual-mark-article-hook)) ;; Set the global newsgroup variables here. ;; Suggested by Jim Sisolak --- 11186,11192 ---- (gnus-summary-show-thread) (run-hooks 'gnus-mark-article-hook) (gnus-set-mode-line 'summary) ! (and (gnus-visual-p 'article-highlight 'highlight) (run-hooks 'gnus-visual-mark-article-hook)) ;; Set the global newsgroup variables here. ;; Suggested by Jim Sisolak *************** *** 11301,11306 **** --- 11366,11374 ---- (interactive (list 'force)) (save-excursion (set-buffer gnus-article-buffer) + ;; delete old process + (and (process-status "gnus-x-face") + (delete-process "gnus-x-face")) (let ((inhibit-point-motion-hooks t) (case-fold-search nil)) (save-restriction *************** *** 11325,11332 **** (error "%s is not a function" gnus-article-x-face-command)) (funcall gnus-article-x-face-command beg end)) ! (call-process-region beg end "sh" nil 0 nil ! "-c" gnus-article-x-face-command)))))))) (defun gnus-article-de-quoted-unreadable (&optional force) "Do a naïve translation of a quoted-printable-encoded article. --- 11393,11404 ---- (error "%s is not a function" gnus-article-x-face-command)) (funcall gnus-article-x-face-command beg end)) ! (let ((process-connection-type nil)) ! (process-kill-without-query ! (start-process "gnus-x-face" nil "sh" "-c" ! gnus-article-x-face-command)) ! (process-send-region "gnus-x-face" beg end) ! (process-send-eof "gnus-x-face"))))))))) (defun gnus-article-de-quoted-unreadable (&optional force) "Do a naïve translation of a quoted-printable-encoded article. *************** *** 11466,11472 **** (defun gnus-article-maybe-highlight () "Do some article highlighting if `gnus-visual' is non-nil." ! (if gnus-visual (gnus-article-highlight-some))) ;; Article savers. --- 11538,11545 ---- (defun gnus-article-maybe-highlight () "Do some article highlighting if `gnus-visual' is non-nil." ! (if (gnus-visual-p 'article-highlight 'highlight) ! (gnus-article-highlight-some))) ;; Article savers. *************** *** 12809,12814 **** --- 12882,12892 ---- ;; We escape all bugs and quit here to make it possible to ;; continue if a group is so out-there that it reports bugs ;; and stuff. + (progn + (and scan + (gnus-check-backend-function 'request-scan (car method)) + (gnus-request-scan group method)) + t) (condition-case () (gnus-request-group group) (error nil) *************** *** 12824,12832 **** group (setq active (cons (read (current-buffer)) (read (current-buffer)))) gnus-active-hashtb) - (and scan - (gnus-check-backend-function 'request-scan (car method)) - (gnus-request-scan group method)) ;; Return the new active info. active)))))) --- 12902,12907 ---- *************** *** 13840,13846 **** \\{gnus-server-mode-map}" (interactive) ! (if gnus-visual (gnus-server-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) --- 13915,13921 ---- \\{gnus-server-mode-map}" (interactive) ! (if (gnus-visual-p 'server-menu 'menu) (gnus-server-make-menu-bar)) (kill-all-local-variables) (setq mode-line-modified "-- ") (make-local-variable 'mode-line-format) *************** *** 14320,14330 **** (defun gnus-possibly-score-headers (&optional trace) (let ((func gnus-score-find-score-files-function) score-files) ! (and func (not (listp func)) (setq func (list func))) ;; Go through all the functions for finding score files (or actual ;; scores) and add them to a list. ! (setq score-files (gnus-score-find-alist gnus-newsgroup-name)) (while func (and (symbolp (car func)) (fboundp (car func)) --- 14395,14406 ---- (defun gnus-possibly-score-headers (&optional trace) (let ((func gnus-score-find-score-files-function) score-files) ! (and func ! (not (listp func)) (setq func (list func))) ;; Go through all the functions for finding score files (or actual ;; scores) and add them to a list. ! (and func (setq score-files (gnus-score-find-alist gnus-newsgroup-name))) (while func (and (symbolp (car func)) (fboundp (car func)) *** pub/sgnus/lisp/nnbabyl.el Thu Sep 21 01:16:45 1995 --- sgnus/lisp/nnbabyl.el Fri Sep 22 01:03:44 1995 *************** *** 249,256 **** (defun nnbabyl-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nnbabyl-request-post-buffer 'nnmail-request-post-buffer) - (defun nnbabyl-request-expire-articles (articles newsgroup &optional server force) (nnbabyl-possibly-change-newsgroup newsgroup) --- 249,254 ---- *** pub/sgnus/lisp/nndir.el Thu Sep 21 01:16:45 1995 --- sgnus/lisp/nndir.el Fri Sep 22 01:03:41 1995 *************** *** 113,120 **** (defun nndir-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nndir-request-post-buffer 'nnmail-request-post-buffer) - (defun nndir-request-expire-articles (articles group &optional server force) (nndir-execute-nnmh-command --- 113,118 ---- *** pub/sgnus/lisp/nndoc.el Thu Sep 21 01:16:46 1995 --- sgnus/lisp/nndoc.el Fri Sep 22 01:03:38 1995 *************** *** 257,263 **** nil) (defalias 'nndoc-request-post 'nnmail-request-post) - (defalias 'nndoc-request-post-buffer 'nnmail-request-post-buffer) ;;; Internal functions. --- 257,262 ---- *** pub/sgnus/lisp/nneething.el Thu Sep 21 01:16:46 1995 --- sgnus/lisp/nneething.el Fri Sep 22 01:03:40 1995 *************** *** 170,177 **** (defun nneething-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nneething-request-post-buffer 'nnmail-request-post-buffer) - (defun nneething-close-group (group &optional server) t) --- 170,175 ---- *** pub/sgnus/lisp/nnfolder.el Thu Sep 21 01:16:46 1995 --- sgnus/lisp/nnfolder.el Fri Sep 22 01:03:42 1995 *************** *** 311,318 **** (defun nnfolder-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nnfolder-request-post-buffer 'nnmail-request-post-buffer) - (defun nnfolder-request-expire-articles (articles newsgroup &optional server force) (nnfolder-possibly-change-group newsgroup) --- 311,316 ---- *** pub/sgnus/lisp/nnkiboze.el Thu Sep 21 01:16:46 1995 --- sgnus/lisp/nnkiboze.el Fri Sep 22 01:03:39 1995 *************** *** 182,189 **** (defalias 'nnkiboze-request-post 'nntp-request-post) - (defalias 'nnkiboze-request-post-buffer 'nntp-request-post-buffer) - ;;; Internal functions. --- 182,187 ---- *** pub/sgnus/lisp/nnmail.el Thu Sep 21 01:16:46 1995 --- sgnus/lisp/nnmail.el Fri Sep 22 01:13:47 1995 *************** *** 111,116 **** --- 111,119 ---- (defvar nnmail-resplit-incoming nil "*If non-nil, re-split incoming procmail sorted mail.") + (defvar nnmail-delete-file-function 'delete-file + "Function called to delete files in some mail backends.") + (defvar nnmail-movemail-program "movemail" "*A command to be executed to move mail from the inbox. The default is \"movemail\".") *************** *** 219,309 **** (defun nnmail-request-post (&optional server) (mail-send-and-exit nil)) - - (defun nnmail-request-post-buffer (post group subject header article-buffer - info follow-to respect-poster) - (let ((method-address (cdr (assq 'to-address (nth 5 info)))) - from date to reply-to message-of - references message-id cc new-cc sendto elt) - (setq method-address - (if (and (stringp method-address) - (string= method-address "")) - nil method-address)) - (save-excursion - (set-buffer (get-buffer-create "*mail*")) - (if (and (buffer-modified-p) - (> (buffer-size) 0) - (not (y-or-n-p "Unsent mail being composed; erase it? "))) - () - (erase-buffer) - (if post - (progn - (mail-setup method-address subject nil nil nil nil) - (auto-save-mode auto-save-default)) - (save-excursion - (set-buffer article-buffer) - (goto-char (point-min)) - (narrow-to-region (point-min) - (progn (search-forward "\n\n") (point))) - (let ((buffer-read-only nil)) - (set-text-properties (point-min) (point-max) nil)) - (setq from (mail-header-from header)) - (setq date (mail-header-date header)) - (and from - (let ((stop-pos - (string-match " *at \\| *@ \\| *(\\| *<" from))) - (setq message-of - (concat (if stop-pos (substring from 0 stop-pos) from) - "'s message of " date)))) - (setq cc (mail-strip-quoted-names (or (mail-fetch-field "cc") ""))) - (setq to (mail-strip-quoted-names (or (mail-fetch-field "to") ""))) - (setq new-cc (rmail-dont-reply-to - (concat (or to "") - (if cc (concat (if to ", " "") cc) "")))) - (let ((rmail-dont-reply-to-names - (regexp-quote (mail-strip-quoted-names - (or method-address reply-to from ""))))) - (setq new-cc (rmail-dont-reply-to new-cc))) - (setq subject (mail-header-subject header)) - (or (string-match "^[Rr][Ee]:" subject) - (setq subject (concat "Re: " subject))) - (setq reply-to (mail-fetch-field "reply-to")) - (setq references (mail-header-references header)) - (setq message-id (mail-header-id header)) - (widen)) - (setq news-reply-yank-from from) - (setq news-reply-yank-message-id message-id) - - ;; Gather the "to" addresses out of the follow-to list and remove - ;; them as we go. - (if (and follow-to (listp follow-to)) - (while (setq elt (assoc "To" follow-to)) - (setq sendto (concat sendto (and sendto ", ") (cdr elt))) - (setq follow-to (delq elt follow-to)))) - (mail-setup (if (and follow-to (listp follow-to)) - sendto - (or method-address reply-to from "")) - subject message-of - (if (zerop (length new-cc)) nil new-cc) - article-buffer nil) - (mail-mode) - (auto-save-mode auto-save-default) - ;; Note that "To" elements should already be in the message. - (if (and follow-to (listp follow-to)) - (progn - (goto-char (point-min)) - (re-search-forward "^To:" nil t) - (beginning-of-line) - (forward-line 1) - (while follow-to - (insert - (car (car follow-to)) ": " (cdr (car follow-to)) "\n") - (setq follow-to (cdr follow-to))))) - (nnheader-insert-references references message-id))) - (use-local-map (copy-keymap (current-local-map))) - (local-set-key "\C-c\C-c" 'gnus-mail-send-and-exit) - (local-set-key "\C-c\C-p" 'gnus-put-message) - (current-buffer)))) (defun nnmail-find-file (file) "Insert FILE in server buffer safely." --- 222,227 ---- *** pub/sgnus/lisp/nnmbox.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nnmbox.el Fri Sep 22 01:03:43 1995 *************** *** 237,244 **** (defun nnmbox-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nnmbox-request-post-buffer 'nnmail-request-post-buffer) - (defun nnmbox-request-expire-articles (articles newsgroup &optional server force) (nnmbox-possibly-change-newsgroup newsgroup) --- 237,242 ---- *** pub/sgnus/lisp/nnmh.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nnmh.el Fri Sep 22 01:03:45 1995 *************** *** 242,249 **** (defun nnmh-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nnmh-request-post-buffer 'nnmail-request-post-buffer) - (defun nnmh-request-expire-articles (articles newsgroup &optional server force) (nnmh-possibly-change-directory newsgroup) (let* ((days (or (and nnmail-expiry-wait-function --- 242,247 ---- *************** *** 276,285 **** days)))) (progn (and gnus-verbose-backends ! (message "Deleting article %d..." article newsgroup)) (condition-case () ! (delete-file article) (file-error (setq rest (cons (car articles) rest))))) (setq rest (cons (car articles) rest)))) --- 274,283 ---- days)))) (progn (and gnus-verbose-backends ! (message "Deleting article %s in %s..." article newsgroup)) (condition-case () ! (funcall nnmail-delete-file-function article) (file-error (setq rest (cons (car articles) rest))))) (setq rest (cons (car articles) rest)))) *************** *** 303,310 **** (kill-buffer (current-buffer)) result) (condition-case () ! (delete-file (concat nnmh-current-directory ! (int-to-string article))) (file-error nil))) result)) --- 301,308 ---- (kill-buffer (current-buffer)) result) (condition-case () ! (funcall nnmail-delete-file-function ! (concat nnmh-current-directory (int-to-string article))) (file-error nil))) result)) *** pub/sgnus/lisp/nnml.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nnml.el Fri Sep 22 14:55:29 1995 *************** *** 257,264 **** (defun nnml-request-post (&optional server) (mail-send-and-exit nil)) - (defalias 'nnml-request-post-buffer 'nnmail-request-post-buffer) - (defun nnml-request-expire-articles (articles newsgroup &optional server force) (nnml-possibly-change-directory newsgroup) (let* ((days (or (and nnmail-expiry-wait-function --- 257,262 ---- *************** *** 291,300 **** days))))) (progn (and gnus-verbose-backends ! (message "Deleting article %d in %s..." article newsgroup)) (condition-case () ! (delete-file article) (file-error (setq rest (cons (car articles) rest)))) (setq active-articles (delq (car articles) active-articles)) --- 289,298 ---- days))))) (progn (and gnus-verbose-backends ! (message "Deleting article %s in %s..." article newsgroup)) (condition-case () ! (funcall nnmail-delete-file-function article) (file-error (setq rest (cons (car articles) rest)))) (setq active-articles (delq (car articles) active-articles)) *************** *** 325,332 **** result) (progn (condition-case () ! (delete-file (concat nnml-current-directory ! (int-to-string article))) (file-error nil)) (nnml-nov-delete-article group article) (and last (nnml-save-nov)))) --- 323,331 ---- result) (progn (condition-case () ! (funcall nnmail-delete-file-function ! (concat nnml-current-directory ! (int-to-string article))) (file-error nil)) (nnml-nov-delete-article group article) (and last (nnml-save-nov)))) *************** *** 675,681 **** (save-excursion (set-buffer nntp-server-buffer) (if (file-exists-p nov) ! (delete-file nov)) (save-excursion (set-buffer nov-buffer) (buffer-disable-undo (current-buffer)) --- 674,680 ---- (save-excursion (set-buffer nntp-server-buffer) (if (file-exists-p nov) ! (funcall nnmail-delete-file-function nov)) (save-excursion (set-buffer nov-buffer) (buffer-disable-undo (current-buffer)) *** pub/sgnus/lisp/nnspool.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nnspool.el Fri Sep 22 01:13:46 1995 *************** *** 37,43 **** "Switches for nnspool-request-post to pass to `inews' for posting news. If you are using Cnews, you probably should set this variable to nil.") ! (defvar nnspool-spool-directory news-path "Local news spool directory.") (defvar nnspool-nov-directory (concat nnspool-spool-directory "over.view/") --- 37,43 ---- "Switches for nnspool-request-post to pass to `inews' for posting news. If you are using Cnews, you probably should set this variable to nil.") ! (defvar nnspool-spool-directory (file-name-as-directory news-path) "Local news spool directory.") (defvar nnspool-nov-directory (concat nnspool-spool-directory "over.view/") *************** *** 360,367 **** (message "nnspool: %s" nnspool-status-string) (ding) (run-hooks 'nnspool-rejected-article-hook)))) - - (defalias 'nnspool-request-post-buffer 'nntp-request-post-buffer) ;;; Internal functions. --- 360,365 ---- *** pub/sgnus/lisp/nntp.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nntp.el Fri Sep 22 22:42:49 1995 *************** *** 388,401 **** --- 388,416 ---- (kill-buffer nntp-async-buffer)))) (while nntp-async-group-alist (and (nth 3 (car nntp-async-group-alist)) + (progn + (condition-case () + (process-send-string (nth 3 nntp-async-group-alist) "QUIT\n") + (error nil)) + t) (delete-process (nth 3 (car nntp-async-group-alist)))) (setq nntp-async-group-alist (cdr nntp-async-group-alist))) (while nntp-server-alist (and (setq proc (nth 1 (assq 'nntp-server-process (car nntp-server-alist)))) + (progn + (condition-case () + (process-send-string proc "QUIT\n") + (error nil)) + t) (delete-process proc)) (and (setq proc (nth 1 (assq 'nntp-async-process (car nntp-server-alist)))) + (progn + (condition-case () + (process-send-string proc "QUIT\n") + (error nil)) + t) (delete-process proc)) (and (setq proc (nth 1 (assq 'nntp-async-buffer (car nntp-server-alist)))) *************** *** 602,688 **** ;; appended to end of the status message. (nntp-wait-for-response "^[23].*\n")))) - (defun nntp-request-post-buffer - (post group subject header article-buffer info follow-to respect-poster) - "Request a buffer suitable for composing an article. - If POST, this is an original article; otherwise it's a followup. - GROUP is the group to be posted to, the article should have subject - SUBJECT. HEADER is a Gnus header vector. ARTICLE-BUFFER contains the - article being followed up. INFO is a Gnus info list. If FOLLOW-TO, - post to this group instead. If RESPECT-POSTER, heed the special - \"poster\" value of the Followup-to header." - (if (assq 'to-address (nth 5 info)) - (nnmail-request-post-buffer - post group subject header article-buffer info follow-to respect-poster) - (let ((mail-default-headers - (or nntp-news-default-headers mail-default-headers)) - from date to followup-to newsgroups message-of - references distribution message-id) - (save-excursion - (set-buffer (get-buffer-create "*post-news*")) - (news-reply-mode) - (if (and (buffer-modified-p) - (> (buffer-size) 0) - (not (y-or-n-p "Unsent article being composed; erase it? "))) - () - (erase-buffer) - (if post - (news-setup nil subject nil group nil) - (save-excursion - (set-buffer article-buffer) - (goto-char (point-min)) - (narrow-to-region (point-min) - (progn (search-forward "\n\n") (point))) - (setq from (mail-header-from header)) - (setq date (mail-header-date header)) - (and from - (let ((stop-pos - (string-match " *at \\| *@ \\| *(\\| *<" from))) - (setq - message-of - (concat (if stop-pos (substring from 0 stop-pos) from) - "'s message of " date)))) - (setq subject (or subject (mail-header-subject header))) - (or (string-match "^[Rr][Ee]:" subject) - (setq subject (concat "Re: " subject))) - (setq followup-to (mail-fetch-field "followup-to")) - (if (or (null respect-poster) ;Ignore followup-to: field. - (string-equal "" followup-to) ;Bogus header. - (string-equal "poster" followup-to);Poster - (and (eq respect-poster 'ask) - followup-to - (not (y-or-n-p (concat "Followup to " - followup-to "? "))))) - (setq followup-to nil)) - (setq newsgroups - (or follow-to followup-to (mail-fetch-field "newsgroups"))) - (setq references (mail-header-references header)) - (setq distribution (mail-fetch-field "distribution")) - ;; Remove bogus distribution. - (and (stringp distribution) - (string-match "world" distribution) - (setq distribution nil)) - (setq message-id (mail-header-id header)) - (widen)) - (setq news-reply-yank-from from) - (setq news-reply-yank-message-id message-id) - (news-setup to subject message-of - (if (stringp newsgroups) newsgroups "") - article-buffer) - (if (and newsgroups (listp newsgroups)) - (progn - (goto-char (point-min)) - (while newsgroups - (insert (car (car newsgroups)) ": " - (cdr (car newsgroups)) "\n") - (setq newsgroups (cdr newsgroups))))) - (nnheader-insert-references references message-id) - (if distribution - (progn - (mail-position-on-field "Distribution") - (insert distribution))))) - (current-buffer))))) - ;;; Internal functions. (defun nntp-send-mode-reader () --- 617,622 ---- *************** *** 893,902 **** (goto-char (point-min)) ;; We first find the number by looking at the status line. (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ") ! (int-to-string ! (buffer-substring (match-beginning 0) ! (match-end 0))))) group newsgroups xref) ;; Then we find the group name. (setq group (cond --- 827,837 ---- (goto-char (point-min)) ;; We first find the number by looking at the status line. (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ") ! (string-to-int ! (buffer-substring (match-beginning 1) ! (match-end 1))))) group newsgroups xref) + (and number (zerop number) (setq number nil)) ;; Then we find the group name. (setq group (cond *************** *** 914,922 **** --- 849,860 ---- ;; article happens to have the same number in several ;; groups, but that's life. ((and (setq xref (mail-fetch-field "xref")) + number (string-match (format "\\([^ :]+\\):%d" number) xref)) (substring xref (match-beginning 1) (match-end 1))) (t ""))) + (and (string-match "\r" group) + (setq group (substring group 0 (match-beginning 0)))) (cons group number))))) (defun nntp-retrieve-headers-with-xover (sequence &optional fetch-old) *** pub/sgnus/lisp/nnvirtual.el Thu Sep 21 01:16:47 1995 --- sgnus/lisp/nnvirtual.el Fri Sep 22 01:03:37 1995 *************** *** 238,248 **** (defalias 'nnvirtual-request-post 'nntp-request-post) - (defun nnvirtual-request-post-buffer - (post group subject header article-buffer info follow-to respect-poster) - (nntp-request-post-buffer post "" subject header article-buffer - info follow-to respect-poster)) - ;;; Internal functions. --- 238,243 ---- *** pub/sgnus/lisp/ChangeLog Thu Sep 21 01:16:58 1995 --- sgnus/lisp/ChangeLog Fri Sep 22 22:42:59 1995 *************** *** 1,8 **** Wed Sep 20 22:20:09 1995 Lars Magne Ingebrigtsen * gnus.el (gnus-create-xref-hashtb): Our newsreader has Xrefs with "group/number" instead of "group:number". ! * gnus-msg.el (gnus-cancel-news): Make sure the From line is the read address. --- 1,86 ---- + Thu Sep 21 14:19:41 1995 Sudish Joseph + + * gnus.el (gnus-article-display-x-face): Use start-process instead + of call-process-region so that we may delete the old x-face + process when visiting a new article. + + Fri Sep 22 22:35:37 1995 Lars Magne Ingebrigtsen + + * gnus.el (gnus-read-header): Didn't work when reffing. + + Fri Sep 22 21:28:32 1995 Lars Magne Ingebrigtsen + + * nntp.el (nntp-find-group-and-number): int-to-string instead of + string-to-int. + + * gnus.el (gnus-set-global-variables): Didn't set + gnus-newsgroup-data. + + * gnus-msg.el (gnus-mail-send): Didn't remove + mail-header-separator. + + * gnus.el (gnus-activate-group): Scanned groups too late. + + Fri Sep 22 01:05:59 1995 Lars Ingebrigtsen + + * gnus.el (gnus-summary-prepare-threads): Use `gnus-subject-equal' + to compare the not-thread-ignore-subject thing. + (gnus-visual-p): New function. + (gnus-visual): Can now be a list of visual elements. + (gnus-request-article-this-buffer): Request all article to + `gnus-original-article-buffer', and then copy it to wherever it's + supposed to go. + (gnus-original-article-buffer): New variable. + (gnus-summary-insert-article): New function. + (gnus-summary-goto-subject): Allow jumping to articles not + currently in the buffer. + + * gnus-msg.el: Reworked all the sendmail/mh-e/vm/rnewspost buffer + entry points. + + Thu Sep 21 13:47:01 1995 Lars Ingebrigtsen + + * gnus.el (gnus-group-mode-map): New score submap. + (gnus-group-list-active): New command and keystroke. + (gnus-group-get-new-news): Allow a forced re-read of the active + file(s). + + * gnus-score.el (gnus-score-flush-cache): New command and + keystroke. + + * gnus.el (gnus-group-set-current-level): Display current level. + (gnus-group-quick-select-group): New command and keystroke. + + * gnus-uu.el (gnus-uu-digest-mail-forward): If the subject or from + are the same in a series, use that from or subject in the + headers. + + * nnmail.el (nnmail-delete-file-function): New variable. + * nnml.el (nnml-request-expire-articles): Use it. + + * gnus.el (gnus-summary-read-group): Allow entering a group for + side-effects; without generating the summary buffer lines. + (gnus-summary-show-article): Allow the prefix to fetch the "raw" + article. + (gnus-group-faq-directory): Allow lists as values. + (gnus-group-fetch-faq): If given a prefix arg, prompt for faq dir + from list above. + + * nntp.el (nntp-request-close): Send QUIT to the server before + hanging up. + + Thu Sep 21 02:10:14 1995 Lars Magne Ingebrigtsen + + * nnml.el (nnml-request-expire-articles): Bugged out. + (nnmh-request-expire-articles): Ditto. + Wed Sep 20 22:20:09 1995 Lars Magne Ingebrigtsen + * gnus.el: v0.01 is released. + * gnus.el (gnus-create-xref-hashtb): Our newsreader has Xrefs with "group/number" instead of "group:number". ! * gnus-msg.el (gnus-cancel-news): Make sure the From line is the read address. *** pub/sgnus/texi/gnus.texi Thu Sep 21 01:17:02 1995 --- sgnus/texi/gnus.texi Fri Sep 22 22:42:49 1995 *************** *** 86,91 **** --- 86,92 ---- * The Summary Buffer:: Reading, saving and posting articles. * The Article Buffer:: Displaying and handling articles. * The Server Buffer:: Making and editing virtual servers. + * Scoring:: Assigning values to articles. * Various:: General purpose settings. * Customization:: Tailoring Gnus to your needs. * Troubleshooting:: What you might try if things do not work. *************** *** 410,418 **** (@pxref{Group Levels}). @item ! You can score articles according to any number of criteria (@pxref{Score ! Files}). You can even get Gnus to score articles for you ! (@pxref{Adaptive Scoring}). @item Gnus maintains a dribble buffer that is auto-saved the normal Emacs --- 411,419 ---- (@pxref{Group Levels}). @item ! You can score articles according to any number of criteria ! (@pxref{Scoring}). You can even get Gnus to score articles for you ! (@pxref{Adaptive Scoring}). @item Gnus maintains a dribble buffer that is auto-saved the normal Emacs *************** *** 1278,1283 **** --- 1279,1285 ---- @cindex group selection @table @kbd + @item SPACE @kindex SPACE (Group) @findex gnus-group-read-group *************** *** 1289,1294 **** --- 1291,1297 ---- will fetch @var{N} number of articles. If @var{N} is positive, fetch the @var{N} newest articles, if @var{N} is negative, fetch the @var{abs(N)} oldest articles. + @item RET @kindex RET (Group) @findex gnus-group-select-group *************** *** 1297,1307 **** --- 1300,1321 ---- @code{gnus-group-read-group} - the only difference is that this command does not display the first unread article automatically upon group entry. + + @item M-RET + @kindex M-RET (Group) + @findex gnus-group-quick-select-group + This does the same as the command above, but tries to do it with the + minimum amount off fuzz (@code{gnus-group-quick-select-group}). No + scoring/killing will be performed, there will be no highlights and no + expunging. This might be useful if you're in a real hurry and have to + enter some humongous groups. + @item c @kindex c (Group) @findex gnus-group-catchup-current Mark all unticked articles in this group as read (@code{gnus-group-catchup-current}). + @item C @kindex C (Group) @findex gnus-group-catchup-current-all *************** *** 1665,1670 **** --- 1679,1686 ---- @vindex nntp-server-opened-hook @cindex @sc{mode reader} @cindex authinfo + @cindex authentification + @cindex nntp authentification @findex nntp-send-authinfo @findex nntp-send-mode-reader @code{nntp-server-opened-hook} is run after a connection has been made. *************** *** 1910,1916 **** In addition to this regexp detailing component groups, an nnkiboze group must have a score file to say what articles that are to be included in ! the group (@pxref{Score Files}). @kindex M-x nnkiboze-generate-groups @findex nnkiboze-generate-groups --- 1926,1932 ---- In addition to this regexp detailing component groups, an nnkiboze group must have a score file to say what articles that are to be included in ! the group (@pxref{Scoring}). @kindex M-x nnkiboze-generate-groups @findex nnkiboze-generate-groups *************** *** 2698,2703 **** --- 2714,2720 ---- These commands all list various slices of the groups that are available. @table @kbd + @item l @itemx A s @kindex A s (Group) *************** *** 2707,2712 **** --- 2724,2730 ---- (@code{gnus-group-list-groups}). If the numeric prefix is used, this command will list only groups of level ARG and lower. By default, it only lists groups of level five or lower (i.e., just subscribed groups). + @item L @itemx A u @kindex A u (Group) *************** *** 2717,2739 **** --- 2735,2771 ---- this command will list only groups of level ARG and lower. By default, it lists groups of level seven or lower (i.e., just subscribed and unsubscribed groups). + @item A k @kindex A k (Group) @findex gnus-group-list-killed List all killed groups (@code{gnus-group-list-killed}). + @item A z @kindex A z (Group) @findex gnus-group-list-zombies List all zombie groups (@code{gnus-group-list-zombies}). + @item A m @kindex A m (Group) @findex gnus-group-list-matching List all subscribed groups with unread articles that match a regexp (@code{gnus-group-list-matching}). + @item A M @kindex A M (Group) @findex gnus-group-list-all-matching List groups that match a regexp (@code{gnus-group-list-all-matching}). + + @item A A + @kindex A A (Group) + @findex gnus-group-list-active + List absolutely all groups that are in the active file(s) of the + server(s) you are connected to (@code{gnus-group-list-active}). This + might very well take quite a while. It might actually be a better idea + to do a @kbd{A m} to list all matching, and just give @samp{.} as the + thing to match on. + @end table @node Group Maintenance *************** *** 2892,2903 **** @section Misc Group Stuff @table @kbd @item g @kindex g (Group) @findex gnus-group-get-new-news ! Check server for new articles. If the numeric prefix is used, this ! command will check only groups of level ARG and lower ! (@code{gnus-group-get-new-news}). @item M-g @kindex M-g (Group) @findex gnus-group-get-new-news-this-group --- 2924,2939 ---- @section Misc Group Stuff @table @kbd + @item g @kindex g (Group) @findex gnus-group-get-new-news ! Check server for new articles. If the numerical prefix is used, this ! command will check only groups of level @var{arg} and lower ! (@code{gnus-group-get-new-news}). If given a non-numerical prefix, this ! command will force a total rereading of the active file(s) from the ! backend(s). ! @item M-g @kindex M-g (Group) @findex gnus-group-get-new-news-this-group *************** *** 2916,2922 **** Try to fetch the FAQ for the current group (@code{gnus-group-fetch-faq}). Gnus will try to get the FAQ from @code{gnus-group-faq-directory}, which is usually a directory on a ! remote machine. ange-ftp will be used for fetching the file. @item R @kindex R (Group) @findex gnus-group-restart --- 2952,2958 ---- Try to fetch the FAQ for the current group (@code{gnus-group-fetch-faq}). Gnus will try to get the FAQ from @code{gnus-group-faq-directory}, which is usually a directory on a ! remote machine. @code{ange-ftp} will be used for fetching the file. @item R @kindex R (Group) @findex gnus-group-restart *************** *** 3011,3024 **** * Saving Articles:: Ways of customizing article saving. * Decoding Articles:: Gnus can treat series of (uu)encoded articles. * Article Treatment:: The article buffer can be mangled at will. - * Various Article Stuff:: Various stuff dealing with articles. * Summary Sorting:: You can sort the summary buffer four ways. * Finding the Parent:: No child support? Get the parent. - * Score Files:: Maintaining a score file. * Mail Group Commands:: Some commands can only be used in mail groups. * Various Summary Stuff:: What didn't fit anywhere else. @end menu @node Summary Buffer Format @section Summary Buffer Format @cindex summary buffer format --- 3047,3059 ---- * Saving Articles:: Ways of customizing article saving. * Decoding Articles:: Gnus can treat series of (uu)encoded articles. * Article Treatment:: The article buffer can be mangled at will. * Summary Sorting:: You can sort the summary buffer four ways. * Finding the Parent:: No child support? Get the parent. * Mail Group Commands:: Some commands can only be used in mail groups. * Various Summary Stuff:: What didn't fit anywhere else. @end menu + @node Summary Buffer Format @section Summary Buffer Format @cindex summary buffer format *************** *** 3432,3437 **** --- 3467,3473 ---- * Post:: Posting and following up. * Mail & Post:: Mailing and posting at the same time. * Drafts:: Postponing messages and rejected messages. + * Rejected Articles:: What happens if the server doesn't like your article? @end menu @node Mail *************** *** 3956,3969 **** @item gnus-user-from-line @vindex gnus-user-from-line ! Your full, complete e-mail address. This variable overrides the other ! Gnus variables if it is non-@code{nil}. Here are two example values of this variable: @samp{"larsi@@ifi.uio.no (Lars Magne Ingebrigtsen)"} and @samp{"Lars Magne Ingebrigtsen ! "}. The latter version is recommended, but the name ! has to be quoted if it contains non-alpha-numerical characters - ! @samp{"\"Lars M. Ingebrigtsen\" "}. @item mail-default-headers @vindex mail-default-headers --- 3992,4006 ---- @item gnus-user-from-line @vindex gnus-user-from-line ! Your full, complete e-mail address with name. This variable overrides ! the other Gnus variables if it is non-@code{nil}. Here are two example values of this variable: @samp{"larsi@@ifi.uio.no (Lars Magne Ingebrigtsen)"} and @samp{"Lars Magne Ingebrigtsen ! "}. The latter version is recommended in news (and is ! probably illegal in mail), but the name has to be quoted if it contains ! non-alpha-numerical characters - @samp{"\"Lars M. Ingebrigtsen\" ! "}. @item mail-default-headers @vindex mail-default-headers *************** *** 4442,4448 **** @node Limiting ! @subsection Limiting It can be convenient to limit the summary buffer to just show some subset of the articles currently in the group. The effect most limit --- 4479,4486 ---- @node Limiting ! @section Limiting ! @cindex limiting It can be convenient to limit the summary buffer to just show some subset of the articles currently in the group. The effect most limit *************** *** 4516,4522 **** Hide all dormant articles that have no children (@code{gnus-summary-limit-exclude-childless-dormant}). ! @node Threading --- 4554,4560 ---- Hide all dormant articles that have no children (@code{gnus-summary-limit-exclude-childless-dormant}). ! @end table @node Threading *************** *** 5432,5443 **** @menu * Article Highlighting:: You want to make the article look like fruit salad. * Article Hiding:: You also want to make certain info go away. ! * Article Mangling:: Lots of way-neat functions to make life better. * Article Date:: Grumble, UT! @end menu ! @node Article Highlighing @subsection Article Highlighting @cindex highlight --- 5470,5481 ---- @menu * Article Highlighting:: You want to make the article look like fruit salad. * Article Hiding:: You also want to make certain info go away. ! * Article Washing:: Lots of way-neat functions to make life better. * Article Date:: Grumble, UT! @end menu ! @node Article Highlighting @subsection Article Highlighting @cindex highlight *************** *** 5525,5530 **** --- 5563,5570 ---- @node Article Hiding + @subsection Article Hiding + @cindex article hiding Or rather, hiding certain things in each article. There usually is much to much gruft in most articles. *************** *** 5572,5582 **** @end table - @end table - @node Article Washing ! @section Article Washin We call this "article washing" for a really good reason. Namely, the @kbd{A} key was taken, so we had to use the @kbd{W} key instead. --- 5612,5622 ---- @end table @node Article Washing ! @subsection Article Washing ! @cindex washing ! @cindex article washing We call this "article washing" for a really good reason. Namely, the @kbd{A} key was taken, so we had to use the @kbd{W} key instead. *************** *** 5602,5611 **** @item A g @kindex A g (Summary) @findex gnus-summary-show-article ! (Re)fetch the current article (@code{gnus-summary-show-article}). If ! given a prefix, don't actually refetch any articles, just jump to the ! current article and configure the windows to display the current ! article. @item W t @kindex W t (Summary) --- 5642,5651 ---- @item A g @kindex A g (Summary) @findex gnus-summary-show-article ! (Re)fetch the current article (@code{gnus-summary-show-article}). If ! given a prefix, fetch the current article, but don't run any of the ! article treatment functions. This will give you a "raw" article, just ! the way it came from the server. @item W t @kindex W t (Summary) *************** *** 5657,5663 **** @end table @node Article Date ! @section Article Date The date is most likely generated in some obscure timezone you've never heard of, so it's quite nice to be able to find out what the time was --- 5697,5703 ---- @end table @node Article Date ! @subsection Article Date The date is most likely generated in some obscure timezone you've never heard of, so it's quite nice to be able to find out what the time was *************** *** 5683,5689 **** (@code{gnus-article-date-lapsed}). @item W T o ! @item W T o (Summary) @findex gnus-article-date-original Display the original date (@code{gnus-article-date-original}). This can be useful if you normally use some other conversion function and is --- 5723,5729 ---- (@code{gnus-article-date-lapsed}). @item W T o ! @kindex W T o (Summary) @findex gnus-article-date-original Display the original date (@code{gnus-article-date-original}). This can be useful if you normally use some other conversion function and is *************** *** 5752,5758 **** @kindex A R (Summary) You can have Gnus fetch all articles mentioned in the @code{References} header of the article by pushing @kbd{A R} ! (code{gnus-summary-refer-references}). @findex gnus-summary-refer-article @kindex M-^ (Summary) --- 5792,5798 ---- @kindex A R (Summary) You can have Gnus fetch all articles mentioned in the @code{References} header of the article by pushing @kbd{A R} ! (@code{gnus-summary-refer-references}). @findex gnus-summary-refer-article @kindex M-^ (Summary) *************** *** 5778,7059 **** have been posted to the current group. (Anything else would be too time consuming.) @code{nnmh} does not support this at all. - @node Score Files - @section Score Files - @cindex score files ! Other people use @dfn{kill files}, but we here at Gnus Towers like ! scoring better than killing, so we'd rather switch than fight. They do ! something completely different as well, so sit up straight and pay ! attention! ! @vindex gnus-summary-mark-below ! All articles have a default score (@code{gnus-summary-default-score}). ! This score may be raised or lowered either interactively or by score ! files. Articles that have a score lower than ! @code{gnus-summary-mark-below} are marked as read. ! Gnus will read any @dfn{score files} that apply to the current group ! before generating the summary buffer. ! There are several commands in the summary buffer that insert score ! entries based on the current article. You can, for instance, ask Gnus to ! lower or increase the score of all articles with a certain subject. ! There are two sorts of scoring entries: Permanent and temporary. ! Temporary score entries are self-expiring entries. Any entries that are ! temporary and have not been used for, say, a week, will be removed ! silently to help keep the sizes of the score files down. ! @menu ! * Summary Score Commands:: Adding score commands to the score file. ! * Score Variables:: Customize your scoring. (My, what terminology). ! * Score File Format:: What a score file may contain. ! * Score File Editing:: You can edit score files by hand as well. ! * Adaptive Scoring:: Big Sister Gnus *knows* what you read. ! * Scoring Tips:: How to score effectively. ! * Reverse Scoring:: That problem child of old is not problem. ! * Global Score Files:: Earth-spanning, ear-splitting score files. ! * Kill Files:: They are still here, but they can be ignored. ! @end menu ! @node Summary Score Commands ! @subsection Summary Score Commands ! @cindex score commands ! The score commands that alter score entries do not actually modify real ! score files. That would be too inefficient. Gnus maintains a cache of ! previously loaded score files, one of which is considered the ! @dfn{current score file alist}. The score commands simply insert ! entries into this list, and upon group exit, this list is saved. ! The current score file is by default the group's local score file, even ! if no such score file actually exists. To insert score commands into ! some other score file (eg. @file{all.SCORE}), you must first make this ! score file the current one. ! General score commands that don't actually change the score file: ! @table @kbd ! @item V s ! @kindex V s (Summary) ! @findex gnus-summary-set-score ! Set the score of the current article (@code{gnus-summary-set-score}). ! @item V S ! @kindex V S (Summary) ! @findex gnus-summary-current-score ! Display the score of the current article ! (@code{gnus-summary-current-score}). ! @item V t ! @kindex V t (Summary) ! @findex gnus-score-find-trace ! Display all score rules that have been used on the current article ! (@code{gnus-score-find-trace}). ! @item V a ! @kindex V a (Summary) ! @findex gnus-summary-score-entry ! Add a new score entry, and allow specifying all elements ! (@code{gnus-summary-score-entry}). ! @item V c ! @kindex V c (Summary) ! @findex gnus-score-change-score-file ! Make a different score file the current ! (@code{gnus-score-change-score-file}). ! @item V e ! @kindex V e (Summary) ! @findex gnus-score-edit-alist ! Edit the current score file (@code{gnus-score-edit-alist}). You will be ! popped into a @code{gnus-score-mode} buffer (@pxref{Score File ! Editing}). ! @item V f ! @kindex V f (Summary) ! @findex gnus-score-edit-file ! Edit a score file and make this score file the current one ! (@code{gnus-score-edit-file}). ! @item I C-i ! @kindex I C-i (Summary) ! @findex gnus-summary-raise-score ! Increase the score of the current article ! (@code{gnus-summary-raise-score}). ! @item L C-l ! @kindex L C-l (Summary) ! @findex gnus-summary-lower-score ! Lower the score of the current article ! (@code{gnus-summary-lower-score}). ! @end table ! The rest of these commands modify the local score file. ! @table @kbd ! @item V m ! @kindex V m (Summary) ! @findex gnus-score-set-mark-below ! Prompt for a score, and mark all articles with a score below this as ! read (@code{gnus-score-set-mark-below}). ! @item V E ! @kindex V E (Summary) ! @findex gnus-score-set-expunge-below ! Expunge all articles with a score below the default score (or the ! numeric prefix) (@code{gnus-score-set-expunge-below}). @end table ! The keystrokes for actually making score entries follow a very regular ! pattern, so there's no need to list all the commands. (Hundreds of ! them.) ! ! @enumerate ! @item ! The first key is either @kbd{I} (upper case i) for increasing the score ! or @kbd{L} for lowering the score. ! @item ! The second key says what header you want to score on. The following ! keys are available: ! @table @kbd ! @item a ! Score on the author name. ! @item s ! Score on the subject line. ! @item x ! Score on the Xref line - i.e., the cross-posting line. ! @item t ! Score on thread - the References line. ! @item d ! Score on the date. ! @item l ! Score on the number of lines. ! @item i ! Score on the Message-ID. ! @item f ! Score on followups. ! @item b ! Score on the body. ! @item h ! Score on the head. ! @end table ! @item ! The third key is the match type. Which match types are legal depends on ! what headers you are scoring on. ! @table @code ! @item strings ! @table @kbd ! @item e ! Exact matching. ! @item s ! Substring matching. ! @item f ! Fuzzy matching. ! @item r ! Regexp matching ! @end table - @item date @table @kbd ! @item b ! Before date. ! @item a ! At date. ! @item n ! This date. ! @end table ! ! @item number ! @table @kbd ! @item < ! Less than number. ! @item = ! Equal to number. ! @item > ! Greater than number. ! @end table @end table ! @item ! The fourth and final key says whether this is a temporary (i.e., expiring) ! score entry, or a permanent (i.e., non-expiring) score entry, or whether ! it is to be done immediately, without adding to the score file. @table @kbd ! @item t ! Temporary score entry. ! @item p ! Permanent score entry. ! @item i ! Immediately scoring. @end table ! @end enumerate ! So, let's say you want to increase the score on the current author with ! exact matching permanently: @kbd{I a e p}. If you want to lower the ! score based on the subject line, using substring matching, and make a ! temporary score entry: @kbd{L s s t}. Pretty easy. ! To make things a bit more complicated, there are shortcuts. If you use ! a capital letter on either the second or third keys, Gnus will use ! defaults for the remaining one or two keystrokes. The defaults are ! "substring" and "temporary". So @kbd{I A} is the same as @kbd{I a s t}, ! and @kbd{I a R} is the same as @kbd{I a r t}. ! @vindex gnus-score-mimic-keymap ! The @code{gnus-score-mimic-keymap} says whether these commands will ! pretend they are keymaps or not. ! @node Score Variables ! @subsection Score Variables ! @cindex score variables ! @table @code ! @item gnus-use-scoring ! @vindex gnus-use-scoring ! If @code{nil}, Gnus will not check for score files, and will not, in ! general, do any score-related work. ! @item gnus-kill-killed ! @vindex gnus-kill-killed ! If this variable is @code{nil}, Gnus will never apply score files to ! articles that have already been through the kill process. While this ! may save you lots of time, it also means that if you apply a kill file ! to a group, and then change the kill file and want to run it over you ! group again to kill more articles, it won't work. You have to set this ! variable to @code{t} to do that. ! @item gnus-kill-files-directory ! @vindex gnus-kill-files-directory ! All kill and score files will be stored in this directory, which is ! initialized from the @samp{SAVEDIR} environment variable by default. ! @item gnus-score-file-suffix ! @vindex gnus-score-file-suffix ! Suffix to add to the group name to arrive at the score file name ! (@samp{SCORE} by default.) ! @item gnus-score-interactive-default-score ! @vindex gnus-score-interactive-default-score ! Score used by all the interactive raise/lower commands to raise/lower ! score with. Default is 1000, which may seem excessive, but this is to ! ensure that the adaptive scoring scheme gets enough room to play with. ! We don't want the small changes from the adaptive scoring to overwrite ! manually entered data. ! @item gnus-summary-default-score ! @vindex gnus-summary-default-score ! Default score of an article, which is 0 by default. ! @item gnus-score-over-mark ! @vindex gnus-score-over-mark ! Mark (in the third column) used for articles with a score over the ! default. Default is @samp{+}. ! @item gnus-score-below-mark ! @vindex gnus-score-below-mark ! Mark (in the third column) used for articles with a score below the ! default. Default is @samp{-}. ! @item gnus-score-find-score-files-function ! @vindex gnus-score-find-score-files-function ! Function used to find score files for the current group. This function ! is called with the name of the group as the argument. ! Predefined functions available are: ! @table @code ! @item gnus-score-find-single ! @findex gnus-score-find-single ! Only apply the group's own score file. ! @item gnus-score-find-bnews ! @findex gnus-score-find-bnews ! Apply all score files that match, using bnews syntax. For instance, if ! the current group is @samp{gnu.emacs.gnus}, @samp{all.emacs.all.SCORE}, ! @samp{not.alt.all.SCORE} and @samp{gnu.all.SCORE} would all apply. In ! short, the instances of @samp{all} in the score file names are ! translated into @samp{.*}, and then a regexp match is done. ! If @code{gnus-use-long-file-name} is non-@code{nil}, this won't work ! very will. It will find stuff like @file{gnu/all/SCORE}, but will not ! find files like @file{not/gnu/all/SCORE}. ! @item gnus-score-find-hierarchical ! @findex gnus-score-find-hierarchical ! Apply all score files from all the parent groups. ! @end table ! This variable can also be a list of functions. In that case, all these ! functions will be called, and all the returned lists of score files will ! be applied. These functions can also return lists of score alists ! directly. In that case, the functions that return these non-file score ! alists should probably be placed before the "real" score file functions, ! to ensure that the last score file returned is the local score file. ! Phu. ! @item gnus-score-expiry-days ! @vindex gnus-score-expiry-days ! This variable says how many days should pass before an unused score file ! entry is expired. The default is 7. ! @end table ! @node Score File Format ! @subsection Score File Format ! @cindex score file format ! A score file is an @code{emacs-lisp} file that normally contains just a ! single form. Casual users are not expected to edit these files; ! everything can be changed from the summary buffer. ! Anyway, if you'd like to dig into it yourself, here's an example: @lisp ! (("from" ! ("Lars Ingebrigtsen" -10000) ! ("Per Abrahamsen") ! ("larsi\\|lmi" -50000 nil R)) ! ("subject" ! ("Ding is Badd" nil 728373)) ! ("xref" ! ("alt.politics" -1000 728372 s)) ! ("lines" ! (2 -100 nil <)) ! (mark 0) ! (expunge -1000) ! (mark-and-expunge -10) ! (read-only nil) ! (orphan -10) ! (adapt t) ! (files "/hom/larsi/News/gnu.SCORE") ! (local (gnus-newsgroup-auto-expire t) ! (gnus-summary-make-false-root 'empty)) ! (eval (ding))) @end lisp ! This example demonstrates absolutely everything about a score file. ! ! Even though this looks much like lisp code, nothing here is actually ! @code{eval}ed. The lisp reader is used to read this form, though, so it ! has to be legal syntactically, if not semantically. ! Six keys are supported by this alist: ! @table @code ! @item STRING ! If the key is a string, it is the name of the header to perform the ! match on. Scoring can only be performed on these eight headers: ! @samp{From}, @samp{Subject}, @samp{References}, @samp{Message-ID}, ! @samp{Xref}, @samp{Lines}, @samp{Chars} and @samp{Date}. In addition to ! these headers, there are three strings to tell Gnus to fetch the entire ! article and do the match on larger parts of the article: @samp{Body} ! will perform the match on the body of the article, @samp{Head} will ! perform the match on the head of the article, and @samp{All} will ! perform the match on the entire article. Note that using any of these ! last three keys will slow down group entry @emph{considerably}. ! Following this key is a random number of score entries, where each score ! entry has one to four elements. ! @enumerate ! @item ! The first element is the @dfn{match element}. On most headers this will ! be a string, but on the Lines and Chars headers, this must be an ! integer. ! @item ! If the second element is present, it should be a number - the @dfn{score ! element}. This number should be an integer in the neginf to posinf ! interval. This number is added to the score of the article if the match ! is successful. If this element is not present, the ! @code{gnus-score-interactive-default-score} number will be used instead. ! @item ! If the third element is present, it should be a number - the @dfn{date ! element}. This date says when the last time this score entry matched, ! which provides a mechanism for expiring the score entries. It this ! element is not present, the score entry is permanent. The date is ! represented by the number of days since December 31, 1 ce. ! @item ! If the fourth element is present, it should be a symbol - the @dfn{type ! element}. This element specifies what function should be used to see ! whether this score entry matches the article. What match types that can ! be used depends on what header you wish to perform the match on. ! @table @dfn ! @item From, Subject, References, Xref, Message-ID ! For most header types, there are the @code{r} and @code{R} (regexp) as ! well as @code{s} and @code{S} (substring) types and @code{e} and ! @code{E} (exact match) types. If this element is not present, Gnus will ! assume that substring matching should be used. @code{R} and @code{S} ! differ from the other two in that the matches will be done in a ! case-sensitive manner. All these one-letter types are really just ! abbreviations for the @code{regexp}, @code{string} and @code{exact} ! types, which you can use instead, if you feel like. ! @item Lines, Chars ! These two headers use different match types: @code{<}, @code{>}, ! @code{=}, @code{>=} and @code{<=}. ! @item Date ! For the Date header we have three match types: @code{before}, @code{at} ! and @code{after}. I can't really imagine this ever being useful, but, ! like, it would feel kinda silly not to provide this function. Just in ! case. You never know. Better safe than sorry. Once burnt, twice shy. ! Don't judge a book by its cover. Never not have sex on a first date. ! @item Head, Body, All ! These three match keys use the same match types as the @code{From} (etc) ! header uses. ! @item Followup ! This match key will add a score entry on all articles that followup to ! some author. Uses the same match types as the @code{From} header uses. ! @end table ! @end enumerate ! @item mark ! The value of this entry should be a number. Any articles with a score ! lower than this number will be marked as read. ! @item expunge ! The value of this entry should be a number. Any articles with a score ! lower than this number will be removed from the summary buffer. ! @item mark-and-expunge ! The value of this entry should be a number. Any articles with a score ! lower than this number will be marked as read and removed from the ! summary buffer. ! @item files ! The value of this entry should be any number of file names. These files ! are assumed to be score files as well, and will be loaded the same way ! this one was. ! @item exclude-files ! The clue of this entry should be any number of files. This files will ! not be loaded, even though they would normally be so, for some reason or ! other. ! @item eval ! The value of this entry will be @code{eval}el. This element will be ! ignored when handling global score files. ! @item read-only ! Read-only score files will not be updated or saved. Global score files ! should feature this atom (@pxref{Global Score Files}). ! @item orphan ! The value of this entry should be a number. Articles that do not have ! parents will get this number added to their scores. ! @item adapt ! This entry controls the adaptive scoring. If it is @code{t}, the ! default adaptive scoring rules will be used. If it is @code{ignore}, no ! adaptive scoring will be performed on this group. If it is a list, this ! list will be used as the adaptive scoring rules. If it isn't present, ! or is something other than @code{t} or @code{ignore}, the default ! adaptive scoring rules will be used. If you want to use adaptive ! scoring on most groups, you'd set @code{gnus-use-adaptive-scoring} to ! @code{t}, and insert an @code{(adapt ignore)} in the groups where you do ! not want adaptive scoring. If you only want adaptive scoring in a few ! groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and ! insert @code{(adapt t)} in the score files of the groups where you want ! it. ! @item local ! @cindex local variables ! The value of this entry should be a list of @code{(VAR VALUE)} pairs. ! Each @var{var} will be made buffer-local to the current summary buffer, ! and set to the value specified. This is a convenient, if somewhat ! strange, way of setting variables in some groups if you don't like hooks ! much. ! @end table ! @node Score File Editing ! @subsection Score File Editing ! You normally enter all scoring commands from the summary buffer, but you ! might feel the urge to edit them by hand as well, so we've supplied you ! with a mode for that. ! It's simply a slightly customized @code{emacs-lisp} mode, with these ! additional commands: ! @table @kbd ! @item C-c C-c ! @kindex C-c C-c (Score) ! @findex gnus-score-edit-done ! Save the changes you have made and return to the summary buffer ! (@code{gnus-score-edit-done}). ! @item C-c C-d ! @kindex C-c C-d (Score) ! @findex gnus-score-edit-insert-date ! Insert the current date in numerical format ! (@code{gnus-score-edit-insert-date}). This is really the day number, if ! you were wondering. ! @end table ! @node Adaptive Scoring ! @subsection Adaptive Scoring ! @cindex adaptive scoring ! If all this scoring is getting you down, Gnus has a way of making it all ! happen automatically - as if by magic. Or rather, as if by artificial ! stupidity, to be precise. ! @vindex gnus-use-adaptive-scoring ! When you read an article, or mark an article as read, or kill an ! article, you leave marks behind. On exit from the group, Gnus can sniff ! these marks and add score elements depending on what marks it finds. ! You turn on this ability by setting @code{gnus-use-adaptive-scoring} to ! @code{t}. ! @vindex gnus-default-adaptive-score-alist ! To give you complete control over the scoring process, you can customize ! the @code{gnus-default-adaptive-score-alist} variable. By default, it ! looks something like this: ! @lisp ! (defvar gnus-default-adaptive-score-alist ! '((gnus-unread-mark) ! (gnus-ticked-mark (from 4)) ! (gnus-dormant-mark (from 5)) ! (gnus-del-mark (from -4) (subject -1)) ! (gnus-read-mark (from 4) (subject 2)) ! (gnus-expirable-mark (from -1) (subject -1)) ! (gnus-killed-mark (from -1) (subject -3)) ! (gnus-kill-file-mark) ! (gnus-catchup-mark (from -1) (subject -1)))) ! @end lisp ! As you see, each element in this alist has a mark as a key (either a ! variable name or a "real" mark - a character). Following this key is a ! random number of header/score pairs. ! To take @code{gnus-del-mark} as an example - this alist says that all ! articles that have that mark (i.e., are marked with @samp{D}) will have a ! score entry added to lower based on the @code{From} header by -4, and ! lowered by @code{Subject} by -1. Change this to fit your prejudices. ! If you use this scheme, you should set @code{mark-below} to something ! small - like -300, perhaps, to avoid having small random changes result ! in articles getting marked as read. ! After using adaptive scoring for a week or so, Gnus should start to ! become properly trained and enhance the authors you like best, and kill ! the authors you like least, without you having to say so explicitly. ! You can control what groups the adaptive scoring is to be performed on ! by using the score files (@pxref{Score File Format}). This will also ! let you use different rules in different groups. ! @vindex gnus-adaptive-file-suffix ! The adaptive score entries will be put into a file where the name is the ! group name with @code{gnus-adaptive-file-suffix} appended. ! @vindex gnus-score-exact-adapt-limit ! When doing adaptive scoring, substring or fuzzy matching would probably ! give you the best results in most cases. However, if the header one ! matches is short, the possibility for false positives is great, so if ! the length of the match is less than ! @code{gnus-score-exact-adapt-limit}, exact matching will be used. If ! this variable is @code{nil}, exact matching will always be used to avoid ! this problem. ! @node Scoring Tips ! @subsection Scoring Tips ! @cindex scoring tips - @table @dfn - @item Crossposts - If you want to lower the score of crossposts, the line to match on is - the @code{Xref} header. - @lisp - ("xref" (" talk.politics.misc:" -1000)) - @end lisp - @item Multiple crossposts - If you want to lower the score of articles that have been crossposted to - more than, say, 3 groups: @lisp ! ("xref" (" +[^ ]+:[0-9]+ +[^ ]+:[0-9]+ +[^ ]+:[0-9]+" -1000 nil r)) @end lisp ! @item Matching on the body ! This is generally not a very good idea - it takes a very long time. ! Gnus actually has to fetch each individual article from the server. But ! you might want to anyway, I guess. Even though there are three match ! keys (@code{Head}, @code{Body} and @code{All}), you should choose one ! and stick with it in each score file. If you use any two, each article ! will be fetched @emph{twice}. If you want to match a bit on the ! @code{Head} and a bit on the @code{Body}, just use @code{All} for all ! the matches. ! @item Marking as read ! You will probably want to mark articles that has a score below a certain ! number as read. This is most easily achieved by putting the following ! in your @file{all.SCORE} file: @lisp ! ((mark -100)) @end lisp - You may also consider doing something similar with @code{expunge}. ! @item Negated charater classes ! If you say stuff like @code{[^abcd]*}, you may get unexpected results. ! That will match newlines, which might lead to, well, The Unknown. Say ! @code{[^abcd\n]*} instead. ! @end table ! @node Reverse Scoring ! @subsection Reverse Scoring ! @cindex reverse scoring ! If you want to keep just articles that have @samp{Sex with Emacs} in the ! subject header, and expunge all other articles, you could put something ! like this in your score file: @lisp ! (("subject" ! ("Sex with Emacs" 2)) ! (mark 1) ! (expunge 1)) @end lisp ! So, you raise all articles that match @samp{Sex with Emacs} and mark the ! rest as read, and expunge them to boot. ! ! @node Global Score Files ! @subsection Global Score Files ! @cindex global score files ! Sure, other newsreaders have "global kill files". These are usually ! nothing more than a single kill file that applies to all groups, stored ! in the user's home directory. Bah! Puny, weak newsreaders! ! What I'm talking about here are Global Score Files. Score files from ! all over the world, from users everywhere, uniting all nations in one ! big, happy score file union! Ange-score! New and untested! ! @vindex gnus-global-score-files ! All you have to do to use other people's score files is to set the ! @code{gnus-global-score-files} variable. One entry for each score file, ! or each score file directory. Gnus will decide by itself what score ! files are applicable to which group. ! Say you want to use all score files in the ! @file{/ftp@@ftp.some-where:/pub/score} directory and the single score ! file @file{/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE}: @lisp ! (setq gnus-global-score-files ! '("/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE" ! "/ftp@@ftp.some-where:/pub/score/")) @end lisp ! @findex gnus-score-search-global-directories ! Simple, eh? Directory names must end with a @samp{/}. These ! directories are typically scanned only once during each Gnus session. ! If you feel the need to manually re-scan the remote directories, you can ! use the @code{gnus-score-search-global-directories} command. ! Note that, at present, using this option will slow down group entry ! somewhat. (That is - a lot.) - If you want to start maintaining score files for other people to use, - just put your score file up for anonymous ftp and announce it to the - world. Become a retro-moderator! Participate in the retro-moderator - wars sure to ensue, where retro-moderators battle it out for the - sympathy of the people, luring them to use their score files on false - premises! Yay! The net is saved! - - Here are some tips for the would-be retro-moderator, off the top of my - head: ! @itemize @bullet ! @item ! Articles that are heavily crossposted are probably junk. ! @item ! To lower a single inappropriate article, lower by @code{Message-Id}. ! @item ! Particularly brilliant authors can be raised on a permanent basis. ! @item ! Authors that repeatedly post off-charter for the group can safely be ! lowered out of existence. ! @item ! Set the @code{mark} and @code{expunge} atoms to obliterate the nastiest ! articles completely. ! @item ! Use expiring score entries to keep the size of the file down. You ! should probably have a long expiry period, though, as some sites keep ! old articles for a long time. ! @end itemize ! ... I wonder whether other newsreaders will support global score files ! in the future. @emph{Snicker}. Yup, any day now, newsreaders like Blue ! Wave, xrn and 1stReader are bound to implement scoring. Should we start ! holding our breath yet? ! @node Kill Files ! @subsection Kill Files ! @cindex kill files ! Gnus still supports those pesky old kill files. In fact, the kill file ! entries can now be expiring, which is something I wrote before Per ! thought of doing score files, so I've left the code in there. ! In short, kill processing is a lot slower (and I do mean @emph{a lot}) ! than score processing, so it might be a good idea to rewrite your kill ! files into score files. ! Anyway, a kill file is a normal @code{emacs-lisp} file. You can put any ! forms into this file, which means that you can use kill files as some ! sort of primitive hook function to be run on group entry, even though ! that isn't a very good idea. ! XCNormal kill files look like this: ! @lisp ! (gnus-kill "From" "Lars Ingebrigtsen") ! (gnus-kill "Subject" "ding") ! (gnus-expunge "X") ! @end lisp ! This will mark every article written by me as read, and remove them from ! the summary buffer. Very useful, you'll agree. ! Other programs use a totally different kill file syntax. If Gnus ! encounters what looks like a @code{rn} kill file, it will take a stab at ! interpreting it. ! Two functions for editing a GNUS kill file: @table @kbd ! @item M-k ! @kindex M-k (Summary) ! @findex gnus-summary-edit-local-kill ! Edit this group's kill file (@code{gnus-summary-edit-local-kill}). ! ! @item M-K ! @kindex M-K (Summary) ! @findex gnus-summary-edit-global-kill ! Edit the general kill file (@code{gnus-summary-edit-global-kill}). @end table ! @vindex gnus-kill-file-name ! A kill file for the group @samp{soc.motss} is normally called ! @file{soc.motss.KILL}. The suffix appended to the group name to get ! this file name is detailed by the @code{gnus-kill-file-name} variable. ! The "global" kill file (not in the score file sense of "global", of ! course) is called just @file{KILL}. ! @vindex gnus-kill-save-kill-file ! If @code{gnus-kill-save-kill-file} is non-@code{nil}, Gnus will save the ! kill file after processing, which is necessary if you use expiring ! kills. ! @node Mail Group Commands ! @section Mail Group Commands ! @cindex mail group commands ! Some commands only make sense in mail groups. If these commands are ! illegal in the current group, they will raise a hell and let you know. ! All these commands (except the expiry and edit commands) use the ! process/prefix convention (@pxref{Process/Prefix}). @table @kbd ! @item B e ! @kindex B e (Summary) ! @findex gnus-summary-expire-articles ! Expire all expirable articles in the group ! (@code{gnus-summary-expire-articles}). ! ! @item B M-C-e ! @kindex B M-C-e (Summary) ! @findex gnus-summary-expire-articles-now ! Expunge all the expirable articles in the group ! (@code{gnus-summary-expire-articles-now}). This means that @strong{all} ! articles that are eligeble for expiry in the current group will ! disappear forever into that big @file{/dev/null} in the sky. ! @item B DEL ! @kindex B DEL (Summary) ! @findex gnus-summary-delete-articles ! Delete the mail article. This is "delete" as in "delete it from your ! disk forever and ever, never to return again." Use with caution. ! (@code{gnus-summary-delete-article}). ! @item B m ! @kindex B m (Summary) ! @cindex move mail ! @findex gnus-summary-move-article ! Move the article from one mail group to another ! (@code{gnus-summary-move-article}). ! ! @item B c ! @kindex B c (Summary) ! @cindex copy mail ! @findex gnus-summary-copy-article ! Copy the article from one group (mail group or not) to a mail group ! (@code{gnus-summary-copy-article}). ! ! @item B i ! @kindex B i (Summary) ! @findex gnus-summary-import-article ! Import a random file into the current mail newsgroup ! (@code{gnus-summary-import-article}). You will be prompted for a file ! name, a @code{From} header and a @code{Subject} header. ! Something similar can be done by just starting to compose a mail ! message. Instead of typing @kbd{C-c C-c} to mail it off, you can type ! @kbd{C-c C-p} instead. This will put the message you have just created ! into the current mail group. ! @item B r ! @kindex B r (Summary) ! @findex gnus-summary-respool-article ! Respool the mail article (@code{gnus-summary-move-article}). ! @item B w ! @itemx e ! @kindex B w (Summary) ! @kindex e (Summary) ! @findex gnus-summary-edit-article ! @kindex C-c C-c (Article) ! Edit the current article (@code{gnus-summary-edit-article}). To finish ! editing and make the changes permanent, type @kbd{C-c C-c} ! (@kbd{gnus-summary-edit-article-done}). ! @item B q ! @kindex B q (Summary) ! @findex gnus-summary-fancy-query ! If you are using fancy splitting, this command will tell you where an ! article would go (@code{gnus-summary-fancy-query}). ! @end table ! @node Various Summary Stuff ! @section Various Summary Stuff - @menu - * Group Information:: Information oriented commands. - * Searching for Articles:: Multiple article commands. - * Really Various Summary Commands:: Those pesky non-conformant commands. - @end menu ! @vindex gnus-summary-prepare-hook ! @code{gnus-summary-prepare-hook} is called after the summary buffer has ! been generated. You might use it to, for instance, highlight lines or ! modify the look of the buffer in some other ungodly manner. I don't ! care. ! @node Group Information ! @subsection Group Information @table @kbd - @item H f - @kindex H f (Summary) - @findex gnus-summary-fetch-faq - @vindex gnus-group-faq-directory - Try to fetch the FAQ (list of frequently asked questions) for the - current group (@code{gnus-summary-fetch-faq}). Gnus will try to get the - FAQ from @code{gnus-group-faq-directory}, which is usually a directory - on a remote machine. @code{ange-ftp} will be used for fetching the file. - @item H d - @kindex H d (Summary) - @findex gnus-summary-describe-group - Give a brief description of the current group - (@code{gnus-summary-describe-group}). If given a prefix, force - rereading the description from the server. - @item H h - @kindex H h (Summary) - @findex gnus-summary-describe-briefly - Give a very brief description of the most important summary keystrokes - (@code{gnus-summary-describe-briefly}). - @item H i - @kindex H i (Summary) - @findex gnus-info-find-node - Go to the Gnus info node (@code{gnus-info-find-node}). - @end table ! @node Searching for Articles ! @subsection Searching for Articles - @table @kbd - @item M-s - @kindex M-s (Summary) - @findex gnus-summary-search-article-forward - Search through all subsequent articles for a regexp - (@code{gnus-summary-search-article-forward}). - @item M-r - @kindex M-r (Summary) - @findex gnus-summary-search-article-backward - Search through all previous articles for a regexp - (@code{gnus-summary-search-article-backward}). - @item & - @kindex & (Summary) - @findex gnus-summary-execute-command - This command will prompt you for a header field, a regular expression to - match on this field, and a command to be executed if the match is made - (@code{gnus-summary-execute-command}). - @item M-& - @kindex M-& (Summary) - @findex gnus-summary-universal-argument - Perform any operation on all articles that have been marked with - the process mark (@code{gnus-summary-universal-argument}). @end table - @node Really Various Summary Commands - @subsection Really Various Summary Commands ! @table @kbd ! @item A D ! @kindex A D (Summary) ! @findex gnus-summary-enter-digest-group ! If the current article is a digest, you might use this command to enter ! you into a group based on the current digest to ease reading ! (@code{gnus-summary-enter-digest-group}). ! @item C-t ! @kindex C-t (Summary) ! @findex gnus-summary-toggle-truncation ! Toggle truncation of summary lines (@code{gnus-summary-toggle-truncation}). ! @item = ! @kindex = (Summary) ! @findex gnus-summary-expand-window ! Expand the summary buffer window (@code{gnus-summary-expand-window}). ! If given a prefix, force an @code{article} window configuration. ! @end table ! @node The Article Buffer ! @chapter The Article Buffer ! @cindex article buffer ! The articles are displayed in the article buffer, of which there is only ! one. All the summary buffer share the same article buffer. ! @menu ! * Hiding Headers:: Deciding what headers should be displayed. ! * Using Mime:: Pushing articles through @sc{mime} before reading them. ! * Customizing Articles:: Tailoring the look of the articles. ! * Article Keymap:: Keystrokes available in the article buffer ! * Misc Article:: Other stuff. ! @end menu ! @node Hiding Headers ! @section Hiding Headers ! @cindex hiding headers ! @cindex deleting headers ! The top section of each article is the @dfn{head}. (The rest is the ! @dfn{body}, but you may have guessed that already.) ! @vindex gnus-show-all-headers ! There is a lot of useful information in the head: the name of the person ! who wrote the article, the date it was written and the subject of the ! article. That's well and nice, but there's also lots of information ! most people do not want to see - what systems the article has passed ! through before reaching you, the @code{Message-Id}, the ! @code{References}, etc. ad nauseum - and you'll probably want to get rid ! of some of those lines. If you want to keep all those lines in the ! article buffer, you can set @code{gnus-show-all-headers} to @code{t}. ! Gnus provides you with two variables for sifting headers: ! @table @code ! @item gnus-visible-headers ! @vindex gnus-visible-headers ! If this variable is non-@code{nil}, it should be a regular expression ! that says what headers you wish to keep in the article buffer. All ! headers that do not match this variable will be hidden. ! For instance, if you only want to see the name of the person who wrote ! the article and the subject, you'd say: @lisp ! (setq gnus-visible-headers "^From:\\|^Subject:") @end lisp ! @item gnus-ignored-headers ! @vindex gnus-ignored-headers ! This variable is the reverse of @code{gnus-visible-headers}. If this ! variable is set (and @code{gnus-visible-headers} is @code{nil}), it ! should be a regular expression that matches all lines that you want to ! hide. All lines that do not match this variable will remain visible. ! For instance, if you just want to get rid of the @code{References} line ! and the @code{Xref} line, you might say: ! @lisp ! (setq gnus-ignored-headers "^References:\\|^Xref:") ! @end lisp ! Note that if @code{gnus-visible-headers} is non-@code{nil}, this ! variable will have no effect. @end table ! @vindex gnus-sorted-header-list ! Gnus can also sort the headers for you. (It does this by default.) You ! can control the sorting by setting the @code{gnus-sorted-header-list} ! variable. It is a list of regular expressions that says in what order ! the headers are to be displayed. ! ! For instance, if you want the name of the author of the article first, ! and then the subject, you might say something like: ! ! @lisp ! (setq gnus-sorted-header-list '("^From:" "^Subject:")) ! @end lisp ! ! Any headers that are to remain visible, but are not listed in this ! variable, will be displayed in random order after all the headers that ! are listed in this variable. ! @node Using Mime ! @section Using Mime ! @cindex @sc{mime} ! Mime is a standard for waving your hands through the air, aimlessly, ! while people stand around yawning. ! @sc{mime}, however, is a standard for encoding your articles, aimlessly, ! while all newsreaders die of fear. ! @sc{mime} may specify what character set the article uses, the encoding ! of the characters, and it also makes it possible to embed pictures and ! other naughty stuff in innocent-looking articles. ! @vindex gnus-show-mime ! @vindex gnus-show-mime-method ! Gnus handles @sc{mime} by shoving the articles through ! @code{gnus-show-mime-method}, which is @code{metamail-buffer} by ! default. If @code{gnus-strict-mime} is non-@code{nil}, the @sc{mime} ! method will only be used it there are @sc{mime} headers in the article. ! Set @code{gnus-show-mime} to @code{t} if you want to use @sc{mime} all ! the time; it might be best to just use the toggling functions from the ! summary buffer to avoid getting nasty surprises. (For instance, you ! enter the group @samp{alt.sing-a-long} and, before you know it, ! @sc{mime} has decoded the sound file in the article and some horrible ! sing-a-long song comes streaming out out your speakers, and you can't ! find the volume button, because there isn't one, and people are starting ! to look at you, and you try to stop the program, but you can't, and you ! can't find the program to control the volume, and everybody else in the ! room suddenly decides to look at you disdainfully, and you'll feel ! rather stupid.) ! Any similarity to real events and people is purely coincidental. Ahem. ! @node Customizing Articles ! @section Customizing Articles ! @cindex article customization ! @vindex gnus-article-display-hook ! The @code{gnus-article-display-hook} is called after the article has ! been inserted into the article buffer. It is meant to handle all ! treatment of the article before it is displayed. By default it contains ! @code{gnus-article-hide-headers}, which hides unwanted headers. ! @findex gnus-article-subcite ! @findex gnus-article-hide-signature ! @findex gnus-article-hide-citation ! Other useful functions you might add to this hook is: ! @table @code ! @item gnus-article-hide-citation ! Hide all cited text. ! @item gnus-article-hide-signature ! Umn, hides the signature. ! @item gnus-article-treat-overstrike ! Treat @samp{^H_} in a reasonable manner. ! @item gnus-article-maybe-highlight ! Do fancy article highlighting. ! @item gnus-article-remove-cr ! Removes trailing carriage returns. ! @item gnus-article-de-quoted-unreadable ! Do naive decoding of articles encoded with Quoted-Printable. ! @item gnus-article-display-x-face ! Displays any X-Face headers. ! @end table ! You can, of course, write your own functions. The functions are called ! from the article buffer, and you can do anything you like, pretty much. ! There is no information that you have to keep in the buffer - you can ! change everything. However, you shouldn't delete any headers. Instead ! make them invisible if you want to make them go away. ! @node Article Keymap ! @section Article Keymap ! @c Most of the keystrokes in the summary buffer can also be used in the ! @c article buffer. They should behave as if you typed them in the summary ! @c buffer, which means that you don't actually have to have a summary ! @c buffer displayed while reading. You can do it all from the article ! @c buffer. ! A few additional keystrokes are available: ! @table @kbd ! @item SPACE ! @kindex SPACE (Article) ! @findex gnus-article-next-page ! Scroll forwards one page (@code{gnus-article-next-page}). ! @item DEL ! @kindex DEL (Article) ! @findex gnus-article-prev-page ! Scroll backwards one page (@code{gnus-article-prev-page}). ! @item C-c ^ ! @kindex C-c ^ (Article) ! @findex gnus-article-refer-article ! If point is in the neighborhood of a @code{Message-Id} and you press ! @kbd{r}, Gnus will try to get that article from the server ! (@code{gnus-article-refer-article}). ! @item C-c C-m ! @kindex C-c C-m (Article) ! @findex gnus-article-mail ! Send a reply to the address near point (@code{gnus-article-mail}). If ! given a prefix, include the mail. ! @item s ! @kindex s (Article) ! @findex gnus-article-show-summary ! Reconfigure the buffers so that the summary buffer becomes visible ! (@code{gnus-article-show-summary}). ! @item ? ! @kindex ? (Article) ! @findex gnus-article-describe-briefly ! Give a very brief description of the available keystrokes ! (@code{gnus-article-describe-briefly}). ! @end table ! @node Misc Article ! @section Misc Article ! @table @code ! @vindex gnus-article-prepare-hook ! @item gnus-article-prepare-hook ! This hook is called right after the article has been inserted into the ! article buffer. It is mainly intended for functions that do something ! depending on the contents; it should probably not be used for changing ! the contents of the article buffer. ! @vindex gnus-article-display-hook ! @item gnus-article-display-hook ! This hook is called as the last thing when displaying an article, and is ! intended for modifying the contents of the buffer, doing highlights, ! hiding headers, and the like. ! @vindex gnus-article-mode-line-format ! @item gnus-article-mode-line-format ! This variable is a format string along the same lines as ! @code{gnus-summary-mode-line-format}. It accepts exactly the same ! format specifications as that variable. ! @vindex gnus-break-pages ! @item gnus-break-pages ! Controls whether @dfn{page breaking} is to take place. If this variable ! is non-@code{nil}, the articles will be divided into pages whenever a ! page delimiter appears in the article. If this variable is @code{nil}, ! paging will not be done. ! @item gnus-page-delimiter ! @vindex gnus-page-delimiter ! This is the delimiter mentioned above. By default, it is @samp{^L} ! (form linefeed). @end table ! @node The Server Buffer ! @chapter The Server Buffer ! Traditionally, a @dfn{server} is a machine or a piece of software that ! one connects to, and then requests information from. Gnus does not ! connect directly to any real servers, but does all transactions through ! one backend or other. But that's just putting one layer more between ! the actual media and Gnus, so we might just as well say that each ! backend represents a virtual server. ! For instance, the @code{nntp} backend may be used to connect to several ! different actual nntp servers, or, perhaps, to many different ports on ! the same actual nntp server. You tell Gnus which backend to use, and ! what parameters to set by specifying a @dfn{select method}. ! These select methods specifications can sometimes become quite ! complicated - say, for instance, that you want to read from the nntp ! server @samp{news.funet.fi} on port number @samp{13}, which hangs if ! queried for @sc{nov} headers and has a buggy select. Ahem. Anyways, if ! you had to specify that for each group that used this server, that would ! be too much work, so Gnus offers a way of putting names to methods, ! which is what you do in the server buffer. ! @menu ! * Server Buffer Format:: You can customize the look of this buffer. ! * Server Commands:: Commands to manipulate servers. ! * Example Methods:: Examples server specifications. ! * Servers & Methods:: You can use server names as select methods. ! @end menu ! @node Server Buffer Format ! @section Server Buffer Format ! @cindex server buffer format ! @vindex gnus-server-line-format ! You can change the look of the server buffer lines by changing the ! @code{gnus-server-line-format} variable. This is a @code{format}-like ! variable, with some simple extensions: ! @table @samp ! @item h ! How the news is fetched - the backend name. ! @item n ! The name of this server. ! @item w ! Where the news is to be fetched from - the address. ! @end table ! @node Server Commands ! @section Server Commands ! @cindex server commands ! @table @kbd ! @item SPC ! Browse the current server (@code{gnus-server-read-server}). ! @item q ! Return to the group buffer (@code{gnus-server-exit}). ! @item l ! List all servers (@code{gnus-server-list-servers}). ! @item k ! Kill the current server (@code{gnus-server-kill-server}). ! @item y ! Yank the previously killed server (@code{gnus-server-yank-server}). ! @item c ! Copy the current server (@code{gnus-server-copy-server}). ! @item a ! Add a new server (@code{gnus-server-add-server}). ! @item e ! Edit a server (@code{gnus-server-edit-server}). ! @end table ! @node Example Methods ! @section Example Methods ! Most select methods are pretty simple and self-explanatory: ! @lisp ! (nntp "news.funet.fi") ! @end lisp ! Reading directly from the spool is even simpler: ! @lisp ! (nnspool "") ! @end lisp ! As you can see, the first element in a select method is the name of the ! backend, and the second is the @dfn{address}, or @dfn{name}, if you ! will. - After these two elements, there may be a random number of @var{(variable - form)} pairs. ! To go back to the first example - imagine that you want to read from ! port @code{15} from that machine. This is what the select method should ! look like then: ! @lisp ! (nntp "news.funet.fi" (nntp-port-number 15)) ! @end lisp ! You should read the documentation to each backend to find out what ! variables are relevant, but here's an @code{nnmh} example. ! @code{nnmh} is a mail backend that reads a spool-like structure. Say ! you have two structures that you wish to access: One is your private ! mail spool, and the other is a public one. Here's the possible spec for ! you private mail: @lisp ! (nnmh "private" (nnmh-directory "~/private/mail/")) @end lisp ! (This server is then called @samp{private}, but you may have guessed ! that. ! Here's the method for the public spool: ! @lisp ! (nnmh "public" ! (nnmh-directory "/usr/information/spool/") ! (nnmh-get-new-mail nil)) ! @end lisp - @node Servers & Methods - @section Servers & Methods - Wherever you would normally use a select method - (eg. @code{gnus-secondary-select-method}, in the group select method, - when browsing a foreign server) you can use a virtual server name - instead. This could potentially save lots of typing. And it's nice all - over. @node Various --- 5818,7126 ---- have been posted to the current group. (Anything else would be too time consuming.) @code{nnmh} does not support this at all. ! @node Mail Group Commands ! @section Mail Group Commands ! @cindex mail group commands ! Some commands only make sense in mail groups. If these commands are ! illegal in the current group, they will raise a hell and let you know. ! All these commands (except the expiry and edit commands) use the ! process/prefix convention (@pxref{Process/Prefix}). ! @table @kbd ! @item B e ! @kindex B e (Summary) ! @findex gnus-summary-expire-articles ! Expire all expirable articles in the group ! (@code{gnus-summary-expire-articles}). ! @item B M-C-e ! @kindex B M-C-e (Summary) ! @findex gnus-summary-expire-articles-now ! Expunge all the expirable articles in the group ! (@code{gnus-summary-expire-articles-now}). This means that @strong{all} ! articles that are eligeble for expiry in the current group will ! disappear forever into that big @file{/dev/null} in the sky. ! @item B DEL ! @kindex B DEL (Summary) ! @findex gnus-summary-delete-articles ! Delete the mail article. This is "delete" as in "delete it from your ! disk forever and ever, never to return again." Use with caution. ! (@code{gnus-summary-delete-article}). ! @item B m ! @kindex B m (Summary) ! @cindex move mail ! @findex gnus-summary-move-article ! Move the article from one mail group to another ! (@code{gnus-summary-move-article}). ! @item B c ! @kindex B c (Summary) ! @cindex copy mail ! @findex gnus-summary-copy-article ! Copy the article from one group (mail group or not) to a mail group ! (@code{gnus-summary-copy-article}). ! @item B i ! @kindex B i (Summary) ! @findex gnus-summary-import-article ! Import a random file into the current mail newsgroup ! (@code{gnus-summary-import-article}). You will be prompted for a file ! name, a @code{From} header and a @code{Subject} header. ! Something similar can be done by just starting to compose a mail ! message. Instead of typing @kbd{C-c C-c} to mail it off, you can type ! @kbd{C-c C-p} instead. This will put the message you have just created ! into the current mail group. ! @item B r ! @kindex B r (Summary) ! @findex gnus-summary-respool-article ! Respool the mail article (@code{gnus-summary-move-article}). ! @item B w ! @itemx e ! @kindex B w (Summary) ! @kindex e (Summary) ! @findex gnus-summary-edit-article ! @kindex C-c C-c (Article) ! Edit the current article (@code{gnus-summary-edit-article}). To finish ! editing and make the changes permanent, type @kbd{C-c C-c} ! (@kbd{gnus-summary-edit-article-done}). ! @item B q ! @kindex B q (Summary) ! @findex gnus-summary-fancy-query ! If you are using fancy splitting, this command will tell you where an ! article would go (@code{gnus-summary-fancy-query}). @end table ! @node Various Summary Stuff ! @section Various Summary Stuff ! @menu ! * Group Information:: Information oriented commands. ! * Searching for Articles:: Multiple article commands. ! * Really Various Summary Commands:: Those pesky non-conformant commands. ! @end menu ! @vindex gnus-summary-prepare-hook ! @code{gnus-summary-prepare-hook} is called after the summary buffer has ! been generated. You might use it to, for instance, highlight lines or ! modify the look of the buffer in some other ungodly manner. I don't ! care. ! @node Group Information ! @subsection Group Information @table @kbd ! @item H f ! @kindex H f (Summary) ! @findex gnus-summary-fetch-faq ! @vindex gnus-group-faq-directory ! Try to fetch the FAQ (list of frequently asked questions) for the ! current group (@code{gnus-summary-fetch-faq}). Gnus will try to get the ! FAQ from @code{gnus-group-faq-directory}, which is usually a directory ! on a remote machine. This variable can also be a list of directories. ! In that case, giving a prefix to this command will allow you to choose ! between the various sites. @code{ange-ftp} probably will be used for ! fetching the file. ! @item H d ! @kindex H d (Summary) ! @findex gnus-summary-describe-group ! Give a brief description of the current group ! (@code{gnus-summary-describe-group}). If given a prefix, force ! rereading the description from the server. ! @item H h ! @kindex H h (Summary) ! @findex gnus-summary-describe-briefly ! Give a very brief description of the most important summary keystrokes ! (@code{gnus-summary-describe-briefly}). ! @item H i ! @kindex H i (Summary) ! @findex gnus-info-find-node ! Go to the Gnus info node (@code{gnus-info-find-node}). @end table ! @node Searching for Articles ! @subsection Searching for Articles ! @table @kbd ! @item M-s ! @kindex M-s (Summary) ! @findex gnus-summary-search-article-forward ! Search through all subsequent articles for a regexp ! (@code{gnus-summary-search-article-forward}). ! @item M-r ! @kindex M-r (Summary) ! @findex gnus-summary-search-article-backward ! Search through all previous articles for a regexp ! (@code{gnus-summary-search-article-backward}). ! @item & ! @kindex & (Summary) ! @findex gnus-summary-execute-command ! This command will prompt you for a header field, a regular expression to ! match on this field, and a command to be executed if the match is made ! (@code{gnus-summary-execute-command}). ! @item M-& ! @kindex M-& (Summary) ! @findex gnus-summary-universal-argument ! Perform any operation on all articles that have been marked with ! the process mark (@code{gnus-summary-universal-argument}). @end table ! @node Really Various Summary Commands ! @subsection Really Various Summary Commands ! @table @kbd ! @item A D ! @kindex A D (Summary) ! @findex gnus-summary-enter-digest-group ! If the current article is a digest, you might use this command to enter ! you into a group based on the current digest to ease reading ! (@code{gnus-summary-enter-digest-group}). ! @item C-t ! @kindex C-t (Summary) ! @findex gnus-summary-toggle-truncation ! Toggle truncation of summary lines (@code{gnus-summary-toggle-truncation}). ! @item = ! @kindex = (Summary) ! @findex gnus-summary-expand-window ! Expand the summary buffer window (@code{gnus-summary-expand-window}). ! If given a prefix, force an @code{article} window configuration. ! @end table ! @node The Article Buffer ! @chapter The Article Buffer ! @cindex article buffer ! The articles are displayed in the article buffer, of which there is only ! one. All the summary buffer share the same article buffer. ! @menu ! * Hiding Headers:: Deciding what headers should be displayed. ! * Using Mime:: Pushing articles through @sc{mime} before reading them. ! * Customizing Articles:: Tailoring the look of the articles. ! * Article Keymap:: Keystrokes available in the article buffer ! * Misc Article:: Other stuff. ! @end menu ! @node Hiding Headers ! @section Hiding Headers ! @cindex hiding headers ! @cindex deleting headers ! The top section of each article is the @dfn{head}. (The rest is the ! @dfn{body}, but you may have guessed that already.) ! @vindex gnus-show-all-headers ! There is a lot of useful information in the head: the name of the person ! who wrote the article, the date it was written and the subject of the ! article. That's well and nice, but there's also lots of information ! most people do not want to see - what systems the article has passed ! through before reaching you, the @code{Message-Id}, the ! @code{References}, etc. ad nauseum - and you'll probably want to get rid ! of some of those lines. If you want to keep all those lines in the ! article buffer, you can set @code{gnus-show-all-headers} to @code{t}. ! Gnus provides you with two variables for sifting headers: ! @table @code ! @item gnus-visible-headers ! @vindex gnus-visible-headers ! If this variable is non-@code{nil}, it should be a regular expression ! that says what headers you wish to keep in the article buffer. All ! headers that do not match this variable will be hidden. ! For instance, if you only want to see the name of the person who wrote ! the article and the subject, you'd say: ! @lisp ! (setq gnus-visible-headers "^From:\\|^Subject:") ! @end lisp ! @item gnus-ignored-headers ! @vindex gnus-ignored-headers ! This variable is the reverse of @code{gnus-visible-headers}. If this ! variable is set (and @code{gnus-visible-headers} is @code{nil}), it ! should be a regular expression that matches all lines that you want to ! hide. All lines that do not match this variable will remain visible. ! For instance, if you just want to get rid of the @code{References} line ! and the @code{Xref} line, you might say: @lisp ! (setq gnus-ignored-headers "^References:\\|^Xref:") @end lisp ! Note that if @code{gnus-visible-headers} is non-@code{nil}, this ! variable will have no effect. ! @end table ! @vindex gnus-sorted-header-list ! Gnus can also sort the headers for you. (It does this by default.) You ! can control the sorting by setting the @code{gnus-sorted-header-list} ! variable. It is a list of regular expressions that says in what order ! the headers are to be displayed. ! For instance, if you want the name of the author of the article first, ! and then the subject, you might say something like: ! @lisp ! (setq gnus-sorted-header-list '("^From:" "^Subject:")) ! @end lisp ! Any headers that are to remain visible, but are not listed in this ! variable, will be displayed in random order after all the headers that ! are listed in this variable. ! @node Using Mime ! @section Using Mime ! @cindex @sc{mime} ! Mime is a standard for waving your hands through the air, aimlessly, ! while people stand around yawning. ! @sc{mime}, however, is a standard for encoding your articles, aimlessly, ! while all newsreaders die of fear. ! @sc{mime} may specify what character set the article uses, the encoding ! of the characters, and it also makes it possible to embed pictures and ! other naughty stuff in innocent-looking articles. ! @vindex gnus-show-mime ! @vindex gnus-show-mime-method ! Gnus handles @sc{mime} by shoving the articles through ! @code{gnus-show-mime-method}, which is @code{metamail-buffer} by ! default. If @code{gnus-strict-mime} is non-@code{nil}, the @sc{mime} ! method will only be used it there are @sc{mime} headers in the article. ! Set @code{gnus-show-mime} to @code{t} if you want to use @sc{mime} all ! the time; it might be best to just use the toggling functions from the ! summary buffer to avoid getting nasty surprises. (For instance, you ! enter the group @samp{alt.sing-a-long} and, before you know it, ! @sc{mime} has decoded the sound file in the article and some horrible ! sing-a-long song comes streaming out out your speakers, and you can't ! find the volume button, because there isn't one, and people are starting ! to look at you, and you try to stop the program, but you can't, and you ! can't find the program to control the volume, and everybody else in the ! room suddenly decides to look at you disdainfully, and you'll feel ! rather stupid.) ! Any similarity to real events and people is purely coincidental. Ahem. ! @node Customizing Articles ! @section Customizing Articles ! @cindex article customization ! @vindex gnus-article-display-hook ! The @code{gnus-article-display-hook} is called after the article has ! been inserted into the article buffer. It is meant to handle all ! treatment of the article before it is displayed. By default it contains ! @code{gnus-article-hide-headers}, which hides unwanted headers. ! @findex gnus-article-subcite ! @findex gnus-article-hide-signature ! @findex gnus-article-hide-citation ! Other useful functions you might add to this hook is: ! @table @code ! @item gnus-article-hide-citation ! Hide all cited text. ! @item gnus-article-hide-signature ! Umn, hides the signature. ! @item gnus-article-treat-overstrike ! Treat @samp{^H_} in a reasonable manner. ! @item gnus-article-maybe-highlight ! Do fancy article highlighting. ! @item gnus-article-remove-cr ! Removes trailing carriage returns. ! @item gnus-article-de-quoted-unreadable ! Do naive decoding of articles encoded with Quoted-Printable. ! @item gnus-article-display-x-face ! Displays any X-Face headers. ! @end table ! You can, of course, write your own functions. The functions are called ! from the article buffer, and you can do anything you like, pretty much. ! There is no information that you have to keep in the buffer - you can ! change everything. However, you shouldn't delete any headers. Instead ! make them invisible if you want to make them go away. ! @node Article Keymap ! @section Article Keymap ! @c Most of the keystrokes in the summary buffer can also be used in the ! @c article buffer. They should behave as if you typed them in the summary ! @c buffer, which means that you don't actually have to have a summary ! @c buffer displayed while reading. You can do it all from the article ! @c buffer. ! A few additional keystrokes are available: ! @table @kbd ! @item SPACE ! @kindex SPACE (Article) ! @findex gnus-article-next-page ! Scroll forwards one page (@code{gnus-article-next-page}). ! @item DEL ! @kindex DEL (Article) ! @findex gnus-article-prev-page ! Scroll backwards one page (@code{gnus-article-prev-page}). ! @item C-c ^ ! @kindex C-c ^ (Article) ! @findex gnus-article-refer-article ! If point is in the neighborhood of a @code{Message-Id} and you press ! @kbd{r}, Gnus will try to get that article from the server ! (@code{gnus-article-refer-article}). ! @item C-c C-m ! @kindex C-c C-m (Article) ! @findex gnus-article-mail ! Send a reply to the address near point (@code{gnus-article-mail}). If ! given a prefix, include the mail. ! @item s ! @kindex s (Article) ! @findex gnus-article-show-summary ! Reconfigure the buffers so that the summary buffer becomes visible ! (@code{gnus-article-show-summary}). ! @item ? ! @kindex ? (Article) ! @findex gnus-article-describe-briefly ! Give a very brief description of the available keystrokes ! (@code{gnus-article-describe-briefly}). ! @end table ! @node Misc Article ! @section Misc Article ! @table @code ! @vindex gnus-article-prepare-hook ! @item gnus-article-prepare-hook ! This hook is called right after the article has been inserted into the ! article buffer. It is mainly intended for functions that do something ! depending on the contents; it should probably not be used for changing ! the contents of the article buffer. ! @vindex gnus-article-display-hook ! @item gnus-article-display-hook ! This hook is called as the last thing when displaying an article, and is ! intended for modifying the contents of the buffer, doing highlights, ! hiding headers, and the like. ! @vindex gnus-article-mode-line-format ! @item gnus-article-mode-line-format ! This variable is a format string along the same lines as ! @code{gnus-summary-mode-line-format}. It accepts exactly the same ! format specifications as that variable. ! @vindex gnus-break-pages ! @item gnus-break-pages ! Controls whether @dfn{page breaking} is to take place. If this variable ! is non-@code{nil}, the articles will be divided into pages whenever a ! page delimiter appears in the article. If this variable is @code{nil}, ! paging will not be done. ! @item gnus-page-delimiter ! @vindex gnus-page-delimiter ! This is the delimiter mentioned above. By default, it is @samp{^L} ! (form linefeed). ! @end table ! ! @node The Server Buffer ! @chapter The Server Buffer ! ! Traditionally, a @dfn{server} is a machine or a piece of software that ! one connects to, and then requests information from. Gnus does not ! connect directly to any real servers, but does all transactions through ! one backend or other. But that's just putting one layer more between ! the actual media and Gnus, so we might just as well say that each ! backend represents a virtual server. ! ! For instance, the @code{nntp} backend may be used to connect to several ! different actual nntp servers, or, perhaps, to many different ports on ! the same actual nntp server. You tell Gnus which backend to use, and ! what parameters to set by specifying a @dfn{select method}. ! ! These select methods specifications can sometimes become quite ! complicated - say, for instance, that you want to read from the nntp ! server @samp{news.funet.fi} on port number @samp{13}, which hangs if ! queried for @sc{nov} headers and has a buggy select. Ahem. Anyways, if ! you had to specify that for each group that used this server, that would ! be too much work, so Gnus offers a way of putting names to methods, ! which is what you do in the server buffer. ! ! @menu ! * Server Buffer Format:: You can customize the look of this buffer. ! * Server Commands:: Commands to manipulate servers. ! * Example Methods:: Examples server specifications. ! * Servers & Methods:: You can use server names as select methods. ! @end menu ! ! @node Server Buffer Format ! @section Server Buffer Format ! @cindex server buffer format ! ! @vindex gnus-server-line-format ! You can change the look of the server buffer lines by changing the ! @code{gnus-server-line-format} variable. This is a @code{format}-like ! variable, with some simple extensions: ! ! @table @samp ! @item h ! How the news is fetched - the backend name. ! @item n ! The name of this server. ! @item w ! Where the news is to be fetched from - the address. ! @end table ! ! @node Server Commands ! @section Server Commands ! @cindex server commands ! ! @table @kbd ! @item SPC ! Browse the current server (@code{gnus-server-read-server}). ! @item q ! Return to the group buffer (@code{gnus-server-exit}). ! @item l ! List all servers (@code{gnus-server-list-servers}). ! @item k ! Kill the current server (@code{gnus-server-kill-server}). ! @item y ! Yank the previously killed server (@code{gnus-server-yank-server}). ! @item c ! Copy the current server (@code{gnus-server-copy-server}). ! @item a ! Add a new server (@code{gnus-server-add-server}). ! @item e ! Edit a server (@code{gnus-server-edit-server}). ! @end table ! ! @node Example Methods ! @section Example Methods ! ! Most select methods are pretty simple and self-explanatory: @lisp ! (nntp "news.funet.fi") @end lisp ! ! Reading directly from the spool is even simpler: ! @lisp ! (nnspool "") @end lisp ! As you can see, the first element in a select method is the name of the ! backend, and the second is the @dfn{address}, or @dfn{name}, if you ! will. ! After these two elements, there may be a random number of @var{(variable ! form)} pairs. ! To go back to the first example - imagine that you want to read from ! port @code{15} from that machine. This is what the select method should ! look like then: @lisp ! (nntp "news.funet.fi" (nntp-port-number 15)) @end lisp ! You should read the documentation to each backend to find out what ! variables are relevant, but here's an @code{nnmh} example. ! @code{nnmh} is a mail backend that reads a spool-like structure. Say ! you have two structures that you wish to access: One is your private ! mail spool, and the other is a public one. Here's the possible spec for ! you private mail: ! @lisp ! (nnmh "private" (nnmh-directory "~/private/mail/")) ! @end lisp ! (This server is then called @samp{private}, but you may have guessed ! that. ! Here's the method for the public spool: @lisp ! (nnmh "public" ! (nnmh-directory "/usr/information/spool/") ! (nnmh-get-new-mail nil)) @end lisp ! @node Servers & Methods ! @section Servers & Methods ! Wherever you would normally use a select method ! (eg. @code{gnus-secondary-select-method}, in the group select method, ! when browsing a foreign server) you can use a virtual server name ! instead. This could potentially save lots of typing. And it's nice all ! over. ! @node Scoring ! @chapter Scoring ! @cindex scoring ! Other people use @dfn{kill files}, but we here at Gnus Towers like ! scoring better than killing, so we'd rather switch than fight. They do ! something completely different as well, so sit up straight and pay ! attention! ! @vindex gnus-summary-mark-below ! All articles have a default score (@code{gnus-summary-default-score}). ! This score may be raised or lowered either interactively or by score ! files. Articles that have a score lower than ! @code{gnus-summary-mark-below} are marked as read. ! Gnus will read any @dfn{score files} that apply to the current group ! before generating the summary buffer. ! There are several commands in the summary buffer that insert score ! entries based on the current article. You can, for instance, ask Gnus to ! lower or increase the score of all articles with a certain subject. ! There are two sorts of scoring entries: Permanent and temporary. ! Temporary score entries are self-expiring entries. Any entries that are ! temporary and have not been used for, say, a week, will be removed ! silently to help keep the sizes of the score files down. ! @menu ! * Summary Score Commands:: Adding score entries for the current group. ! * Group Score Commands:: General score commands. ! * Score Variables:: Customize your scoring. (My, what terminology). ! * Score File Format:: What a score file may contain. ! * Score File Editing:: You can edit score files by hand as well. ! * Adaptive Scoring:: Big Sister Gnus *knows* what you read. ! * Scoring Tips:: How to score effectively. ! * Reverse Scoring:: That problem child of old is not problem. ! * Global Score Files:: Earth-spanning, ear-splitting score files. ! * Kill Files:: They are still here, but they can be ignored. ! @end menu ! @node Summary Score Commands ! @section Summary Score Commands ! @cindex score commands ! The score commands that alter score entries do not actually modify real ! score files. That would be too inefficient. Gnus maintains a cache of ! previously loaded score files, one of which is considered the ! @dfn{current score file alist}. The score commands simply insert ! entries into this list, and upon group exit, this list is saved. ! The current score file is by default the group's local score file, even ! if no such score file actually exists. To insert score commands into ! some other score file (eg. @file{all.SCORE}), you must first make this ! score file the current one. ! General score commands that don't actually change the score file: @table @kbd ! @item V s ! @kindex V s (Summary) ! @findex gnus-summary-set-score ! Set the score of the current article (@code{gnus-summary-set-score}). ! @item V S ! @kindex V S (Summary) ! @findex gnus-summary-current-score ! Display the score of the current article ! (@code{gnus-summary-current-score}). ! @item V t ! @kindex V t (Summary) ! @findex gnus-score-find-trace ! Display all score rules that have been used on the current article ! (@code{gnus-score-find-trace}). ! @item V a ! @kindex V a (Summary) ! @findex gnus-summary-score-entry ! Add a new score entry, and allow specifying all elements ! (@code{gnus-summary-score-entry}). ! @item V c ! @kindex V c (Summary) ! @findex gnus-score-change-score-file ! Make a different score file the current ! (@code{gnus-score-change-score-file}). ! @item V e ! @kindex V e (Summary) ! @findex gnus-score-edit-alist ! Edit the current score file (@code{gnus-score-edit-alist}). You will be ! popped into a @code{gnus-score-mode} buffer (@pxref{Score File ! Editing}). ! @item V f ! @kindex V f (Summary) ! @findex gnus-score-edit-file ! Edit a score file and make this score file the current one ! (@code{gnus-score-edit-file}). ! @item I C-i ! @kindex I C-i (Summary) ! @findex gnus-summary-raise-score ! Increase the score of the current article ! (@code{gnus-summary-raise-score}). ! @item L C-l ! @kindex L C-l (Summary) ! @findex gnus-summary-lower-score ! Lower the score of the current article ! (@code{gnus-summary-lower-score}). @end table ! The rest of these commands modify the local score file. ! @table @kbd ! @item V m ! @kindex V m (Summary) ! @findex gnus-score-set-mark-below ! Prompt for a score, and mark all articles with a score below this as ! read (@code{gnus-score-set-mark-below}). ! @item V E ! @kindex V E (Summary) ! @findex gnus-score-set-expunge-below ! Expunge all articles with a score below the default score (or the ! numeric prefix) (@code{gnus-score-set-expunge-below}). ! @end table + The keystrokes for actually making score entries follow a very regular + pattern, so there's no need to list all the commands. (Hundreds of + them.) ! @enumerate ! @item ! The first key is either @kbd{I} (upper case i) for increasing the score ! or @kbd{L} for lowering the score. ! @item ! The second key says what header you want to score on. The following ! keys are available: ! @table @kbd ! @item a ! Score on the author name. ! @item s ! Score on the subject line. ! @item x ! Score on the Xref line - i.e., the cross-posting line. ! @item t ! Score on thread - the References line. ! @item d ! Score on the date. ! @item l ! Score on the number of lines. ! @item i ! Score on the Message-ID. ! @item f ! Score on followups. ! @item b ! Score on the body. ! @item h ! Score on the head. ! @end table ! @item ! The third key is the match type. Which match types are legal depends on ! what headers you are scoring on. ! @table @code ! @item strings @table @kbd ! @item e ! Exact matching. ! @item s ! Substring matching. ! @item f ! Fuzzy matching. ! @item r ! Regexp matching ! @end table ! @item date ! @table @kbd ! @item b ! Before date. ! @item a ! At date. ! @item n ! This date. ! @end table ! @item number ! @table @kbd ! @item < ! Less than number. ! @item = ! Equal to number. ! @item > ! Greater than number. ! @end table ! @end table ! @item ! The fourth and final key says whether this is a temporary (i.e., expiring) ! score entry, or a permanent (i.e., non-expiring) score entry, or whether ! it is to be done immediately, without adding to the score file. ! @table @kbd ! @item t ! Temporary score entry. ! @item p ! Permanent score entry. ! @item i ! Immediately scoring. ! @end table ! @end enumerate ! So, let's say you want to increase the score on the current author with ! exact matching permanently: @kbd{I a e p}. If you want to lower the ! score based on the subject line, using substring matching, and make a ! temporary score entry: @kbd{L s s t}. Pretty easy. ! To make things a bit more complicated, there are shortcuts. If you use ! a capital letter on either the second or third keys, Gnus will use ! defaults for the remaining one or two keystrokes. The defaults are ! "substring" and "temporary". So @kbd{I A} is the same as @kbd{I a s t}, ! and @kbd{I a R} is the same as @kbd{I a r t}. ! @vindex gnus-score-mimic-keymap ! The @code{gnus-score-mimic-keymap} says whether these commands will ! pretend they are keymaps or not. ! @node Group Score Commands ! @section Group Score Commands ! @cindex group score commands ! There aren't many of these as yet, I'm afraid. @table @kbd ! @item W f ! @kindex W f (Group) ! @findex gnus-score-flush-cache ! Gnus maintains a cache of score alists to avoid having to reload them ! all the time. This command will flush the cache ! (@code{gnus-score-flush-cache}). @end table ! @node Score Variables ! @section Score Variables ! @cindex score variables ! @table @code ! @item gnus-use-scoring ! @vindex gnus-use-scoring ! If @code{nil}, Gnus will not check for score files, and will not, in ! general, do any score-related work. ! @item gnus-kill-killed ! @vindex gnus-kill-killed ! If this variable is @code{nil}, Gnus will never apply score files to ! articles that have already been through the kill process. While this ! may save you lots of time, it also means that if you apply a kill file ! to a group, and then change the kill file and want to run it over you ! group again to kill more articles, it won't work. You have to set this ! variable to @code{t} to do that. ! @item gnus-kill-files-directory ! @vindex gnus-kill-files-directory ! All kill and score files will be stored in this directory, which is ! initialized from the @samp{SAVEDIR} environment variable by default. ! @item gnus-score-file-suffix ! @vindex gnus-score-file-suffix ! Suffix to add to the group name to arrive at the score file name ! (@samp{SCORE} by default.) ! @item gnus-score-interactive-default-score ! @vindex gnus-score-interactive-default-score ! Score used by all the interactive raise/lower commands to raise/lower ! score with. Default is 1000, which may seem excessive, but this is to ! ensure that the adaptive scoring scheme gets enough room to play with. ! We don't want the small changes from the adaptive scoring to overwrite ! manually entered data. ! @item gnus-summary-default-score ! @vindex gnus-summary-default-score ! Default score of an article, which is 0 by default. ! @item gnus-score-over-mark ! @vindex gnus-score-over-mark ! Mark (in the third column) used for articles with a score over the ! default. Default is @samp{+}. ! @item gnus-score-below-mark ! @vindex gnus-score-below-mark ! Mark (in the third column) used for articles with a score below the ! default. Default is @samp{-}. ! @item gnus-score-find-score-files-function ! @vindex gnus-score-find-score-files-function ! Function used to find score files for the current group. This function ! is called with the name of the group as the argument. ! Predefined functions available are: ! @table @code ! @item gnus-score-find-single ! @findex gnus-score-find-single ! Only apply the group's own score file. ! @item gnus-score-find-bnews ! @findex gnus-score-find-bnews ! Apply all score files that match, using bnews syntax. For instance, if ! the current group is @samp{gnu.emacs.gnus}, @samp{all.emacs.all.SCORE}, ! @samp{not.alt.all.SCORE} and @samp{gnu.all.SCORE} would all apply. In ! short, the instances of @samp{all} in the score file names are ! translated into @samp{.*}, and then a regexp match is done. ! If @code{gnus-use-long-file-name} is non-@code{nil}, this won't work ! very will. It will find stuff like @file{gnu/all/SCORE}, but will not ! find files like @file{not/gnu/all/SCORE}. ! @item gnus-score-find-hierarchical ! @findex gnus-score-find-hierarchical ! Apply all score files from all the parent groups. ! @end table ! This variable can also be a list of functions. In that case, all these ! functions will be called, and all the returned lists of score files will ! be applied. These functions can also return lists of score alists ! directly. In that case, the functions that return these non-file score ! alists should probably be placed before the "real" score file functions, ! to ensure that the last score file returned is the local score file. ! Phu. ! @item gnus-score-expiry-days ! @vindex gnus-score-expiry-days ! This variable says how many days should pass before an unused score file ! entry is expired. The default is 7. ! @end table ! @node Score File Format ! @section Score File Format ! @cindex score file format ! A score file is an @code{emacs-lisp} file that normally contains just a ! single form. Casual users are not expected to edit these files; ! everything can be changed from the summary buffer. ! Anyway, if you'd like to dig into it yourself, here's an example: @lisp ! (("from" ! ("Lars Ingebrigtsen" -10000) ! ("Per Abrahamsen") ! ("larsi\\|lmi" -50000 nil R)) ! ("subject" ! ("Ding is Badd" nil 728373)) ! ("xref" ! ("alt.politics" -1000 728372 s)) ! ("lines" ! (2 -100 nil <)) ! (mark 0) ! (expunge -1000) ! (mark-and-expunge -10) ! (read-only nil) ! (orphan -10) ! (adapt t) ! (files "/hom/larsi/News/gnu.SCORE") ! (local (gnus-newsgroup-auto-expire t) ! (gnus-summary-make-false-root 'empty)) ! (eval (ding))) @end lisp ! This example demonstrates absolutely everything about a score file. ! Even though this looks much like lisp code, nothing here is actually ! @code{eval}ed. The lisp reader is used to read this form, though, so it ! has to be legal syntactically, if not semantically. ! Six keys are supported by this alist: ! @table @code ! @item STRING ! If the key is a string, it is the name of the header to perform the ! match on. Scoring can only be performed on these eight headers: ! @samp{From}, @samp{Subject}, @samp{References}, @samp{Message-ID}, ! @samp{Xref}, @samp{Lines}, @samp{Chars} and @samp{Date}. In addition to ! these headers, there are three strings to tell Gnus to fetch the entire ! article and do the match on larger parts of the article: @samp{Body} ! will perform the match on the body of the article, @samp{Head} will ! perform the match on the head of the article, and @samp{All} will ! perform the match on the entire article. Note that using any of these ! last three keys will slow down group entry @emph{considerably}. ! ! Following this key is a random number of score entries, where each score ! entry has one to four elements. ! @enumerate ! @item ! The first element is the @dfn{match element}. On most headers this will ! be a string, but on the Lines and Chars headers, this must be an ! integer. ! @item ! If the second element is present, it should be a number - the @dfn{score ! element}. This number should be an integer in the neginf to posinf ! interval. This number is added to the score of the article if the match ! is successful. If this element is not present, the ! @code{gnus-score-interactive-default-score} number will be used instead. ! @item ! If the third element is present, it should be a number - the @dfn{date ! element}. This date says when the last time this score entry matched, ! which provides a mechanism for expiring the score entries. It this ! element is not present, the score entry is permanent. The date is ! represented by the number of days since December 31, 1 ce. ! @item ! If the fourth element is present, it should be a symbol - the @dfn{type ! element}. This element specifies what function should be used to see ! whether this score entry matches the article. What match types that can ! be used depends on what header you wish to perform the match on. ! @table @dfn ! @item From, Subject, References, Xref, Message-ID ! For most header types, there are the @code{r} and @code{R} (regexp) as ! well as @code{s} and @code{S} (substring) types and @code{e} and ! @code{E} (exact match) types. If this element is not present, Gnus will ! assume that substring matching should be used. @code{R} and @code{S} ! differ from the other two in that the matches will be done in a ! case-sensitive manner. All these one-letter types are really just ! abbreviations for the @code{regexp}, @code{string} and @code{exact} ! types, which you can use instead, if you feel like. ! @item Lines, Chars ! These two headers use different match types: @code{<}, @code{>}, ! @code{=}, @code{>=} and @code{<=}. ! @item Date ! For the Date header we have three match types: @code{before}, @code{at} ! and @code{after}. I can't really imagine this ever being useful, but, ! like, it would feel kinda silly not to provide this function. Just in ! case. You never know. Better safe than sorry. Once burnt, twice shy. ! Don't judge a book by its cover. Never not have sex on a first date. ! @item Head, Body, All ! These three match keys use the same match types as the @code{From} (etc) ! header uses. ! @item Followup ! This match key will add a score entry on all articles that followup to ! some author. Uses the same match types as the @code{From} header uses. ! @end table ! @end enumerate ! ! @item mark ! The value of this entry should be a number. Any articles with a score ! lower than this number will be marked as read. ! @item expunge ! The value of this entry should be a number. Any articles with a score ! lower than this number will be removed from the summary buffer. ! @item mark-and-expunge ! The value of this entry should be a number. Any articles with a score ! lower than this number will be marked as read and removed from the ! summary buffer. ! @item files ! The value of this entry should be any number of file names. These files ! are assumed to be score files as well, and will be loaded the same way ! this one was. ! @item exclude-files ! The clue of this entry should be any number of files. This files will ! not be loaded, even though they would normally be so, for some reason or ! other. ! @item eval ! The value of this entry will be @code{eval}el. This element will be ! ignored when handling global score files. ! @item read-only ! Read-only score files will not be updated or saved. Global score files ! should feature this atom (@pxref{Global Score Files}). ! @item orphan ! The value of this entry should be a number. Articles that do not have ! parents will get this number added to their scores. ! @item adapt ! This entry controls the adaptive scoring. If it is @code{t}, the ! default adaptive scoring rules will be used. If it is @code{ignore}, no ! adaptive scoring will be performed on this group. If it is a list, this ! list will be used as the adaptive scoring rules. If it isn't present, ! or is something other than @code{t} or @code{ignore}, the default ! adaptive scoring rules will be used. If you want to use adaptive ! scoring on most groups, you'd set @code{gnus-use-adaptive-scoring} to ! @code{t}, and insert an @code{(adapt ignore)} in the groups where you do ! not want adaptive scoring. If you only want adaptive scoring in a few ! groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and ! insert @code{(adapt t)} in the score files of the groups where you want ! it. ! @item local ! @cindex local variables ! The value of this entry should be a list of @code{(VAR VALUE)} pairs. ! Each @var{var} will be made buffer-local to the current summary buffer, ! and set to the value specified. This is a convenient, if somewhat ! strange, way of setting variables in some groups if you don't like hooks ! much. @end table ! @node Score File Editing ! @section Score File Editing ! You normally enter all scoring commands from the summary buffer, but you ! might feel the urge to edit them by hand as well, so we've supplied you ! with a mode for that. ! It's simply a slightly customized @code{emacs-lisp} mode, with these ! additional commands: ! @table @kbd ! @item C-c C-c ! @kindex C-c C-c (Score) ! @findex gnus-score-edit-done ! Save the changes you have made and return to the summary buffer ! (@code{gnus-score-edit-done}). ! @item C-c C-d ! @kindex C-c C-d (Score) ! @findex gnus-score-edit-insert-date ! Insert the current date in numerical format ! (@code{gnus-score-edit-insert-date}). This is really the day number, if ! you were wondering. ! @end table ! @node Adaptive Scoring ! @section Adaptive Scoring ! @cindex adaptive scoring ! If all this scoring is getting you down, Gnus has a way of making it all ! happen automatically - as if by magic. Or rather, as if by artificial ! stupidity, to be precise. ! @vindex gnus-use-adaptive-scoring ! When you read an article, or mark an article as read, or kill an ! article, you leave marks behind. On exit from the group, Gnus can sniff ! these marks and add score elements depending on what marks it finds. ! You turn on this ability by setting @code{gnus-use-adaptive-scoring} to ! @code{t}. ! @vindex gnus-default-adaptive-score-alist ! To give you complete control over the scoring process, you can customize ! the @code{gnus-default-adaptive-score-alist} variable. By default, it ! looks something like this: ! @lisp ! (defvar gnus-default-adaptive-score-alist ! '((gnus-unread-mark) ! (gnus-ticked-mark (from 4)) ! (gnus-dormant-mark (from 5)) ! (gnus-del-mark (from -4) (subject -1)) ! (gnus-read-mark (from 4) (subject 2)) ! (gnus-expirable-mark (from -1) (subject -1)) ! (gnus-killed-mark (from -1) (subject -3)) ! (gnus-kill-file-mark) ! (gnus-catchup-mark (from -1) (subject -1)))) ! @end lisp ! As you see, each element in this alist has a mark as a key (either a ! variable name or a "real" mark - a character). Following this key is a ! random number of header/score pairs. ! To take @code{gnus-del-mark} as an example - this alist says that all ! articles that have that mark (i.e., are marked with @samp{D}) will have a ! score entry added to lower based on the @code{From} header by -4, and ! lowered by @code{Subject} by -1. Change this to fit your prejudices. ! If you use this scheme, you should set @code{mark-below} to something ! small - like -300, perhaps, to avoid having small random changes result ! in articles getting marked as read. ! After using adaptive scoring for a week or so, Gnus should start to ! become properly trained and enhance the authors you like best, and kill ! the authors you like least, without you having to say so explicitly. ! You can control what groups the adaptive scoring is to be performed on ! by using the score files (@pxref{Score File Format}). This will also ! let you use different rules in different groups. ! @vindex gnus-adaptive-file-suffix ! The adaptive score entries will be put into a file where the name is the ! group name with @code{gnus-adaptive-file-suffix} appended. ! @vindex gnus-score-exact-adapt-limit ! When doing adaptive scoring, substring or fuzzy matching would probably ! give you the best results in most cases. However, if the header one ! matches is short, the possibility for false positives is great, so if ! the length of the match is less than ! @code{gnus-score-exact-adapt-limit}, exact matching will be used. If ! this variable is @code{nil}, exact matching will always be used to avoid ! this problem. ! @node Scoring Tips ! @section Scoring Tips ! @cindex scoring tips ! @table @dfn ! @item Crossposts ! If you want to lower the score of crossposts, the line to match on is ! the @code{Xref} header. ! @lisp ! ("xref" (" talk.politics.misc:" -1000)) ! @end lisp ! @item Multiple crossposts ! If you want to lower the score of articles that have been crossposted to ! more than, say, 3 groups: ! @lisp ! ("xref" (" +[^ ]+:[0-9]+ +[^ ]+:[0-9]+ +[^ ]+:[0-9]+" -1000 nil r)) ! @end lisp ! @item Matching on the body ! This is generally not a very good idea - it takes a very long time. ! Gnus actually has to fetch each individual article from the server. But ! you might want to anyway, I guess. Even though there are three match ! keys (@code{Head}, @code{Body} and @code{All}), you should choose one ! and stick with it in each score file. If you use any two, each article ! will be fetched @emph{twice}. If you want to match a bit on the ! @code{Head} and a bit on the @code{Body}, just use @code{All} for all ! the matches. ! @item Marking as read ! You will probably want to mark articles that has a score below a certain ! number as read. This is most easily achieved by putting the following ! in your @file{all.SCORE} file: ! @lisp ! ((mark -100)) ! @end lisp ! You may also consider doing something similar with @code{expunge}. ! ! @item Negated charater classes ! If you say stuff like @code{[^abcd]*}, you may get unexpected results. ! That will match newlines, which might lead to, well, The Unknown. Say ! @code{[^abcd\n]*} instead. @end table ! @node Reverse Scoring ! @section Reverse Scoring ! @cindex reverse scoring ! If you want to keep just articles that have @samp{Sex with Emacs} in the ! subject header, and expunge all other articles, you could put something ! like this in your score file: ! @lisp ! (("subject" ! ("Sex with Emacs" 2)) ! (mark 1) ! (expunge 1)) ! @end lisp ! So, you raise all articles that match @samp{Sex with Emacs} and mark the ! rest as read, and expunge them to boot. ! @node Global Score Files ! @section Global Score Files ! @cindex global score files ! Sure, other newsreaders have "global kill files". These are usually ! nothing more than a single kill file that applies to all groups, stored ! in the user's home directory. Bah! Puny, weak newsreaders! ! What I'm talking about here are Global Score Files. Score files from ! all over the world, from users everywhere, uniting all nations in one ! big, happy score file union! Ange-score! New and untested! ! @vindex gnus-global-score-files ! All you have to do to use other people's score files is to set the ! @code{gnus-global-score-files} variable. One entry for each score file, ! or each score file directory. Gnus will decide by itself what score ! files are applicable to which group. ! Say you want to use all score files in the ! @file{/ftp@@ftp.some-where:/pub/score} directory and the single score ! file @file{/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE}: ! @lisp ! (setq gnus-global-score-files ! '("/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE" ! "/ftp@@ftp.some-where:/pub/score/")) ! @end lisp ! @findex gnus-score-search-global-directories ! Simple, eh? Directory names must end with a @samp{/}. These ! directories are typically scanned only once during each Gnus session. ! If you feel the need to manually re-scan the remote directories, you can ! use the @code{gnus-score-search-global-directories} command. ! Note that, at present, using this option will slow down group entry ! somewhat. (That is - a lot.) ! If you want to start maintaining score files for other people to use, ! just put your score file up for anonymous ftp and announce it to the ! world. Become a retro-moderator! Participate in the retro-moderator ! wars sure to ensue, where retro-moderators battle it out for the ! sympathy of the people, luring them to use their score files on false ! premises! Yay! The net is saved! ! Here are some tips for the would-be retro-moderator, off the top of my ! head: ! @itemize @bullet ! @item ! Articles that are heavily crossposted are probably junk. ! @item ! To lower a single inappropriate article, lower by @code{Message-Id}. ! @item ! Particularly brilliant authors can be raised on a permanent basis. ! @item ! Authors that repeatedly post off-charter for the group can safely be ! lowered out of existence. ! @item ! Set the @code{mark} and @code{expunge} atoms to obliterate the nastiest ! articles completely. ! @item ! Use expiring score entries to keep the size of the file down. You ! should probably have a long expiry period, though, as some sites keep ! old articles for a long time. ! @end itemize ! ... I wonder whether other newsreaders will support global score files ! in the future. @emph{Snicker}. Yup, any day now, newsreaders like Blue ! Wave, xrn and 1stReader are bound to implement scoring. Should we start ! holding our breath yet? ! @node Kill Files ! @section Kill Files ! @cindex kill files ! Gnus still supports those pesky old kill files. In fact, the kill file ! entries can now be expiring, which is something I wrote before Per ! thought of doing score files, so I've left the code in there. ! In short, kill processing is a lot slower (and I do mean @emph{a lot}) ! than score processing, so it might be a good idea to rewrite your kill ! files into score files. ! Anyway, a kill file is a normal @code{emacs-lisp} file. You can put any ! forms into this file, which means that you can use kill files as some ! sort of primitive hook function to be run on group entry, even though ! that isn't a very good idea. ! ! XCNormal kill files look like this: @lisp ! (gnus-kill "From" "Lars Ingebrigtsen") ! (gnus-kill "Subject" "ding") ! (gnus-expunge "X") @end lisp ! This will mark every article written by me as read, and remove them from ! the summary buffer. Very useful, you'll agree. ! Other programs use a totally different kill file syntax. If Gnus ! encounters what looks like a @code{rn} kill file, it will take a stab at ! interpreting it. ! Two functions for editing a GNUS kill file: ! ! @table @kbd ! @item M-k ! @kindex M-k (Summary) ! @findex gnus-summary-edit-local-kill ! Edit this group's kill file (@code{gnus-summary-edit-local-kill}). ! ! @item M-K ! @kindex M-K (Summary) ! @findex gnus-summary-edit-global-kill ! Edit the general kill file (@code{gnus-summary-edit-global-kill}). ! @end table ! ! @vindex gnus-kill-file-name ! A kill file for the group @samp{soc.motss} is normally called ! @file{soc.motss.KILL}. The suffix appended to the group name to get ! this file name is detailed by the @code{gnus-kill-file-name} variable. ! The "global" kill file (not in the score file sense of "global", of ! course) is called just @file{KILL}. ! ! @vindex gnus-kill-save-kill-file ! If @code{gnus-kill-save-kill-file} is non-@code{nil}, Gnus will save the ! kill file after processing, which is necessary if you use expiring ! kills. @node Various *************** *** 7294,7302 **** --- 7361,7421 ---- @item gnus-visual @vindex gnus-visual + @cindex visual + @cindex highlighting + @cindex menus + If @code{nil}, Gnus won't attempt to create menus or use fancy colors or fonts. This will also inhibit loading the @file{gnus-visual.el} file. + + This variable can also be a list of visual properties that are enabled. + The following elements are legal, and are all set by default: + + @table @code + + @item summary-highlight + Perform various highlighting in the summary buffer. + + @item article-highlight + Perform various highlighting in the article buffer. + + @item highlight + Turn on highlighting in all buffers. + + @item group-menu + Create menus in the group buffer. + + @item summary-menu + Create menus in the summary buffer. + + @item article-menu + Create menus in the article buffer. + + @item browse-menu + Create menus in the browse buffer. + + @item server-menu + Create menus in the server buffer. + + @item menu + Create menus in all buffers. + + @end table + + So if you only want highlighting in the article buffer and menus in all + buffers, you couls say something like: + + @lisp + (setq gnus-visual '(article-highlight menu)) + @end lisp + + If you want only highlighting and no menus whatsoever, you'd say: + + @lisp + (setq gnus-visual '(highlight)) + @end lisp + @item gnus-mouse-face @vindex gnus-mouse-face This is the face (i.e., font) used for mouse highlighting in Gnus. No *** pub/sgnus/texi/ChangeLog Thu Sep 21 01:16:59 1995 --- sgnus/texi/ChangeLog Fri Sep 22 14:45:16 1995 *************** *** 1,3 **** --- 1,14 ---- + Fri Sep 22 14:44:26 1995 Lars Ingebrigtsen + + * gnus.texi (Various Various): Addition. + + Thu Sep 21 13:55:16 1995 Lars Ingebrigtsen + + * gnus.texi (Article Washing): Change. + (Selecting a Group): Addition. + (Mail & Post): Change. + (Scoring): Made into a chapter. + Wed Sep 20 16:14:11 1995 Lars Ingebrigtsen * gnus.texi (Drafts): New.