X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=lisp%2Fgnus.el;h=373d3438ffdf84eddc54f767e9111951980c4d60;hb=c8b25eebe2bfccd8b707d8c9e8ffa0d88d4a20af;hp=0181566438e08902ae92b1245d6108f83e7c5bab;hpb=8f32b1534222e4f9abb7e1e32b79fc52353a2312;p=elisp%2Fgnus.git- diff --git a/lisp/gnus.el b/lisp/gnus.el index 0181566..4c3c359 100644 --- a/lisp/gnus.el +++ b/lisp/gnus.el @@ -1,8 +1,8 @@ ;;; gnus.el --- a newsreader for GNU Emacs -;; Copyright (C) 1987,88,89,90,93,94,95,96,97 Free Software Foundation, Inc. +;; Copyright (C) 1987-1990,1993-1999 Free Software Foundation, Inc. ;; Author: Masanobu UMEDA -;; Lars Magne Ingebrigtsen +;; Lars Magne Ingebrigtsen ;; Keywords: news, mail ;; This file is part of GNU Emacs. @@ -29,6 +29,7 @@ (eval '(run-hooks 'gnus-load-hook)) (eval-when-compile (require 'cl)) +(require 'mm-util) (require 'custom) (eval-and-compile @@ -41,6 +42,15 @@ :group 'news :group 'mail) +(defgroup gnus-charset nil + "Group character set issues." + :link '(custom-manual "(gnus)Charsets") + :group 'gnus) + +(defgroup gnus-cache nil + "Cache interface." + :group 'gnus) + (defgroup gnus-start nil "Starting your favorite newsreader." :group 'gnus) @@ -241,17 +251,20 @@ is restarted, and sometimes reloaded." :link '(custom-manual "(gnus)Various Various") :group 'gnus) +(defgroup gnus-mime nil + "Variables for controlling the Gnus MIME interface." + :group 'gnus) + (defgroup gnus-exit nil "Exiting gnus." :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) -(defconst gnus-version-number "6.0.1" - "Version number for this version of gnus.") +(defconst gnus-version-number "0.97" + "Version number for this version of Gnus.") -(defconst gnus-version - (format "Semi-gnus %s (based on Quassia Gnus v0.22)" gnus-version-number) - "Version string for this version of gnus.") +(defconst gnus-version (format "Pterodactyl Gnus v%s" gnus-version-number) + "Version string for this version of Gnus.") (defcustom gnus-inhibit-startup-message nil "If non-nil, the startup message will not be displayed. @@ -265,8 +278,6 @@ be set in `.emacs' instead." :group 'gnus-start :type 'boolean) -;;; Kludges to help the transition from the old `custom.el'. - (unless (featurep 'gnus-xmas) (defalias 'gnus-make-overlay 'make-overlay) (defalias 'gnus-delete-overlay 'delete-overlay) @@ -286,7 +297,8 @@ be set in `.emacs' instead." (defalias 'gnus-characterp 'numberp) (defalias 'gnus-deactivate-mark 'deactivate-mark) (defalias 'gnus-window-edges 'window-edges) - (defalias 'gnus-key-press-event-p 'numberp)) + (defalias 'gnus-key-press-event-p 'numberp) + (defalias 'gnus-decode-rfc1522 'ignore)) ;; We define these group faces here to avoid the display ;; update forced when creating new faces. @@ -357,6 +369,72 @@ be set in `.emacs' instead." ())) "Level 3 empty newsgroup face.") +(defface gnus-group-news-4-face + '((((class color) + (background dark)) + (:bold t)) + (((class color) + (background light)) + (:bold t)) + (t + ())) + "Level 4 newsgroup face.") + +(defface gnus-group-news-4-empty-face + '((((class color) + (background dark)) + ()) + (((class color) + (background light)) + ()) + (t + ())) + "Level 4 empty newsgroup face.") + +(defface gnus-group-news-5-face + '((((class color) + (background dark)) + (:bold t)) + (((class color) + (background light)) + (:bold t)) + (t + ())) + "Level 5 newsgroup face.") + +(defface gnus-group-news-5-empty-face + '((((class color) + (background dark)) + ()) + (((class color) + (background light)) + ()) + (t + ())) + "Level 5 empty newsgroup face.") + +(defface gnus-group-news-6-face + '((((class color) + (background dark)) + (:bold t)) + (((class color) + (background light)) + (:bold t)) + (t + ())) + "Level 6 newsgroup face.") + +(defface gnus-group-news-6-empty-face + '((((class color) + (background dark)) + ()) + (((class color) + (background light)) + ()) + (t + ())) + "Level 6 empty newsgroup face.") + (defface gnus-group-news-low-face '((((class color) (background dark)) @@ -597,6 +675,33 @@ be set in `.emacs' instead." "Face used for normal interest read articles.") +;;; +;;; Gnus buffers +;;; + +(defvar gnus-buffers nil) + +(defun gnus-get-buffer-create (name) + "Do the same as `get-buffer-create', but store the created buffer." + (or (get-buffer name) + (car (push (get-buffer-create name) gnus-buffers)))) + +(defun gnus-add-buffer () + "Add the current buffer to the list of Gnus buffers." + (push (current-buffer) gnus-buffers)) + +(defun gnus-buffers () + "Return a list of live Gnus buffers." + (while (and gnus-buffers + (not (buffer-name (car gnus-buffers)))) + (pop gnus-buffers)) + (let ((buffers gnus-buffers)) + (while (cdr buffers) + (if (buffer-name (cadr buffers)) + (pop buffers) + (setcdr buffers (cddr buffers))))) + gnus-buffers) + ;;; Splash screen. (defvar gnus-group-buffer "*Group*") @@ -607,17 +712,17 @@ be set in `.emacs' instead." (defface gnus-splash-face '((((class color) (background dark)) - (:foreground "ForestGreen")) + (:foreground "Brown")) (((class color) (background light)) - (:foreground "ForestGreen")) + (:foreground "Brown")) (t ())) - "Level 1 newsgroup face.") + "Face of the splash screen.") (defun gnus-splash () (save-excursion - (switch-to-buffer (get-buffer-create gnus-group-buffer)) + (switch-to-buffer (gnus-get-buffer-create gnus-group-buffer)) (let ((buffer-read-only nil)) (erase-buffer) (unless gnus-inhibit-startup-message @@ -685,9 +790,10 @@ be set in `.emacs' instead." (eval-when (load) (let ((command (format "%s" this-command))) - (when (and (string-match "gnus" command) - (not (string-match "gnus-other-frame" command))) - (gnus-splash)))) + (if (and (string-match "gnus" command) + (not (string-match "gnus-other-frame" command))) + (gnus-splash) + (gnus-get-buffer-create gnus-group-buffer)))) ;;; Do the rest. @@ -703,7 +809,12 @@ All other Gnus path variables are initialized from this variable." (defcustom gnus-directory (or (getenv "SAVEDIR") (nnheader-concat gnus-home-directory "News/")) - "Directory variable from which all other Gnus file variables are derived." + "*Directory variable from which all other Gnus file variables are derived. + +Note that Gnus is mostly loaded when the `.gnus.el' file is read. +This means that other directory variables that are initialized from +this variable won't be set properly if you set this variable in `.gnus.el'. +Set this variable in `.emacs' instead." :group 'gnus-files :type 'directory) @@ -745,22 +856,20 @@ used to 899, you would say something along these lines: (or (getenv "NNTPSERVER") (and (file-readable-p gnus-nntpserver-file) (save-excursion - (set-buffer (get-buffer-create " *gnus nntp*")) - (buffer-disable-undo (current-buffer)) + (set-buffer (gnus-get-buffer-create " *gnus nntp*")) (insert-file-contents gnus-nntpserver-file) (let ((name (buffer-string))) (prog1 - (if (string-match "^[ \t\n]*$" name) + (if (string-match "\\'[ \t\n]*$" name) nil name) (kill-buffer (current-buffer)))))))) (defcustom gnus-select-method - (condition-case nil + (ignore-errors (nconc - (list 'nntp (or (condition-case nil - (gnus-getenv-nntpserver) - (error nil)) + (list 'nntp (or (ignore-errors + (gnus-getenv-nntpserver)) (when (and gnus-default-nntp-server (not (string= gnus-default-nntp-server ""))) gnus-default-nntp-server) @@ -768,9 +877,8 @@ used to 899, you would say something along these lines: (if (or (null gnus-nntp-service) (equal gnus-nntp-service "nntp")) nil - (list gnus-nntp-service))) - (error nil)) - "Default method for selecting a newsgroup. + (list gnus-nntp-service)))) + "*Default method for selecting a newsgroup. This variable should be a list, where the first element is how the news is to be fetched, the second is the address. @@ -798,7 +906,7 @@ see the manual for details." ,(nnheader-concat message-directory "archive/active")) (nnfolder-get-new-mail nil) (nnfolder-inhibit-expiry t)) - "Method used for archiving messages you've sent. + "*Method used for archiving messages you've sent. This should be a mail method. It's probably not a very effective to change this variable once you've @@ -830,6 +938,8 @@ that case, just return a fully prefixed name of the group -- \"nnml+private:mail.misc\", for instance." :group 'gnus-message :type '(choice (const :tag "none" nil) + function + sexp string)) (defcustom gnus-secondary-servers nil @@ -903,7 +1013,7 @@ in the documentation of `gnus-select-method'." "/ftp@nctuccca.edu.tw:/USENET/FAQ/" "/ftp@hwarang.postech.ac.kr:/pub/usenet/" "/ftp@ftp.hk.super.net:/mirror/faqs/") - "Directory where the group FAQs are stored. + "*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. @@ -1044,24 +1154,19 @@ articles. This is not a good idea." :group 'gnus-meta :type 'boolean) -(defcustom gnus-use-demon nil - "If non-nil, Gnus might use some demons." - :group 'gnus-meta - :type 'boolean) - (defcustom gnus-use-scoring t "*If non-nil, enable scoring." :group 'gnus-meta :type 'boolean) (defcustom gnus-use-picons nil - "*If non-nil, display picons." + "*If non-nil, display picons in a frame of their own." :group 'gnus-meta :type 'boolean) (defcustom gnus-summary-prepare-exit-hook '(gnus-summary-expire-articles) - "A hook called when preparing to exit from the summary buffer. + "*A hook called when preparing to exit from the summary buffer. It calls `gnus-summary-expire-articles' by default." :group 'gnus-summary-exit :type 'hook) @@ -1075,7 +1180,8 @@ required." (defcustom gnus-expert-user nil "*Non-nil means that you will never be asked for confirmation about anything. -And that means *anything*." +That doesn't mean *anything* anything; particularly destructive +commands will still require prompting." :group 'gnus-meta :type 'boolean) @@ -1125,10 +1231,11 @@ slower." ("nnsoup" post-mail address) ("nndraft" post-mail) ("nnfolder" mail respool address) - ("nngateway" none address prompt-address physical-address) + ("nngateway" post-mail address prompt-address physical-address) ("nnweb" none) + ("nnlistserv" none) ("nnagent" post-mail)) - "An alist of valid select methods. + "*An alist of valid select methods. The first element of each list lists should be a string with the name of the select method. The other elements may be the category of this method (i. e., `post', `mail', `none' or whatever) or other @@ -1242,7 +1349,7 @@ following hook: (defcustom gnus-group-change-level-function nil "Function run when a group level is changed. It is called with three parameters -- GROUP, LEVEL and OLDLEVEL." - :group 'gnus-group-level + :group 'gnus-group-levels :type 'function) ;;; Face thingies. @@ -1255,7 +1362,7 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL." browse-menu server-menu page-marker tree-menu binary-menu pick-menu grouplens-menu) - "Enable visual features. + "*Enable visual features. 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. @@ -1298,66 +1405,12 @@ and `grouplens-menu'." 'highlight) 'default) (error 'highlight)) - "Face used for group or summary buffer mouse highlighting. + "*Face used for group or summary buffer mouse highlighting. The line beneath the mouse pointer will be highlighted with this face." :group 'gnus-visual :type 'face) -(defcustom gnus-article-display-hook - (if (and (string-match "XEmacs" emacs-version) - (featurep 'xface)) - '(gnus-article-hide-headers-if-wanted - gnus-article-hide-boring-headers - gnus-article-treat-overstrike - gnus-article-maybe-highlight - gnus-article-display-x-face) - '(gnus-article-hide-headers-if-wanted - gnus-article-hide-boring-headers - gnus-article-treat-overstrike - gnus-article-maybe-highlight)) - "Controls how the article buffer will look. - -If you leave the list empty, the article will appear exactly as it is -stored on the disk. The list entries will hide or highlight various -parts of the article, making it easier to find the information you -want." - :group 'gnus-article-highlight - :group 'gnus-visual - :type 'hook - :options '(gnus-article-add-buttons - gnus-article-add-buttons-to-head - gnus-article-emphasize - gnus-article-fill-cited-article - gnus-article-remove-cr - gnus-article-de-quoted-unreadable - gnus-summary-stop-page-breaking - ;; gnus-summary-caesar-message - ;; gnus-summary-verbose-headers - gnus-summary-toggle-mime - gnus-article-hide - gnus-article-hide-headers - gnus-article-hide-boring-headers - gnus-article-hide-signature - gnus-article-hide-citation - gnus-article-hide-pgp - gnus-article-hide-pem - gnus-article-highlight - gnus-article-highlight-headers - gnus-article-highlight-citation - gnus-article-highlight-signature - gnus-article-date-ut - gnus-article-date-local - gnus-article-date-lapsed - gnus-article-date-original - gnus-article-remove-trailing-blank-lines - gnus-article-strip-leading-blank-lines - gnus-article-strip-multiple-blank-lines - gnus-article-strip-blank-lines - gnus-article-treat-overstrike - gnus-article-display-x-face - gnus-smiley-display)) - (defcustom gnus-article-save-directory gnus-directory "*Name of the directory articles will be saved in (default \"~/News\")." :group 'gnus-article-saving @@ -1366,12 +1419,31 @@ want." (defvar gnus-plugged t "Whether Gnus is plugged or not.") +(defcustom gnus-default-charset 'iso-8859-1 + "Default charset assumed to be used when viewing non-ASCII characters. +This variable is overridden on a group-to-group basis by the +gnus-group-charset-alist variable and is only used on groups not +covered by that variable." + :type 'symbol + :group 'gnus-charset) + +(defcustom gnus-default-posting-charset nil + "Default charset assumed to be used when posting non-ASCII characters. +This variable is overridden on a group-to-group basis by the +gnus-group-posting-charset-alist variable and is only used on groups not +covered by that variable. +If nil, no default charset is assumed when posting." + :type 'symbol + :group 'gnus-charset) + ;;; Internal variables +(defvar gnus-agent-meta-information-header "X-Gnus-Agent-Meta-Information") (defvar gnus-group-get-parameter-function 'gnus-group-get-parameter) (defvar gnus-original-article-buffer " *Original Article*") (defvar gnus-newsgroup-name nil) +(defvar gnus-ephemeral-servers nil) (defvar gnus-agent nil "Whether we want to use the Gnus agent or not.") @@ -1390,7 +1462,6 @@ want." ;; Variable holding the user answers to all method prompts. (defvar gnus-method-history nil) -(defvar gnus-group-history nil) ;; Variable holding the user answers to all mail method prompts. (defvar gnus-mail-method-history nil) @@ -1401,15 +1472,22 @@ want." (defvar gnus-server-alist nil "List of available servers.") +(defcustom gnus-cache-directory + (nnheader-concat gnus-directory "cache/") + "*The directory where cached articles will be stored." + :group 'gnus-cache + :type 'directory) + (defvar gnus-predefined-server-alist `(("cache" - (nnspool "cache" - (nnspool-spool-directory "~/News/cache/") - (nnspool-nov-directory "~/News/cache/") - (nnspool-active-file "~/News/cache/active")))) + nnspool "cache" + (nnspool-spool-directory ,gnus-cache-directory) + (nnspool-nov-directory ,gnus-cache-directory) + (nnspool-active-file + ,(nnheader-concat gnus-cache-directory "active")))) "List of predefined (convenience) servers.") -(defvar gnus-topic-indentation "") ;; Obsolete variable. +(defvar gnus-topic-indentation "");; Obsolete variable. (defconst gnus-article-mark-lists '((marked . tick) (replied . reply) @@ -1437,7 +1515,6 @@ want." '((gnus-group-mode "(gnus)The Group Buffer") (gnus-summary-mode "(gnus)The Summary Buffer") (gnus-article-mode "(gnus)The Article Buffer") - (mime/viewer-mode "(gnus)The Article Buffer") (gnus-server-mode "(gnus)The Server Buffer") (gnus-browse-mode "(gnus)Browse Foreign Server") (gnus-tree-mode "(gnus)Tree Display")) @@ -1448,9 +1525,6 @@ want." (defvar gnus-article-buffer "*Article*") (defvar gnus-server-buffer "*Server*") -(defvar gnus-buffer-list nil - "Gnus buffers that should be killed on exit.") - (defvar gnus-slave nil "Whether this Gnus is a slave or not.") @@ -1526,19 +1600,20 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") (cdr package))))) '(("metamail" metamail-buffer) ("info" Info-goto-node) - ("hexl" hexl-hex-string-to-integer) ("pp" pp pp-to-string pp-eval-expression) + ("qp" quoted-printable-decode-region quoted-printable-decode-string) ("ps-print" ps-print-preprint) ("mail-extr" mail-extract-address-components) + ("browse-url" browse-url) ("message" :interactive t message-send-and-exit message-yank-original) - ("nnmail" nnmail-split-fancy nnmail-article-group nnmail-date-to-time) + ("babel" babel-as-string) + ("nnmail" nnmail-split-fancy nnmail-article-group) ("nnvirtual" nnvirtual-catchup-group nnvirtual-convert-headers) - ("timezone" timezone-make-date-arpa-standard timezone-fix-time - timezone-make-sortable-date timezone-make-time-string) - ("rmailout" rmail-output) + ("rmailout" rmail-output rmail-output-to-rmail-file) ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages - rmail-show-message) + rmail-show-message rmail-summary-exists + rmail-select-summary rmail-update-summary) ("gnus-audio" :interactive t gnus-audio-play) ("gnus-xmas" gnus-xmas-splash) ("gnus-soup" :interactive t @@ -1568,7 +1643,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") gnus-article-hide-citation-in-followups) ("gnus-kill" gnus-kill gnus-apply-kill-file-internal gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author - gnus-execute gnus-expunge) + gnus-execute gnus-expunge gnus-batch-kill gnus-batch-score) ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers gnus-cache-possibly-remove-articles gnus-cache-request-article gnus-cache-retrieve-headers gnus-cache-possibly-alter-active @@ -1605,8 +1680,9 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") gnus-uu-decode-binhex gnus-uu-decode-uu-view gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view - gnus-uu-decode-binhex-view) - ("gnus-uu" gnus-uu-delete-work-dir gnus-quote-arg-for-sh-or-csh) + gnus-uu-decode-binhex-view gnus-uu-unmark-thread + gnus-uu-mark-over gnus-uu-post-news) + ("gnus-uu" gnus-uu-delete-work-dir gnus-uu-unmark-thread) ("gnus-msg" (gnus-summary-send-map keymap) gnus-article-mail gnus-copy-article-buffer gnus-extended-version) ("gnus-msg" :interactive t @@ -1616,10 +1692,15 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") gnus-post-news gnus-summary-reply gnus-summary-reply-with-original gnus-summary-mail-forward gnus-summary-mail-other-window gnus-summary-resend-message gnus-summary-resend-bounced-mail - gnus-bug) + gnus-summary-wide-reply gnus-summary-followup-to-mail + gnus-summary-followup-to-mail-with-original gnus-bug + gnus-summary-wide-reply-with-original + gnus-summary-post-forward gnus-summary-wide-reply-with-original + gnus-summary-post-forward) ("gnus-picon" :interactive t gnus-article-display-picons gnus-group-display-picons gnus-picons-article-display-x-face gnus-picons-display-x-face) + ("gnus-picon" gnus-picons-buffer-name) ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p gnus-grouplens-mode) ("smiley" :interactive t gnus-smiley-display) @@ -1627,12 +1708,15 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group gnus-list-of-unread-articles gnus-list-of-read-articles gnus-offer-save-summaries gnus-make-thread-indent-array - gnus-summary-exit gnus-update-read-articles) + gnus-summary-exit gnus-update-read-articles gnus-summary-last-subject + gnus-summary-skip-intangible gnus-summary-article-number + gnus-data-header gnus-data-find) ("gnus-group" gnus-group-insert-group-line gnus-group-quit gnus-group-list-groups gnus-group-first-unread-group gnus-group-set-mode-line gnus-group-set-info gnus-group-save-newsrc gnus-group-setup-buffer gnus-group-get-new-news - gnus-group-make-help-group gnus-group-update-group) + gnus-group-make-help-group gnus-group-update-group + gnus-group-iterate gnus-group-group-name) ("gnus-bcklg" gnus-backlog-request-article gnus-backlog-enter-article gnus-backlog-remove-article) ("gnus-art" gnus-article-read-summary-keys gnus-article-save @@ -1640,23 +1724,24 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") gnus-article-next-page gnus-article-prev-page gnus-request-article-this-buffer gnus-article-mode gnus-article-setup-buffer gnus-narrow-to-page - gnus-article-delete-invisible-text gnus-hack-decode-rfc1522) + gnus-article-delete-invisible-text gnus-treat-article) ("gnus-art" :interactive t gnus-article-hide-headers gnus-article-hide-boring-headers - gnus-article-treat-overstrike gnus-article-word-wrap + gnus-article-treat-overstrike gnus-article-remove-cr gnus-article-remove-trailing-blank-lines gnus-article-display-x-face gnus-article-de-quoted-unreadable - gnus-article-mime-decode-quoted-printable gnus-article-hide-pgp + gnus-article-hide-pgp gnus-article-hide-pem gnus-article-hide-signature gnus-article-strip-leading-blank-lines gnus-article-date-local gnus-article-date-original gnus-article-date-lapsed gnus-article-show-all-headers gnus-article-edit-mode gnus-article-edit-article - gnus-article-edit-done gnus-decode-rfc1522 article-decode-rfc1522 - gnus-start-date-timer gnus-stop-date-timer) + gnus-article-edit-done gnus-article-decode-encoded-words + gnus-start-date-timer gnus-stop-date-timer + gnus-mime-view-all-parts) ("gnus-int" gnus-request-type) ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1 - gnus-dribble-enter gnus-read-init-file) + gnus-dribble-enter gnus-read-init-file gnus-dribble-touch) ("gnus-dup" gnus-dup-suppress-articles gnus-dup-unsuppress-article gnus-dup-enter-articles) ("gnus-range" gnus-copy-sequence) @@ -1670,17 +1755,21 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.") gnus-async-halt-prefetch) ("gnus-agent" gnus-open-agent gnus-agent-get-function gnus-agent-save-groups gnus-agent-save-active gnus-agent-method-p - gnus-agent-get-undownloaded-list gnus-agent-fetch-session) + gnus-agent-get-undownloaded-list gnus-agent-fetch-session + gnus-summary-set-agent-mark gnus-agent-save-group-info) ("gnus-agent" :interactive t gnus-unplugged gnus-agentize gnus-agent-batch) ("gnus-vm" :interactive t gnus-summary-save-in-vm gnus-summary-save-article-vm) - ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-drafts)))) + ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-drafts) + ("gnus-mlspl" gnus-group-split gnus-group-split-fancy) + ("gnus-mlspl" :interactive t gnus-group-split-setup + gnus-group-split-update)))) ;;; gnus-sum.el thingies -(defcustom gnus-summary-line-format "%U\%R\%z\%I\%(%[%4L: %-20,20n%]%) %s\n" +(defcustom gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n" "*The format specification of the lines in the summary buffer. It works along the same lines as a normal formatting string, @@ -1693,6 +1782,7 @@ with some simple extensions. %a Extracted name of the poster (string) %A Extracted address of the poster (string) %F Contents of the From: header (string) +%f Contents of the From: or To: headers (string) %x Contents of the Xref: header (string) %D Date of the article (string) %d Date of the article (string) in DD-MMM format @@ -1731,7 +1821,7 @@ such area. The %U (status), %R (replied) and %z (zcore) specs have to be handled with care. For reasons of efficiency, Gnus will compute what column these characters will end up in, and \"hard-code\" that. This means that -it is illegal to have these specs after a variable-length spec. Well, +it is invalid to have these specs after a variable-length spec. Well, you might not be arrested, but your summary buffer will look strange, which is bad enough. @@ -1753,7 +1843,7 @@ This restriction may disappear in later versions of Gnus." (define-key keymap (pop keys) 'undefined)))) (defvar gnus-article-mode-map - (let ((keymap (make-keymap))) + (let ((keymap (make-sparse-keymap))) (gnus-suppress-keymap keymap) keymap)) (defvar gnus-summary-mode-map @@ -1803,14 +1893,6 @@ This restriction may disappear in later versions of Gnus." "Set GROUP's active info." `(gnus-sethash ,group ,active gnus-active-hashtb)) -(defun gnus-alive-p () - "Say whether Gnus is running or not." - (and gnus-group-buffer - (get-buffer gnus-group-buffer) - (save-excursion - (set-buffer gnus-group-buffer) - (eq major-mode 'gnus-group-mode)))) - ;; Info access macros. (defmacro gnus-info-group (info) @@ -1915,6 +1997,7 @@ This restriction may disappear in later versions of Gnus." ;;; Gnus Utility Functions ;;; + (defmacro gnus-string-or (&rest strings) "Return the first element of STRINGS that is a non-blank string. STRINGS will be evaluated in normal `or' order." @@ -1929,52 +2012,39 @@ STRINGS will be evaluated in normal `or' order." (setq strings nil))) string)) -;; Add the current buffer to the list of buffers to be killed on exit. -(defun gnus-add-current-to-buffer-list () - (or (memq (current-buffer) gnus-buffer-list) - (push (current-buffer) gnus-buffer-list))) - (defun gnus-version (&optional arg) "Version number of this version of Gnus. If ARG, insert string at point." (interactive "P") - (let ((methods gnus-valid-select-methods) - (mess gnus-version) - meth) - ;; Go through all the legal select methods and add their version - ;; numbers to the total version string. Only the backends that are - ;; currently in use will have their message numbers taken into - ;; consideration. - (while methods - (setq meth (intern (concat (caar methods) "-version"))) - (and (boundp meth) - (stringp (symbol-value meth)) - (setq mess (concat mess "; " (symbol-value meth)))) - (setq methods (cdr methods))) - (if arg - (insert (message mess)) - (message mess)))) + (if arg + (insert (message gnus-version)) + (message gnus-version))) (defun gnus-continuum-version (version) "Return VERSION as a floating point number." (when (or (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version) (string-match "^\\(.?\\)gnus-\\([0-9.]+\\)$" version)) - (let* ((alpha (and (match-beginning 1) (match-string 1 version))) - (number (match-string 2 version)) - major minor least) - (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number) - (setq major (string-to-number (match-string 1 number))) - (setq minor (string-to-number (match-string 2 number))) - (setq least (if (match-beginning 3) + (let ((alpha (and (match-beginning 1) (match-string 1 version))) + (number (match-string 2 version)) + major minor least) + (unless (string-match + "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number) + (error "Invalid version string: %s" version)) + (setq major (string-to-number (match-string 1 number)) + minor (string-to-number (match-string 2 number)) + least (if (match-beginning 3) (string-to-number (match-string 3 number)) 0)) (string-to-number (if (zerop major) (format "%s00%02d%02d" - (cond - ((member alpha '("(ding)" "d")) "4.99") - ((member alpha '("September" "s")) "5.01") - ((member alpha '("Red" "r")) "5.03")) + (if (member alpha '("(ding)" "d")) + "4.99" + (+ 5 (* 0.02 + (abs + (- (mm-char-int (aref (downcase alpha) 0)) + (mm-char-int ?t)))) + -0.01)) minor least) (format "%d.%02d%02d" major minor least)))))) @@ -2017,7 +2087,7 @@ g -- Group name." (setq prompt (match-string 1 string))) (setq i (match-end 0)) ;; We basically emulate just about everything that - ;; `interactive' does, but adds the "g" and "G" specs. + ;; `interactive' does, but add the specs listed above. (push (cond ((= c ?a) @@ -2074,11 +2144,13 @@ g -- Group name." ((= c ?g) (gnus-group-group-name)) ((= c ?A) - (gnus-summary-article-number)) + (gnus-summary-skip-intangible) + (or (get-text-property (point) 'gnus-number) + (gnus-summary-last-subject))) ((= c ?H) - (gnus-summary-article-header)) + (gnus-data-header (gnus-data-find (gnus-summary-article-number)))) (t - (error "Not implemented spec"))) + (error "Non-implemented spec"))) out) (cond ((= c ?r) @@ -2156,7 +2228,14 @@ that that variable is buffer-local to the summary buffers." "Return non-nil if GROUP (and ARTICLE) come from a news server." (or (gnus-member-of-valid 'post group) ; Ordinary news group. (and (gnus-member-of-valid 'post-mail group) ; Combined group. - (eq (gnus-request-type group article) 'news)))) + (if (or (null article) + (not (< article 0))) + (eq (gnus-request-type group article) 'news) + (if (not (vectorp article)) + nil + ;; It's a real article. + (eq (gnus-request-type group (mail-header-id article)) + 'news)))))) ;; Returns a list of writable groups. (defun gnus-writable-groups () @@ -2187,11 +2266,11 @@ that that variable is buffer-local to the summary buffers." (defun gnus-ephemeral-group-p (group) "Say whether GROUP is ephemeral or not." - (gnus-group-get-parameter group 'quit-config)) + (gnus-group-get-parameter group 'quit-config t)) (defun gnus-group-quit-config (group) "Return the quit-config of GROUP." - (gnus-group-get-parameter group 'quit-config)) + (gnus-group-get-parameter group 'quit-config t)) (defun gnus-kill-ephemeral-group (group) "Remove ephemeral GROUP from relevant structures." @@ -2225,9 +2304,11 @@ that that variable is buffer-local to the summary buffers." (gnus-server-to-method method)) ((equal method gnus-select-method) gnus-select-method) - ((and (stringp (car method)) group) + ((and (stringp (car method)) + group) (gnus-server-extend-method group method)) - ((and method (not group) + ((and method + (not group) (equal (cadr method) "")) method) (t @@ -2251,7 +2332,14 @@ that that variable is buffer-local to the summary buffers." (not (equal server (format "%s:%s" (caaar opened) (cadaar opened))))) (pop opened)) - (caar opened)))) + (caar opened)) + ;; It could be a named method, search all servers + (let ((servers gnus-secondary-select-methods)) + (while (and servers + (not (equal server (format "%s:%s" (caar servers) + (cadar servers))))) + (pop servers)) + (car servers)))) (defmacro gnus-method-equal (ss1 ss2) "Say whether two servers are equal." @@ -2264,6 +2352,15 @@ that that variable is buffer-local to the summary buffers." (setq s1 (cdr s1))) (null s1)))))) +(defun gnus-methods-equal-p (m1 m2) + (let ((m1 (or m1 gnus-select-method)) + (m2 (or m2 gnus-select-method))) + (or (equal m1 m2) + (and (eq (car m1) (car m2)) + (or (not (memq 'address (assoc (symbol-name (car m1)) + gnus-valid-select-methods))) + (equal (nth 1 m1) (nth 1 m2))))))) + (defun gnus-server-equal (m1 m2) "Say whether two methods are equal." (let ((m1 (cond ((null m1) gnus-select-method) @@ -2345,16 +2442,32 @@ You should probably use `gnus-find-method-for-group' instead." possible (list backend server)))))) +(defsubst gnus-native-method-p (method) + "Return whether METHOD is the native select method." + (gnus-method-equal method gnus-select-method)) + (defsubst gnus-secondary-method-p (method) "Return whether METHOD is a secondary select method." (let ((methods gnus-secondary-select-methods) (gmethod (gnus-server-get-method nil method))) (while (and methods - (not (equal (gnus-server-get-method nil (car methods)) - gmethod))) + (not (gnus-method-equal + (gnus-server-get-method nil (car methods)) + gmethod))) (setq methods (cdr methods))) methods)) +(defun gnus-method-simplify (method) + "Return the shortest uniquely identifying string or method for METHOD." + (cond ((stringp method) + method) + ((gnus-native-method-p method) + nil) + ((gnus-secondary-method-p method) + (format "%s:%s" (nth 0 method) (nth 1 method))) + (t + method))) + (defun gnus-groups-from-server (server) "Return a list of all groups that are fetched from SERVER." (let ((alist (cdr gnus-newsrc-alist)) @@ -2377,28 +2490,41 @@ You should probably use `gnus-find-method-for-group' instead." "Say whether the group is secondary or not." (gnus-secondary-method-p (gnus-find-method-for-group group))) -(defun gnus-group-find-parameter (group &optional symbol) +(defun gnus-group-find-parameter (group &optional symbol allow-list) "Return the group parameters for GROUP. If SYMBOL, return the value of that symbol in the group parameters." (save-excursion (set-buffer gnus-group-buffer) (let ((parameters (funcall gnus-group-get-parameter-function group))) (if symbol - (gnus-group-parameter-value parameters symbol) + (gnus-group-parameter-value parameters symbol allow-list) parameters)))) -(defun gnus-group-get-parameter (group &optional symbol) +(defun gnus-group-get-parameter (group &optional symbol allow-list) "Return the group parameters for GROUP. -If SYMBOL, return the value of that symbol in the group parameters." +If SYMBOL, return the value of that symbol in the group parameters. +Most functions should use `gnus-group-find-parameter', which +also examines the topic parameters." (let ((params (gnus-info-params (gnus-get-info group)))) (if symbol - (gnus-group-parameter-value params symbol) + (gnus-group-parameter-value params symbol allow-list) params))) -(defun gnus-group-parameter-value (params symbol) +(defun gnus-group-parameter-value (params symbol &optional allow-list) "Return the value of SYMBOL in group PARAMS." - (or (car (memq symbol params)) ; It's either a simple symbol - (cdr (assq symbol params)))) ; or a cons. + ;; We only wish to return group parameters (dotted lists) and + ;; not local variables, which may have the same names. + ;; But first we handle single elements... + (or (car (memq symbol params)) + ;; Handle alist. + (let (elem) + (catch 'found + (while (setq elem (pop params)) + (when (and (consp elem) + (eq (car elem) symbol) + (or allow-list + (atom (cdr elem)))) + (throw 'found (cdr elem)))))))) (defun gnus-group-add-parameter (group param) "Add parameter PARAM to GROUP." @@ -2431,7 +2557,7 @@ If SYMBOL, return the value of that symbol in the group parameters." (when params (setq params (delq name params)) (while (assq name params) - (setq params (delq (assq name params) params))) + (gnus-pull name params)) (gnus-info-set-params info params)))))) (defun gnus-group-add-score (group &optional score) @@ -2441,48 +2567,47 @@ If SCORE is nil, add 1 to the score of GROUP." (when info (gnus-info-set-score info (+ (gnus-info-score info) (or score 1)))))) -;; Function written by Stainless Steel Rat (defun gnus-short-group-name (group &optional levels) "Collapse GROUP name LEVELS. Select methods are stripped and any remote host name is stripped down to just the host name." - (let* ((name "") (foreign "") (depth -1) (skip 1) + (let* ((name "") + (foreign "") + (depth 0) + (skip 1) (levels (or levels + gnus-group-uncollapsed-levels (progn (while (string-match "\\." group skip) (setq skip (match-end 0) depth (+ depth 1))) depth)))) - ;; separate foreign select method from group name and collapse. - ;; if method contains a server, collapse to non-domain server name, - ;; otherwise collapse to select method - (when (string-match ":" group) - (cond ((string-match "+" group) - (let* ((plus (string-match "+" group)) - (colon (string-match ":" group (or plus 0))) - (dot (string-match "\\." group))) - (setq foreign (concat - (substring group (+ 1 plus) - (cond ((null dot) colon) - ((< colon dot) colon) - ((< dot colon) dot))) - ":") - group (substring group (+ 1 colon))))) - (t - (let* ((colon (string-match ":" group))) - (setq foreign (concat (substring group 0 (+ 1 colon))) - group (substring group (+ 1 colon))))))) - ;; collapse group name leaving LEVELS uncollapsed elements - (while group - (if (and (string-match "\\." group) (> levels 0)) - (setq name (concat name (substring group 0 1)) - group (substring group (match-end 0)) - levels (- levels 1) - name (concat name ".")) - (setq name (concat foreign name group) - group nil))) - name)) - + ;; Separate foreign select method from group name and collapse. + ;; If method contains a server, collapse to non-domain server name, + ;; otherwise collapse to select method. + (let* ((colon (string-match ":" group)) + (server (and colon (substring group 0 colon))) + (plus (and server (string-match "+" server)))) + (when server + (if plus + (setq foreign (substring server (+ 1 plus) + (string-match "\\." server)) + group (substring group (+ 1 colon))) + (setq foreign server + group (substring group (+ 1 colon)))) + (setq foreign (concat foreign ":"))) + ;; Collapse group name leaving LEVELS uncollapsed elements + (let* ((glist (split-string group "\\.")) + (glen (length glist)) + res) + (setq levels (- glen levels)) + (dolist (g glist) + (push (if (>= (decf levels) 0) + (substring g 0 1) + g) + res)) + (concat foreign (mapconcat 'identity (nreverse res) ".")))))) + (defun gnus-narrow-to-body () "Narrow to the body of an article." (narrow-to-region @@ -2559,6 +2684,7 @@ If NEWSGROUP is nil, return the global kill file name instead." (let ((opened gnus-opened-servers)) (while (and method opened) (when (and (equal (cadr method) (cadaar opened)) + (equal (car method) (caaar opened)) (not (equal method (caar opened)))) (setq method nil)) (pop opened)) @@ -2627,7 +2753,7 @@ If NEWSGROUP is nil, return the global kill file name instead." (defun gnus-read-group (prompt &optional default) "Prompt the user for a group name. -Disallow illegal group names." +Disallow invalid group names." (let ((prefix "") group) (while (not group) @@ -2636,18 +2762,21 @@ Disallow illegal group names." (setq group (read-string (concat prefix prompt) (cons (or default "") 0) 'gnus-group-history))) - (setq prefix (format "Illegal group name: \"%s\". " group) + (setq prefix (format "Invalid group name: \"%s\". " group) group nil))) group)) (defun gnus-read-method (prompt) "Prompt the user for a method. Allow completion over sensible values." - (let ((method - (completing-read - prompt (append gnus-valid-select-methods gnus-predefined-server-alist - gnus-server-alist) - nil t nil 'gnus-method-history))) + (let* ((servers + (append gnus-valid-select-methods + gnus-predefined-server-alist + gnus-server-alist)) + (method + (completing-read + prompt servers + nil t nil 'gnus-method-history))) (cond ((equal method "") (setq method gnus-select-method)) @@ -2657,7 +2786,7 @@ Allow completion over sensible values." (assoc method gnus-valid-select-methods)) (read-string "Address: ") ""))) - ((assoc method gnus-server-alist) + ((assoc method servers) method) (t (list (intern method) ""))))) @@ -2666,7 +2795,7 @@ Allow completion over sensible values." ;;;###autoload (defun gnus-slave-no-server (&optional arg) - "Read network news as a slave, without connecting to local server" + "Read network news as a slave, without connecting to local server." (interactive "P") (gnus-no-server arg t)) @@ -2694,8 +2823,6 @@ As opposed to `gnus', this command will not connect to the local server." (let ((window (get-buffer-window gnus-group-buffer))) (cond (window (select-frame (window-frame window))) - ((= (length (frame-list)) 1) - (select-frame (make-frame))) (t (other-frame 1)))) (gnus arg))