* spam.el (spam-use-spamoracle): new variable
[gnus] / lisp / gnus.el
index 47c9829..d4c8063 100644 (file)
 (require 'mm-util)
 (require 'nnheader)
 
-;; Make sure it was the right mm-util.
-(unless (fboundp 'mm-guess-mime-charset)
-  (error "Wrong `mm-util' found in `load-path'.  Make sure the Gnus one is found first."))
-
 (defgroup gnus nil
   "The coffee-brewing, all singing, all dancing, kitchen sink newsreader."
   :group 'news
   :link '(custom-manual "(gnus)Article Caching")
   :group 'gnus)
 
+(defgroup gnus-registry nil
+  "Article Registry."
+  :group 'gnus)
+
 (defgroup gnus-start nil
   "Starting your favorite newsreader."
   :group 'gnus)
@@ -282,10 +282,10 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "0.13"
+(defconst gnus-version-number "5.10.3"
   "Version number for this version of Gnus.")
 
-(defconst gnus-version (format "Oort Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
@@ -319,6 +319,7 @@ be set in `.emacs' instead."
   (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'identity)
+  (defalias 'gnus-assq-delete-all 'assq-delete-all)
   (defalias 'gnus-add-text-properties 'add-text-properties)
   (defalias 'gnus-put-text-property 'put-text-property)
   (defvar gnus-mode-line-image-cache t)
@@ -675,9 +676,9 @@ be set in `.emacs' instead."
 (defface gnus-summary-high-undownloaded-face
    '((((class color)
        (background light))
-      (:bold t :foreground "cyan4" :bold nil))
+      (:bold t :foreground "cyan4"))
      (((class color) (background dark))
-      (:bold t :foreground "LightGray" :bold nil))
+      (:bold t :foreground "LightGray"))
      (t (:inverse-video t :bold t)))
   "Face used for high interest uncached articles.")
 
@@ -767,6 +768,13 @@ be set in `.emacs' instead."
   "Add the current buffer to the list of Gnus buffers."
   (push (current-buffer) gnus-buffers))
 
+(defmacro gnus-kill-buffer (buffer)
+  "Kill BUFFER and remove from the list of Gnus buffers."
+  `(let ((buf ,buffer))
+     (when (gnus-buffer-exists-p buf)
+       (setq gnus-buffers (delete (get-buffer buf) gnus-buffers))
+       (kill-buffer buf))))
+
 (defun gnus-buffers ()
   "Return a list of live Gnus buffers."
   (while (and gnus-buffers
@@ -841,6 +849,7 @@ be set in `.emacs' instead."
     (storm "#666699" "#99ccff")
     (pdino "#9999cc" "#99ccff")
     (purp "#9999cc" "#666699")
+    (no "#000000" "#ff0000")
     (neutral "#b4b4b4" "#878787")
     (september "#bf9900" "#ffcc00"))
   "Color alist used for the Gnus logo.")
@@ -961,7 +970,7 @@ For example:
 (defmacro gnus-define-group-parameter (param &rest rest)
   "Define a group parameter PARAM.
 REST is a plist of following:
-:type               One of `bool', `list' or `nil'.
+:type               One of `bool', `list' or nil.
 :function           The name of the function.
 :function-document  The documentation of the function.
 :parameter-type     The type for customizing the parameter.
@@ -1336,7 +1345,7 @@ newsgroups."
   "*The number of articles which indicates a large newsgroup.
 If the number of articles in a newsgroup is greater than this value,
 confirmation is required for selecting the newsgroup.
-If it is `nil', no confirmation is required."
+If it is nil, no confirmation is required."
   :group 'gnus-group-select
   :type '(choice (const :tag "No limit" nil)
                 integer))
@@ -1478,7 +1487,7 @@ slower."
   :type 'boolean)
 
 (defcustom gnus-shell-command-separator ";"
-  "String used to separate to shell commands."
+  "String used to separate shell commands."
   :group 'gnus-files
   :type 'string)
 
@@ -1576,7 +1585,7 @@ to be desirable; see the manual for further details."
 
 ;; There should be special validation for this.
 (define-widget 'gnus-email-address 'string
-  "An email address")
+  "An email address.")
 
 (gnus-define-group-parameter
  to-address
@@ -1741,9 +1750,29 @@ posting an article."
 
 This number will be prompted as the initial value of the number of
 articles to list when the group is a large newsgroup (see
-`gnus-large-newsgroup').  If it is `nil', the default value is the
+`gnus-large-newsgroup').  If it is nil, the default value is the
 total number of articles in the group.")
 
+;; The Gnus registry's ignored groups
+(gnus-define-group-parameter
+ registry-ignore
+ :type list
+ :function-document
+ "Whether this group should be ignored by the registry."
+ :variable gnus-registry-ignored-groups
+ :variable-default nil
+ :variable-document
+ "*Groups in which the registry should be turned off."
+ :variable-group gnus-registry
+ :variable-type '(repeat
+                 (list
+                  (regexp :tag "Group Name Regular Expression")
+                  (boolean :tag "Ignored")))
+ :parameter-type '(boolean :tag "Group Ignored by the Registry")
+ :parameter-document
+ "Whether the Gnus Registry should ignore this group.")
+
 ;; group parameters for spam processing added by Ted Zlatanov <tzz@lifelogs.com>
 (defcustom gnus-install-group-spam-parameters t
   "*Disable the group parameters for spam detection.  
@@ -1787,32 +1816,35 @@ This only makes sense for mail groups."
                          (choice
                           (variable-item gnus-group-spam-classification-spam)
                           (variable-item gnus-group-spam-classification-ham)
-                          (other :tag "Unclassified" nil))))
+                          (const :tag "Unclassified" nil))))
 
    :parameter-type '(list :tag "Group contents spam/ham classification"
                          (choice :tag "Group contents classification for spam sorting"
                                  (variable-item gnus-group-spam-classification-spam)
                                  (variable-item gnus-group-spam-classification-ham)
-                                 (other :tag "Unclassified" nil)))
+                                 (const :tag "Unclassified" nil)))
    :parameter-document
    "The spam classification (spam, ham, or neither) of this group.
 When a spam group is entered, all unread articles are marked as spam.")
 
   (defvar gnus-group-spam-exit-processor-ifile "ifile"
-    "The ifile summary exit spam processor.
-Only applicable to spam groups.")
+    "The ifile summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-stat "stat"
-    "The spam-stat summary exit spam processor.
-Only applicable to spam groups.")
+    "The spam-stat summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-bogofilter "bogofilter"
-    "The Bogofilter summary exit spam processor.
-Only applicable to spam groups.")
+    "The Bogofilter summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-blacklist "blacklist"
-    "The Blacklist summary exit spam processor.
-Only applicable to spam groups.")
+    "The Blacklist summary exit spam processor.")
+
+  (defvar gnus-group-spam-exit-processor-report-gmane "report-gmane"
+    "The Gmane reporting summary exit spam processor.
+Only applicable to NNTP groups with articles from Gmane.  See spam-report.el")
+
+  (defvar gnus-group-spam-exit-processor-spamoracle "spamoracle-spam"
+    "The spamoracle summary exit spam processor.")
 
   (defvar gnus-group-ham-exit-processor-ifile "ifile-ham"
     "The ifile summary exit ham processor.
@@ -1834,6 +1866,14 @@ Only applicable to non-spam (unclassified and ham) groups.")
     "The BBDB summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
+  (defvar gnus-group-ham-exit-processor-copy "copy"
+    "The ham copy exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-spamoracle "spamoracle-ham"
+    "The spamoracle summary exit ham processor. 
+Only applicable to non-spam (unclassified and ham) groups.")
+
   (gnus-define-group-parameter
    spam-process
    :type list
@@ -1845,11 +1885,15 @@ Only applicable to non-spam (unclassified and ham) groups.")
                                   (variable-item gnus-group-spam-exit-processor-stat)
                                   (variable-item gnus-group-spam-exit-processor-bogofilter)
                                   (variable-item gnus-group-spam-exit-processor-blacklist)
+                                  (variable-item gnus-group-spam-exit-processor-report-gmane)
+                                  (variable-item gnus-group-spam-exit-processor-spamoracle)
                                   (variable-item gnus-group-ham-exit-processor-bogofilter)
                                   (variable-item gnus-group-ham-exit-processor-ifile)
                                   (variable-item gnus-group-ham-exit-processor-stat)
                                   (variable-item gnus-group-ham-exit-processor-whitelist)
-                                  (variable-item gnus-group-ham-exit-processor-BBDB))))
+                                  (variable-item gnus-group-ham-exit-processor-BBDB)
+                                  (variable-item gnus-group-ham-exit-processor-copy)
+                                  (variable-item gnus-group-ham-exit-processor-spamoracle))))
    :function-document
    "Which spam or ham processors will be applied to the GROUP articles at summary exit."
    :variable gnus-spam-process-newsgroups
@@ -1858,8 +1902,7 @@ Only applicable to non-spam (unclassified and ham) groups.")
    "*Groups in which to automatically process spam or ham articles with
 a backend on summary exit.  If non-nil, this should be a list of group
 name regexps that should match all groups in which to do automatic
-spam processing, associated with the appropriate processor.  This only makes sense
-for mail groups."
+spam processing, associated with the appropriate processor."
    :variable-group spam
    :variable-type '(repeat :tag "Spam/Ham Processors" 
                           (list :tag "Spam Summary Exit Processor Choices"
@@ -1869,11 +1912,13 @@ for mail groups."
                                      (variable-item gnus-group-spam-exit-processor-stat)
                                      (variable-item gnus-group-spam-exit-processor-bogofilter)
                                      (variable-item gnus-group-spam-exit-processor-blacklist)
+                                     (variable-item gnus-group-spam-exit-processor-report-gmane)
                                      (variable-item gnus-group-ham-exit-processor-bogofilter)
                                      (variable-item gnus-group-ham-exit-processor-ifile)
                                      (variable-item gnus-group-ham-exit-processor-stat)
                                      (variable-item gnus-group-ham-exit-processor-whitelist)
-                                     (variable-item gnus-group-ham-exit-processor-BBDB))))
+                                     (variable-item gnus-group-ham-exit-processor-BBDB)
+                                     (variable-item gnus-group-ham-exit-processor-copy))))
    :parameter-document
    "Which spam processors will be applied to the spam or ham GROUP articles at summary exit.")
 
@@ -1881,7 +1926,7 @@ for mail groups."
    spam-process-destination
    :parameter-type '(choice :tag "Destination for spam-processed articles at summary exit"
                            (string :tag "Move to a group")
-                           (other :tag "Expire" nil))
+                           (const :tag "Expire" nil))
    :function-document
    "Where spam-processed articles will go at summary exit."
    :variable gnus-spam-process-destinations
@@ -1891,7 +1936,7 @@ for mail groups."
 another group, or expire them (the default).  If non-nil, this should
 be a list of group name regexps that should match all groups in which
 to do spam-processed article moving, associated with the destination
-group or `nil' for explicit expiration.  This only makes sense for
+group or nil for explicit expiration.  This only makes sense for
 mail groups."
    :variable-group spam
    :variable-type '(repeat 
@@ -1901,7 +1946,7 @@ mail groups."
                     (choice 
                      :tag "Destination for spam-processed articles at summary exit"
                      (string :tag "Move to a group")
-                     (other :tag "Expire" nil))))
+                     (const :tag "Expire" nil))))
    :parameter-document
    "Where spam-processed articles will go at summary exit.")
 
@@ -1910,7 +1955,7 @@ mail groups."
    :parameter-type '(choice 
                     :tag "Destination for ham articles at summary exit from a spam group"
                     (string :tag "Move to a group")
-                    (other :tag "Do nothing" nil))
+                    (const :tag "Do nothing" nil))
    :function-document
    "Where ham articles will go at summary exit from a spam group."
    :variable gnus-ham-process-destinations
@@ -1920,7 +1965,7 @@ mail groups."
 another group, or do nothing (the default).  If non-nil, this should
 be a list of group name regexps that should match all groups in which
 to do ham article moving, associated with the destination
-group or `nil' for explicit ignoring.  This only makes sense for
+group or nil for explicit ignoring.  This only makes sense for
 mail groups, and only works in spam groups."
    :variable-group spam
    :variable-type '(repeat 
@@ -1930,9 +1975,52 @@ mail groups, and only works in spam groups."
                     (choice 
                      :tag "Destination for ham articles at summary exit from spam group"
                      (string :tag "Move to a group")
-                     (other :tag "Expire" nil))))
+                     (const :tag "Expire" nil))))
+   :parameter-document
+   "Where ham articles will go at summary exit from a spam group.")
+
+  (gnus-define-group-parameter 
+   ham-marks
+   :type 'list
+   :parameter-type '(list :tag "Ham mark choices"
+                         (set 
+                          (variable-item gnus-del-mark)
+                          (variable-item gnus-read-mark)
+                          (variable-item gnus-killed-mark)
+                          (variable-item gnus-kill-file-mark)
+                          (variable-item gnus-low-score-mark)))
+
    :parameter-document
-   "Where ham articles will go at summary exit from a spam group."))
+   "Marks considered ham (positively not spam).  Such articles will be
+processed as ham (non-spam) on group exit.  When nil, the global
+spam-ham-marks variable takes precedence."
+   :variable-default '((".*" ((gnus-del-mark 
+                              gnus-read-mark
+                              gnus-killed-mark 
+                              gnus-kill-file-mark
+                              gnus-low-score-mark))))
+   :variable-group spam
+   :variable-document
+   "*Groups in which to explicitly set the ham marks to some value.")
+
+  (gnus-define-group-parameter 
+   spam-marks
+   :type 'list
+   :parameter-type '(list :tag "Spam mark choices"
+                         (set 
+                          (variable-item gnus-spam-mark)
+                          (variable-item gnus-killed-mark)
+                          (variable-item gnus-kill-file-mark)
+                          (variable-item gnus-low-score-mark)))
+
+   :parameter-document
+   "Marks considered spam.
+Such articles will be processed as spam on group exit.  When nil, the global
+spam-spam-marks variable takes precedence."
+   :variable-default '((".*" ((gnus-spam-mark))))
+   :variable-group spam
+   :variable-document
+   "*Groups in which to explicitly set the spam marks to some value."))
 
 (defcustom gnus-group-uncollapsed-levels 1
   "Number of group name elements to leave alone when making a short group name."
@@ -2058,23 +2146,29 @@ face."
   "Whether Gnus is plugged or not.")
 
 (defcustom gnus-agent-cache t
-  "Whether Gnus use agent cache.
-You also need to enable `gnus-agent'."
+  "Controls use of the agent cache while plugged.
+When set, Gnus will prefer using the locally stored content rather
+than re-fetching it from the server.  You also need to enable
+`gnus-agent' for this to have any affect."
   :version "21.3"
   :group 'gnus-agent
   :type 'boolean)
 
-(defcustom gnus-default-charset (mm-guess-mime-charset)
+(defcustom gnus-default-charset 'undecided
   "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
+`gnus-group-charset-alist' variable and is only used on groups not
 covered by that variable."
   :type 'symbol
   :group 'gnus-charset)
 
+;; Fixme: Doc reference to agent.
 (defcustom gnus-agent t
   "Whether we want to use the Gnus agent or not.
-Putting (gnus-agentize) in ~/.gnus is obsolete by (setq gnus-agent t)."
+
+You may customize gnus-agent to disable its use.  However, some
+backends have started to use the agent as a client-side cache.
+Disabling the agent may result in noticable loss of performance."
   :version "21.3"
   :group 'gnus-agent
   :type 'boolean)
@@ -2089,7 +2183,7 @@ Putting (gnus-agentize) in ~/.gnus is obsolete by (setq gnus-agent t)."
 
 (defcustom gnus-other-frame-parameters nil
   "Frame parameters used by `gnus-other-frame' to create a Gnus frame.
-This should be an alist for FSF Emacs, or a plist for XEmacs."
+This should be an alist for Emacs, or a plist for XEmacs."
   :group 'gnus-start
   :type (if (featurep 'xemacs)
            '(repeat (list :inline t :format "%v"
@@ -2104,6 +2198,7 @@ This should be an alist for FSF Emacs, or a plist for XEmacs."
 
 (defvar gnus-agent-gcc-header "X-Gnus-Agent-Gcc")
 (defvar gnus-agent-meta-information-header "X-Gnus-Agent-Meta-Information")
+(defvar gnus-agent-target-move-group-header "X-Gnus-Agent-Move-To")
 (defvar gnus-draft-meta-information-header "X-Draft-From")
 (defvar gnus-group-get-parameter-function 'gnus-group-get-parameter)
 (defvar gnus-original-article-buffer " *Original Article*")
@@ -2233,6 +2328,10 @@ such as a mark that says whether an article is stored in the cache
   "Assoc list of read articles.
 gnus-newsrc-hashtb should be kept so that both hold the same information.")
 
+(defvar gnus-registry-alist nil
+  "Assoc list of registry data.
+gnus-registry.el will populate this if it's loaded.")
+
 (defvar gnus-newsrc-hashtb nil
   "Hashtable of gnus-newsrc-alist.")
 
@@ -2430,7 +2529,6 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-decode-HZ
       gnus-article-wash-html
       gnus-article-unsplit-urls
-      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
@@ -3112,21 +3210,57 @@ that that variable is buffer-local to the summary buffers."
 (defsubst gnus-method-to-full-server-name (method)
   (format "%s+%s" (car method) (nth 1 method)))
 
-(defun gnus-group-prefixed-name (group method)
-  "Return the whole name from GROUP and METHOD."
-  (and (stringp method) (setq method (gnus-server-to-method method)))
+(defun gnus-group-prefixed-name (group method &optional full)
+  "Return the whole name from GROUP and METHOD.
+Call with full set to get the fully qualified group name (even if the
+server is native)."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (if (or (not method)
-         (gnus-server-equal method "native")
-         (string-match ":" group))
+         (and (not full) (gnus-server-equal method "native"))
+         ;;;!!! This might not be right.  We'll see...
+         ;(string-match ":" group)
+         )
       group
     (concat (gnus-method-to-server-name method) ":" group)))
 
+(defun gnus-group-guess-prefixed-name (group)
+  "Guess the whole name from GROUP and METHOD."
+  (gnus-group-prefixed-name group (gnus-find-method-for-group
+                              group)))
+
+(defun gnus-group-full-name (group method)
+  "Return the full name from GROUP and METHOD, even if the method is
+native."
+  (gnus-group-prefixed-name group method t))
+
+(defun gnus-group-guess-full-name (group)
+  "Guess the full name from GROUP, even if the method is native."
+  (if (gnus-group-prefixed-p group)
+      group
+    (gnus-group-full-name group (gnus-find-method-for-group group))))
+
 (defun gnus-group-real-prefix (group)
   "Return the prefix of the current group name."
   (if (string-match "^[^:]+:" group)
       (substring group 0 (match-end 0))
     ""))
 
+(defun gnus-group-short-name (group)
+  "Return the short group name."
+  (let ((prefix (gnus-group-real-prefix group)))
+    (if (< 0 (length prefix))
+       (substring group (length prefix) nil)
+      group)))
+
+(defun gnus-group-prefixed-p (group)
+  "Return the prefix of the current group name."
+  (< 0 (length (gnus-group-real-prefix group))))
+
+(defun gnus-summary-buffer-name (group)
+  "Return the summary buffer name of GROUP."
+  (concat "*Summary " (gnus-group-decoded-name group) "*"))
+
 (defun gnus-group-method (group)
   "Return the server or method used for selecting GROUP.
 You should probably use `gnus-find-method-for-group' instead."
@@ -3692,11 +3826,11 @@ current display is used."
          (switch-to-buffer gnus-group-buffer)
        (funcall gnus-other-frame-function arg)
        (add-hook 'gnus-exit-gnus-hook
-                 (lambda nil
-                   (when (and (frame-live-p gnus-other-frame-object)
-                              (cdr (frame-list)))
-                     (delete-frame gnus-other-frame-object))
-                   (setq gnus-other-frame-object nil)))))))
+                 '(lambda nil
+                    (when (and (frame-live-p gnus-other-frame-object)
+                               (cdr (frame-list)))
+                      (delete-frame gnus-other-frame-object))
+                    (setq gnus-other-frame-object nil)))))))
 
 ;;(setq thing ?                                ; this is a comment
 ;;      more 'yes)