Merge branch 'master' of https://git.gnus.org/gnus
[gnus] / lisp / gnus-registry.el
index 93ee0ef..e3af088 100644 (file)
@@ -1,27 +1,25 @@
 ;;; gnus-registry.el --- article registry for Gnus
 
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 
+;;; Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
-;; Keywords: news
+;; Keywords: news registry
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -62,6 +60,7 @@
 (require 'gnus-sum)
 (require 'gnus-util)
 (require 'nnmail)
+(require 'easymenu)
 
 (defvar gnus-adaptive-word-syntax-table)
 
@@ -139,6 +138,10 @@ references.'"
                 (const :tag "Always Install" t)
                 (const :tag "Ask Me" ask)))
 
+(defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning.
+
+(defvar gnus-registry-misc-menus nil)  ; ugly way to keep the menus
+
 (defcustom gnus-registry-clean-empty t
   "Whether the empty registry entries should be deleted.
 Registry entries are considered empty when they have no groups
@@ -146,11 +149,17 @@ and no extra data."
   :group 'gnus-registry
   :type 'boolean)
 
-(defcustom gnus-registry-use-long-group-names nil
-  "Whether the registry should use long group names (BUGGY)."
+(defcustom gnus-registry-use-long-group-names t
+  "Whether the registry should use long group names."
   :group 'gnus-registry
   :type 'boolean)
 
+(defcustom gnus-registry-max-track-groups 20
+  "The maximum number of non-unique group matches to check for a message ID."
+  :group 'gnus-registry
+  :type '(radio (const :format "Unlimited " nil)
+               (integer :format "Maximum non-unique matches: %v")))
+
 (defcustom gnus-registry-track-extra nil
   "Whether the registry should track extra data about a message.
 The Subject and Sender (From:) headers are currently tracked this
@@ -260,9 +269,7 @@ considered precious) will not be trimmed."
                             (if (and (eq system-type 'ms-dos)
                                      (not (gnus-long-file-names)))
                                 "%s#%d.tm#" ; MSDOS limits files to 8+3
-                              (if (memq system-type '(vax-vms axp-vms))
-                                  "%s$tmp$%d"
-                                "%s#tmp#%d"))
+                              "%s#tmp#%d")
                             working-dir (setq i (1+ i))))
                      (file-exists-p working-file)))
 
@@ -510,7 +517,9 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
         9
         "%s is looking for matches for reference %s from [%s]"
         log-agent reference refstr)
-       (dolist (group (gnus-registry-fetch-groups reference))
+       (dolist (group (gnus-registry-fetch-groups 
+                       reference 
+                       gnus-registry-max-track-groups))
          (when (and group (gnus-registry-follow-group-p group))
            (gnus-message
             7
@@ -523,8 +532,10 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
                   "references" refstr found found)))
      
      ;; else: there were no matches, now try the extra tracking by sender
-     ((and (gnus-registry-track-sender-p) 
-          sender)
+     ((and (gnus-registry-track-sender-p)
+          sender
+          (not (equal (gnus-extract-address-component-email sender)
+                      user-mail-address)))
       (maphash
        (lambda (key value)
         (let ((this-sender (cdr
@@ -532,7 +543,9 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
               matches)
           (when (and this-sender
                      (equal sender this-sender))
-            (let ((groups (gnus-registry-fetch-groups key)))
+            (let ((groups (gnus-registry-fetch-groups 
+                           key
+                           gnus-registry-max-track-groups)))
               (dolist (group groups)
                 (push group found-full)
                 (setq found (append (list group) (delete group found)))))
@@ -559,7 +572,9 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
               matches)
           (when (and this-subject
                      (equal subject this-subject))
-            (let ((groups (gnus-registry-fetch-groups key)))
+            (let ((groups (gnus-registry-fetch-groups 
+                           key
+                           gnus-registry-max-track-groups)))
               (dolist (group groups)
                 (push group found-full)
                 (setq found (append (list group) (delete group found)))))
@@ -646,10 +661,10 @@ necessary."
   "Determines if a group name should be followed.
 Consults `gnus-registry-unfollowed-groups' and
 `nnmail-split-fancy-with-parent-ignore-groups'."
-  (not (or (gnus-registry-grep-in-list
+  (not (or (gnus-grep-in-list
            group
            gnus-registry-unfollowed-groups)
-          (gnus-registry-grep-in-list
+          (gnus-grep-in-list
            group
            nnmail-split-fancy-with-parent-ignore-groups))))
 
@@ -679,9 +694,8 @@ Consults `gnus-registry-unfollowed-groups' and
   (let (articles)
     (maphash
      (lambda (key value)
-       (when (gnus-registry-grep-in-list
-             keyword
-             (cdr (gnus-registry-fetch-extra key 'keywords)))
+       (when (member keyword
+                  (cdr-safe (gnus-registry-fetch-extra key 'keywords)))
         (push key articles)))
      gnus-registry-hashtb)
     articles))
@@ -731,16 +745,6 @@ Consults `gnus-registry-unfollowed-groups' and
                          (assoc article (gnus-data-list nil)))))
     nil))
 
-;;; this should be redone with catch/throw
-(defun gnus-registry-grep-in-list (word list)
-  (when word
-    (memq nil
-         (mapcar 'not
-                 (mapcar
-                  (lambda (x)
-                    (string-match word x))
-                  list)))))
-
 (defun gnus-registry-do-marks (type function)
   "For each known mark, call FUNCTION for each cell of type TYPE.
 
@@ -757,7 +761,8 @@ FUNCTION should take two parameters, a mark symbol and the cell value."
   "Install the keyboard shortcuts and menus for the registry.
 Uses `gnus-registry-marks' to find what shortcuts to install."
   (let (keys-plist)
-    (gnus-registry-do-marks 
+    (setq gnus-registry-misc-menus nil)
+    (gnus-registry-do-marks
      :char
      (lambda (mark data)
        (let ((function-format
@@ -806,19 +811,34 @@ Uses `gnus-registry-marks' to find what shortcuts to install."
                    ;; all this just to get the mark, I must be doing it wrong
                    (intern ,(symbol-name mark))
                    articles ,remove t)
+                  (gnus-message
+                   9 
+                   "Applying mark %s to %d articles"
+                   ,(symbol-name mark) (length articles))
                   (dolist (article articles)
                     (gnus-summary-update-article 
-                     article 
+                     article
                      (assoc article (gnus-data-list nil)))))))
             (push (intern function-name) keys-plist)
-            (push shortcut keys-plist)
-            (gnus-message 
+            (push shortcut keys-plist)      
+            (push (vector (format "%s %s"
+                                  (upcase-initials variant-name)
+                                  (symbol-name mark))
+                          (intern function-name) t)
+                  gnus-registry-misc-menus)
+            (gnus-message
              9 
              "Defined mark handling function %s" 
              function-name))))))
     (gnus-define-keys-1
-     '(gnus-registry-mark-map "M" gnus-summary-mark-map) 
-     keys-plist)))
+     '(gnus-registry-mark-map "M" gnus-summary-mark-map)
+     keys-plist)
+    (add-hook 'gnus-summary-menu-hook
+             (lambda ()
+               (easy-menu-add-item 
+                gnus-summary-misc-menu
+                nil 
+                (cons "Registry Marks" gnus-registry-misc-menus))))))
 
 ;;; use like this:
 ;;; (defalias 'gnus-user-format-function-M 
@@ -1007,8 +1027,8 @@ Returns the first place where the trail finds a group name."
                       crumb
                     (gnus-group-short-name crumb))))))))
 
-(defun gnus-registry-fetch-groups (id)
-  "Get the groups of a message, based on the message ID."
+(defun gnus-registry-fetch-groups (id &optional max)
+  "Get the groups (up to MAX, if given) of a message, based on the message ID."
   (let ((trail (gethash id gnus-registry-hashtb))
        groups)
     (dolist (crumb trail)
@@ -1020,7 +1040,9 @@ Returns the first place where the trail finds a group name."
          (if (or (not (stringp crumb)) gnus-registry-use-long-group-names)
              crumb
            (gnus-group-short-name crumb))
-        groups))))
+        groups))
+       (when (and max (> (length groups) max))
+         (return))))
     ;; return the list of groups
     groups))