;;; gnus-registry.el --- article registry for Gnus
;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006 Free Software Foundation, Inc.
+;; 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
;; Keywords: news
:test 'equal)
"*The article registry by Message ID.")
-(defcustom gnus-registry-unfollowed-groups '("delayed" "drafts" "queue")
- "List of groups that gnus-registry-split-fancy-with-parent won't follow.
-The group names are matched, they don't have to be fully qualified."
+(defcustom gnus-registry-unfollowed-groups '("delayed$" "drafts$" "queue$" "INBOX$")
+ "List of groups that gnus-registry-split-fancy-with-parent won't return.
+The group names are matched, they don't have to be fully
+qualified. This parameter tells the Registry 'never split a
+message into a group that matches one of these, regardless of
+references.'"
:group 'gnus-registry
- :type '(repeat string))
+ :type '(repeat regexp))
(defcustom gnus-registry-install nil
"Whether the registry should be installed."
(gnus-load file)
(gnus-message 5 "Reading %s...done" file))))
+;; FIXME: Get rid of duplicated code, cf. `gnus-save-newsrc-file' in
+;; `gnus-start.el'. --rsteib
(defun gnus-registry-cache-save ()
"Save the registry cache file."
(interactive)
(setq alist
(nthcdr
trim-length
- (sort alist
+ (sort alist
(lambda (a b)
(time-less-p
(or (cdr (gethash (car a) timehash)) '(0 0 0))
messages.
For a message to be split, it looks for the parent message in the
-References or In-Reply-To header and then looks in the registry to
-see which group that message was put in. This group is returned.
+References or In-Reply-To header and then looks in the registry
+to see which group that message was put in. This group is
+returned, unless it matches one of the entries in
+gnus-registry-unfollowed-groups or
+nnmail-split-fancy-with-parent-ignore-groups.
See the Info node `(gnus)Fancy Mail Splitting' for more details."
(let* ((refstr (or (message-fetch-field "references") "")) ; guarantee string
(setq res nil))))
res))
+(defun gnus-registry-wash-for-keywords (&optional force)
+ (interactive)
+ (let ((id (gnus-registry-fetch-message-id-fast gnus-current-article))
+ word words)
+ (if (or (not (gnus-registry-fetch-extra id 'keywords))
+ force)
+ (save-excursion
+ (set-buffer gnus-article-buffer)
+ (article-goto-body)
+ (save-window-excursion
+ (save-restriction
+ (narrow-to-region (point) (point-max))
+ (with-syntax-table gnus-adaptive-word-syntax-table
+ (while (re-search-forward "\\b\\w+\\b" nil t)
+ (setq word (gnus-registry-remove-alist-text-properties
+ (downcase (buffer-substring
+ (match-beginning 0) (match-end 0)))))
+ (if (> (length word) 3)
+ (push word words))))))
+ (gnus-registry-store-extra-entry id 'keywords words)))))
+
+(defun gnus-registry-find-keywords (keyword)
+ (interactive "skeyword: ")
+ (let (articles)
+ (maphash
+ (lambda (key value)
+ (when (gnus-registry-grep-in-list
+ keyword
+ (cdr (gnus-registry-fetch-extra key 'keywords)))
+ (push key articles)))
+ gnus-registry-hashtb)
+ articles))
+
(defun gnus-registry-register-message-ids ()
"Register the Message-ID of every article in the group"
(unless (gnus-parameter-registry-ignore gnus-newsgroup-name)
(mapcar 'not
(mapcar
(lambda (x)
- (string-match x word))
+ (string-match word x))
list)))))
+;;; if this extends to more than 'flags, it should be improved to be more generic.
+(defun gnus-registry-fetch-extra-flags (id)
+ "Get the flags of a message, based on the message ID.
+Returns a list of symbol flags or nil."
+ (car-safe (cdr (gnus-registry-fetch-extra id 'flags))))
+
+(defun gnus-registry-has-extra-flag (id flag)
+ "Checks if a message has `flag', based on the message ID."
+ (memq flag (gnus-registry-fetch-extra-flags id)))
+
+(defun gnus-registry-store-extra-flags (id &rest flag-list)
+ "Set the flags of a message, based on the message ID.
+The `flag-list' can be nil, in which case no flags are left."
+ (gnus-registry-store-extra-entry id 'flags (list flag-list)))
+
+(defun gnus-registry-delete-extra-flags (id &rest flag-delete-list)
+ "Delete the message flags in `flag-delete-list', based on the message ID."
+ (let ((flags (gnus-registry-fetch-extra-flags id)))
+ (when flags
+ (dolist (flag flag-delete-list)
+ (setq flags (delq flag flags))))
+ (gnus-registry-store-extra-flags id (car flags))))
+
+(defun gnus-registry-delete-all-extra-flags (id)
+ "Delete all the flags for a message ID."
+ (gnus-registry-store-extra-flags id nil))
+
(defun gnus-registry-fetch-extra (id &optional entry)
"Get the extra data of a message, based on the message ID.
Returns the first place where the trail finds a nonstring."
gnus-registry-hashtb)
(setq gnus-registry-dirty t)))))
+(defun gnus-registry-delete-extra-entry (id key)
+ "Delete a specific entry in the extras field of the registry entry for id."
+ (gnus-registry-store-extra-entry id key nil))
+
(defun gnus-registry-store-extra-entry (id key value)
"Put a specific entry in the extras field of the registry entry for id."
(let* ((extra (gnus-registry-fetch-extra id))
- (alist (gnus-registry-remove-alist-text-properties
- (cons (cons key value)
- (gnus-assq-delete-all key (gnus-registry-fetch-extra id))))))
+ ;; all the entries except the one for `key'
+ (the-rest (gnus-assq-delete-all key (gnus-registry-fetch-extra id)))
+ (alist (if value
+ (gnus-registry-remove-alist-text-properties
+ (cons (cons key value)
+ the-rest))
+ the-rest)))
(gnus-registry-store-extra id alist)))
(defun gnus-registry-fetch-group (id)