Merge branch 'master' of https://git.gnus.org/gnus
[gnus] / lisp / gnus-kill.el
index be0b37f..5483a74 100644 (file)
@@ -1,16 +1,18 @@
-;;; gnus-kill --- kill commands for Gnus
-;; Copyright (C) 1995 Free Software Foundation, Inc.
+;;; gnus-kill.el --- kill commands for Gnus
+
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; 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 2, 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
 ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 ;;; Code:
 
-(require 'gnus)
-
-(defvar gnus-kill-file-mode-hook nil
-  "*A hook for Gnus kill file mode.")
+(eval-when-compile (require 'cl))
 
-(defvar gnus-kill-expiry-days 7
-  "*Number of days before expiring unused kill file entries.")
-
-(defvar gnus-winconf-kill-file nil)
+(require 'gnus)
+(require 'gnus-art)
+(require 'gnus-range)
+
+(defcustom gnus-kill-file-mode-hook nil
+  "Hook for Gnus kill file mode."
+  :group 'gnus-score-kill
+  :type 'hook)
+
+(defcustom gnus-kill-expiry-days 7
+  "*Number of days before expiring unused kill file entries."
+  :group 'gnus-score-kill
+  :group 'gnus-score-expire
+  :type 'integer)
+
+(defcustom gnus-kill-save-kill-file nil
+  "*If non-nil, will save kill files after processing them."
+  :group 'gnus-score-kill
+  :type 'boolean)
+
+(defcustom gnus-winconf-kill-file nil
+  "What does this do, Lars?
+I don't know, Per."
+  :group 'gnus-score-kill
+  :type 'sexp)
+
+(defcustom gnus-kill-killed t
+  "*If non-nil, Gnus will apply kill files to already killed articles.
+If it is nil, Gnus will never apply kill files to articles that have
+already been through the scoring process, which might very well save lots
+of time."
+  :group 'gnus-score-kill
+  :type 'boolean)
 
 \f
 
 (defmacro gnus-raise (field expression level)
-  (` (gnus-kill (, field) (, expression)
-               (function (gnus-summary-raise-score (, level))) t)))
+  `(gnus-kill ,field ,expression
+             (function (gnus-summary-raise-score ,level)) t))
 
 (defmacro gnus-lower (field expression level)
-  (` (gnus-kill (, field) (, expression)
-               (function (gnus-summary-raise-score (- (, level)))) t)))
+  `(gnus-kill ,field ,expression
+             (function (gnus-summary-raise-score (- ,level))) t))
 
 ;;;
 ;;; Gnus Kill File Mode
 
 (defvar gnus-kill-file-mode-map nil)
 
-(if gnus-kill-file-mode-map
-    nil
-  (setq gnus-kill-file-mode-map (copy-keymap emacs-lisp-mode-map))
-  (define-key gnus-kill-file-mode-map 
-    "\C-c\C-k\C-s" 'gnus-kill-file-kill-by-subject)
-  (define-key gnus-kill-file-mode-map
-    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-author)
-  (define-key gnus-kill-file-mode-map
-    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-thread)
-  (define-key gnus-kill-file-mode-map 
-    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-xref)
-  (define-key gnus-kill-file-mode-map
-    "\C-c\C-a" 'gnus-kill-file-apply-buffer)
-  (define-key gnus-kill-file-mode-map
-    "\C-c\C-e" 'gnus-kill-file-apply-last-sexp)
-  (define-key gnus-kill-file-mode-map 
-    "\C-c\C-c" 'gnus-kill-file-exit))
+(unless gnus-kill-file-mode-map
+  (gnus-define-keymap (setq gnus-kill-file-mode-map
+                           (copy-keymap emacs-lisp-mode-map))
+    "\C-c\C-k\C-s" gnus-kill-file-kill-by-subject
+    "\C-c\C-k\C-a" gnus-kill-file-kill-by-author
+    "\C-c\C-k\C-t" gnus-kill-file-kill-by-thread
+    "\C-c\C-k\C-x" gnus-kill-file-kill-by-xref
+    "\C-c\C-a" gnus-kill-file-apply-buffer
+    "\C-c\C-e" gnus-kill-file-apply-last-sexp
+    "\C-c\C-c" gnus-kill-file-exit))
 
 (defun gnus-kill-file-mode ()
   "Major mode for editing kill files.
@@ -95,12 +115,12 @@ well-known.  For this reason, Gnus provides a general function which
 does this easily for non-Lisp programmers.
 
   The `gnus-kill' function executes commands available in Summary Mode
-by their key sequences. `gnus-kill' should be called with FIELD,
+by their key sequences.  `gnus-kill' should be called with FIELD,
 REGEXP and optional COMMAND and ALL.  FIELD is a string representing
 the header field or an empty string.  If FIELD is an empty string, the
 entire article body is searched for.  REGEXP is a string which is
-compared with FIELD value. COMMAND is a string representing a valid
-key sequence in Summary mode or Lisp expression. COMMAND defaults to
+compared with FIELD value.  COMMAND is a string representing a valid
+key sequence in Summary mode or Lisp expression.  COMMAND defaults to
 '(gnus-summary-mark-as-read nil \"X\").  Make sure that COMMAND is
 executed in the Summary buffer.  If the second optional argument ALL
 is non-nil, the COMMAND is applied to articles which are already
@@ -140,7 +160,7 @@ gnus-kill-file-mode-hook with no arguments, if that value is non-nil."
   (setq major-mode 'gnus-kill-file-mode)
   (setq mode-name "Kill")
   (lisp-mode-variables nil)
-  (run-hooks 'emacs-lisp-mode-hook 'gnus-kill-file-mode-hook))
+  (gnus-run-mode-hooks 'emacs-lisp-mode-hook 'gnus-kill-file-mode-hook))
 
 (defun gnus-kill-file-edit-file (newsgroup)
   "Begin editing a kill file for NEWSGROUP.
@@ -157,11 +177,7 @@ If NEWSGROUP is nil, the global kill file is selected."
       (cond ((get-buffer-window buffer)
             (pop-to-buffer buffer))
            ((eq major-mode 'gnus-group-mode)
-            (gnus-configure-windows '(1 0 0)) ;Take all windows.
-            (pop-to-buffer gnus-group-buffer)
-            ;; Fix by sachs@SLINKY.CS.NYU.EDU (Jay Sachs).
-            (let ((gnus-summary-buffer buffer))
-              (gnus-configure-windows '(1 1 0))) ;Split into two.
+            (gnus-configure-windows 'group) ;Take all windows.
             (pop-to-buffer buffer))
            ((eq major-mode 'gnus-summary-mode)
             (gnus-configure-windows 'article)
@@ -180,58 +196,70 @@ If NEWSGROUP is nil, the global kill file is selected."
     (gnus-kill-file-mode)
     (bury-buffer buffer)))
 
-(defun gnus-kill-file-enter-kill (field regexp)
+(defun gnus-kill-file-enter-kill (field regexp &optional dont-move)
   ;; Enter kill file entry.
   ;; FIELD: String containing the name of the header field to kill.
   ;; REGEXP: The string to kill.
   (save-excursion
     (let (string)
-      (gnus-kill-set-kill-buffer)
-      (goto-char (point-max))
+      (unless (eq major-mode 'gnus-kill-file-mode)
+       (gnus-kill-set-kill-buffer))
+      (unless dont-move
+       (goto-char (point-max)))
       (insert (setq string (format "(gnus-kill %S %S)\n" field regexp)))
       (gnus-kill-file-apply-string string))))
-    
+
 (defun gnus-kill-file-kill-by-subject ()
   "Kill by subject."
   (interactive)
   (gnus-kill-file-enter-kill
-   "Subject" 
-   (regexp-quote 
-    (gnus-simplify-subject (header-subject gnus-current-headers)))))
-  
+   "Subject"
+   (if (vectorp gnus-current-headers)
+       (regexp-quote
+       (gnus-simplify-subject (mail-header-subject gnus-current-headers)))
+     "")
+   t))
+
 (defun gnus-kill-file-kill-by-author ()
   "Kill by author."
   (interactive)
   (gnus-kill-file-enter-kill
-   "From" (regexp-quote (header-from gnus-current-headers))))
+   "From"
+   (if (vectorp gnus-current-headers)
+       (regexp-quote (mail-header-from gnus-current-headers))
+     "") t))
+
 (defun gnus-kill-file-kill-by-thread ()
   "Kill by author."
-  (interactive "p")
+  (interactive)
   (gnus-kill-file-enter-kill
-   "References" (regexp-quote (header-id gnus-current-headers))))
+   "References"
+   (if (vectorp gnus-current-headers)
+       (regexp-quote (mail-header-id gnus-current-headers))
+     "")))
+
 (defun gnus-kill-file-kill-by-xref ()
   "Kill by Xref."
   (interactive)
-  (let ((xref (header-xref gnus-current-headers))
+  (let ((xref (and (vectorp gnus-current-headers)
+                  (mail-header-xref gnus-current-headers)))
        (start 0)
        group)
     (if xref
        (while (string-match " \\([^ \t]+\\):" xref start)
          (setq start (match-end 0))
-         (if (not (string= 
-                   (setq group 
-                         (substring xref (match-beginning 1) (match-end 1)))
-                   gnus-newsgroup-name))
-             (gnus-kill-file-enter-kill 
-              "Xref" (concat " " (regexp-quote group) ":"))))
-      (gnus-kill-file-enter-kill "Xref" ""))))
+         (when (not (string=
+                     (setq group
+                           (substring xref (match-beginning 1) (match-end 1)))
+                     gnus-newsgroup-name))
+           (gnus-kill-file-enter-kill
+            "Xref" (concat " " (regexp-quote group) ":") t)))
+      (gnus-kill-file-enter-kill "Xref" "" t))))
 
 (defun gnus-kill-file-raise-followups-to-author (level)
   "Raise score for all followups to the current author."
   (interactive "p")
-  (let ((name (header-from gnus-current-headers))
+  (let ((name (mail-header-from gnus-current-headers))
        string)
     (save-excursion
       (gnus-kill-set-kill-buffer)