X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-group.el;h=e24cf00dda0f85edea870ac7fdc97fcc769c0d94;hb=2d356801ab1a350e4f51424464e78ebf0f88f59e;hp=8fb193e46565aff443a9f3386d669119cd9818c5;hpb=c6cb90486fb87df7c47101e412b3e75ae06d121e;p=gnus diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index 8fb193e46..e24cf00dd 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -1,6 +1,7 @@ ;;; gnus-group.el --- group mode commands for Gnus -;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 -;; Free Software Foundation, Inc. + +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +;; 2005, 2006 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: news @@ -19,8 +20,8 @@ ;; 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., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. ;;; Commentary: @@ -28,7 +29,7 @@ (eval-when-compile (require 'cl) - (defvar tool-bar-map)) + (defvar tool-bar-mode)) (require 'gnus) (require 'gnus-start) @@ -38,10 +39,11 @@ (require 'gnus-range) (require 'gnus-win) (require 'gnus-undo) +(require 'gmm-utils) (require 'time-date) (require 'gnus-ems) -(eval-when-compile +(eval-when-compile (require 'mm-url) (let ((features (cons 'gnus-group features))) (require 'gnus-sum)) @@ -133,7 +135,7 @@ for the groups to be sorted. Pre-made functions include `gnus-group-sort-by-score', `gnus-group-sort-by-method', `gnus-group-sort-by-server', and `gnus-group-sort-by-rank'. -This variable can also be a list of sorting functions. In that case, +This variable can also be a list of sorting functions. In that case, the most significant sort function should be the last function in the list." :group 'gnus-group-listing @@ -195,7 +197,7 @@ with some simple extensions. Note that this format specification is not always respected. For reasons of efficiency, when listing killed groups, this specification -is ignored altogether. If the spec is changed considerably, your +is ignored altogether. If the spec is changed considerably, your output may end up looking strange when listing both alive and killed groups. @@ -287,14 +289,15 @@ variable." :type 'hook) (defcustom gnus-useful-groups - '(("(ding) mailing list mirrored at sunsite.auc.dk" - "emacs.ding" - (nntp "sunsite.auc.dk" - (nntp-address "sunsite.auc.dk"))) - ("gnus-bug archive" - "gnus-bug" - (nndir "/ftp@ftp.ifi.uio.no:/pub/emacs/gnus/gnus-bug/")) - ("Gnus help group" + '(("(ding) mailing list mirrored at gmane.org" + "gmane.emacs.gnus.general" + (nntp "Gmane" + (nntp-address "news.gmane.org"))) + ("Gnus bug archive" + "gnus.gnus-bug" + (nntp "news.gnus.org" + (nntp-address "news.gnus.org"))) + ("Local Gnus help group" "gnus-help" (nndoc "gnus-help" (nndoc-article-type mbox) @@ -313,50 +316,50 @@ variable." (defcustom gnus-group-highlight '(;; Mail. ((and mailp (= unread 0) (eq level 1)) . - gnus-group-mail-1-empty-face) + gnus-group-mail-1-empty) ((and mailp (eq level 1)) . - gnus-group-mail-1-face) + gnus-group-mail-1) ((and mailp (= unread 0) (eq level 2)) . - gnus-group-mail-2-empty-face) + gnus-group-mail-2-empty) ((and mailp (eq level 2)) . - gnus-group-mail-2-face) + gnus-group-mail-2) ((and mailp (= unread 0) (eq level 3)) . - gnus-group-mail-3-empty-face) + gnus-group-mail-3-empty) ((and mailp (eq level 3)) . - gnus-group-mail-3-face) + gnus-group-mail-3) ((and mailp (= unread 0)) . - gnus-group-mail-low-empty-face) + gnus-group-mail-low-empty) ((and mailp) . - gnus-group-mail-low-face) + gnus-group-mail-low) ;; News. ((and (= unread 0) (eq level 1)) . - gnus-group-news-1-empty-face) + gnus-group-news-1-empty) ((and (eq level 1)) . - gnus-group-news-1-face) + gnus-group-news-1) ((and (= unread 0) (eq level 2)) . - gnus-group-news-2-empty-face) + gnus-group-news-2-empty) ((and (eq level 2)) . - gnus-group-news-2-face) + gnus-group-news-2) ((and (= unread 0) (eq level 3)) . - gnus-group-news-3-empty-face) + gnus-group-news-3-empty) ((and (eq level 3)) . - gnus-group-news-3-face) + gnus-group-news-3) ((and (= unread 0) (eq level 4)) . - gnus-group-news-4-empty-face) + gnus-group-news-4-empty) ((and (eq level 4)) . - gnus-group-news-4-face) + gnus-group-news-4) ((and (= unread 0) (eq level 5)) . - gnus-group-news-5-empty-face) + gnus-group-news-5-empty) ((and (eq level 5)) . - gnus-group-news-5-face) + gnus-group-news-5) ((and (= unread 0) (eq level 6)) . - gnus-group-news-6-empty-face) + gnus-group-news-6-empty) ((and (eq level 6)) . - gnus-group-news-6-face) + gnus-group-news-6) ((and (= unread 0)) . - gnus-group-news-low-empty-face) + gnus-group-news-low-empty) (t . - gnus-group-news-low-face)) + gnus-group-news-low)) "*Controls the highlighting of group buffer lines. Below is a list of `Form'/`Face' pairs. When deciding how a a @@ -386,7 +389,7 @@ ticked: The number of ticked articles." :type 'character) (defgroup gnus-group-icons nil - "Add Icons to your group buffer. " + "Add Icons to your group buffer." :group 'gnus-group-visual) (defcustom gnus-group-icon-list @@ -448,7 +451,7 @@ nnml:\" in the minibuffer prompt. If it is an alist, it must consist of \(NUMBER . PROMPT\) pairs, for example: \((1 . \"\") (2 . \"nnfolder+archive:\")). The element with number 0 is used when no prefix argument is given to `gnus-group-jump-to-group'." - :version "21.4" + :version "22.1" :group 'gnus-group-various :type '(choice (string :tag "Prompt string") (const :tag "Empty" nil) @@ -497,9 +500,15 @@ simple manner.") (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d) (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d) - (?g gnus-tmp-decoded-group ?s) + (?g (if (boundp 'gnus-tmp-decoded-group) + gnus-tmp-decoded-group + gnus-tmp-group) + ?s) (?G gnus-tmp-qualified-group ?s) - (?c (gnus-short-group-name gnus-tmp-decoded-group) ?s) + (?c (gnus-short-group-name (if (boundp 'gnus-tmp-decoded-group) + gnus-tmp-decoded-group + gnus-tmp-group)) + ?s) (?C gnus-tmp-comment ?s) (?D gnus-tmp-newsgroup-description ?s) (?o gnus-tmp-moderated ?c) @@ -650,6 +659,7 @@ simple manner.") "r" gnus-group-rename-group "R" gnus-group-make-rss-group "c" gnus-group-customize + "z" gnus-group-compact-group "x" gnus-group-nnimap-expunge "\177" gnus-group-delete-group [delete] gnus-group-delete-group) @@ -828,6 +838,8 @@ simple manner.") (gnus-group-group-name)] ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)] ["Customize" gnus-group-customize (gnus-group-group-name)] + ["Compact" gnus-group-compact-group + :active (gnus-group-group-name)] ("Edit" ["Parameters" gnus-group-edit-group-parameters :included (not (gnus-topic-mode-p)) @@ -984,43 +996,144 @@ simple manner.") (gnus-run-hooks 'gnus-group-menu-hook))) -(defvar gnus-group-toolbar-map nil) - -;; Emacs 21 tool bar. Should be no-op otherwise. -(defun gnus-group-make-tool-bar () - (if (and - (condition-case nil (require 'tool-bar) (error nil)) - (fboundp 'tool-bar-add-item-from-menu) - (default-value 'tool-bar-mode) - (not gnus-group-toolbar-map)) - (setq gnus-group-toolbar-map - (let ((tool-bar-map (make-sparse-keymap)) - (load-path (mm-image-load-path))) - (tool-bar-add-item-from-menu - 'gnus-group-get-new-news "get-news" gnus-group-mode-map) - (tool-bar-add-item-from-menu - 'gnus-group-get-new-news-this-group "gnntg" gnus-group-mode-map) - (tool-bar-add-item-from-menu - 'gnus-group-catchup-current "catchup" gnus-group-mode-map) - (tool-bar-add-item-from-menu - 'gnus-group-describe-group "describe-group" gnus-group-mode-map) - (tool-bar-add-item "subscribe" 'gnus-group-subscribe 'subscribe - :help "Subscribe to the current group") - (tool-bar-add-item "unsubscribe" 'gnus-group-unsubscribe - 'unsubscribe - :help "Unsubscribe from the current group") - (tool-bar-add-item-from-menu - 'gnus-group-exit "exit-gnus" gnus-group-mode-map) - tool-bar-map))) - (if gnus-group-toolbar-map - (set (make-local-variable 'tool-bar-map) gnus-group-toolbar-map))) + +(defvar gnus-group-tool-bar-map nil) + +(defun gnus-group-tool-bar-update (&optional symbol value) + "Update group buffer toolbar. +Setter function for custom variables." + (when symbol + (set-default symbol value)) + ;; (setq-default gnus-group-tool-bar-map nil) + ;; (use-local-map gnus-group-mode-map) + (when (gnus-alive-p) + (with-current-buffer gnus-group-buffer + (gnus-group-make-tool-bar t)))) + +(defcustom gnus-group-tool-bar (if (eq gmm-tool-bar-style 'gnome) + 'gnus-group-tool-bar-gnome + 'gnus-group-tool-bar-retro) + "Specifies the Gnus group tool bar. + +It can be either a list or a symbol refering to a list. See +`gmm-tool-bar-from-list' for the format of the list. The +default key map is `gnus-group-mode-map'. + +Pre-defined symbols include `gnus-group-tool-bar-gnome' and +`gnus-group-tool-bar-retro'." + :type '(choice (const :tag "GNOME style" gnus-group-tool-bar-gnome) + (const :tag "Retro look" gnus-group-tool-bar-retro) + (repeat :tag "User defined list" gmm-tool-bar-item) + (symbol)) + :version "23.0" ;; No Gnus + :initialize 'custom-initialize-default + :set 'gnus-group-tool-bar-update + :group 'gnus-group) + +(defcustom gnus-group-tool-bar-gnome + '((gnus-group-post-news "mail/compose") + ;; Some useful agent icons? I don't use the agent so agent users should + ;; suggest useful commands: + (gnus-agent-toggle-plugged "disconnect" t + :help "Gnus is currently unplugged. Click to work online." + :visible (and gnus-agent (not gnus-plugged))) + (gnus-agent-toggle-plugged "connect" t + :help "Gnus is currently plugged. Click to work offline." + :visible (and gnus-agent gnus-plugged)) + ;; FIXME: gnus-agent-toggle-plugged (in gnus-agent-group-make-menu-bar) + ;; should have a better help text. + (gnus-group-send-queue "mail/outbox" t + :visible (and gnus-agent gnus-plugged) + :help "Send articles from the queue group") + (gnus-group-get-new-news "mail/inbox" nil + :visible (or (not gnus-agent) + gnus-plugged)) + ;; FIXME: gnus-*-read-group should have a better help text. + (gnus-topic-read-group "open" nil + :visible (and (boundp 'gnus-topic-mode) + gnus-topic-mode)) + (gnus-group-read-group "open" nil + :visible (not (and (boundp 'gnus-topic-mode) + gnus-topic-mode))) + ;; (gnus-group-find-new-groups "???" nil) + (gnus-group-save-newsrc "save") + (gnus-group-describe-group "describe") + (gnus-group-unsubscribe-current-group "gnus/toggle-subscription") + (gnus-group-prev-unread-group "left-arrow") + (gnus-group-next-unread-group "right-arrow") + (gnus-group-exit "exit") + (gmm-customize-mode "preferences" t :help "Edit mode preferences") + (gnus-info-find-node "help")) + "List of functions for the group tool bar (GNOME style). + +See `gmm-tool-bar-from-list' for the format of the list." + :type '(repeat gmm-tool-bar-item) + :version "23.0" ;; No Gnus + :initialize 'custom-initialize-default + :set 'gnus-group-tool-bar-update + :group 'gnus-group) + +(defcustom gnus-group-tool-bar-retro + '((gnus-group-get-new-news "gnus/get-news") + (gnus-group-get-new-news-this-group "gnus/gnntg") + (gnus-group-catchup-current "gnus/catchup") + (gnus-group-describe-group "gnus/describe-group") + (gnus-group-subscribe "gnus/subscribe" t + :help "Subscribe to the current group") + (gnus-group-unsubscribe "gnus/unsubscribe" t + :help "Unsubscribe from the current group") + (gnus-group-exit "gnus/exit-gnus" gnus-group-mode-map)) + "List of functions for the group tool bar (retro look). + +See `gmm-tool-bar-from-list' for the format of the list." + :type '(repeat gmm-tool-bar-item) + :version "23.0" ;; No Gnus + :initialize 'custom-initialize-default + :set 'gnus-group-tool-bar-update + :group 'gnus-group) + +(defcustom gnus-group-tool-bar-zap-list t + "List of icon items from the global tool bar. +These items are not displayed in the Gnus group mode tool bar. + +See `gmm-tool-bar-from-list' for the format of the list." + :type 'gmm-tool-bar-zap-list + :version "23.0" ;; No Gnus + :initialize 'custom-initialize-default + :set 'gnus-group-tool-bar-update + :group 'gnus-group) + +(defvar image-load-path) + +(defun gnus-group-make-tool-bar (&optional force) + "Make a group mode tool bar from `gnus-group-tool-bar'. +When FORCE, rebuild the tool bar." + (when (and (not (featurep 'xemacs)) + (boundp 'tool-bar-mode) + tool-bar-mode + ;; The Gnus 5.10.6 code checked (default-value 'tool-bar-mode). + ;; Why? --rsteib + (or (not gnus-group-tool-bar-map) force)) + (let* ((load-path + (gmm-image-load-path-for-library "gnus" + "gnus/toggle-subscription.xpm" + nil t)) + (image-load-path (cons (car load-path) + (when (boundp 'image-load-path) + image-load-path))) + (map (gmm-tool-bar-from-list gnus-group-tool-bar + gnus-group-tool-bar-zap-list + 'gnus-group-mode-map))) + (if map + (set (make-local-variable 'tool-bar-map) map)))) + gnus-group-tool-bar-map) (defun gnus-group-mode () "Major mode for reading news. All normal editing commands are switched off. \\ -The group buffer lists (some of) the groups available. For instance, +The group buffer lists (some of) the groups available. For instance, `\\[gnus-group-list-groups]' will list all subscribed groups with unread articles, while `\\[gnus-group-list-zombies]' lists all zombie groups. @@ -1054,7 +1167,7 @@ The following commands are available: (gnus-undo-mode 1)) (when gnus-slave (gnus-slave-mode)) - (gnus-run-hooks 'gnus-group-mode-hook)) + (gnus-run-mode-hooks 'gnus-group-mode-hook)) (defun gnus-update-group-mark-positions () (save-excursion @@ -1385,6 +1498,36 @@ if it is a string, only list groups matching REGEXP." (gnus-range-difference (list active) (gnus-info-read info)) seen)))))) +;; Moving through the Group buffer (in topic mode) e.g. with C-n doesn't +;; update the state (enabled/disabled) of the icon `gnus-group-describe-group' +;; automatically. After `C-l' the state is correct. See the following report +;; on emacs-devel +;; : +;; From: Reiner Steib +;; Subject: tool bar icons not updated according to :active condition +;; Newsgroups: gmane.emacs.devel +;; Date: Mon, 23 Jan 2006 19:59:13 +0100 +;; Message-ID: + +(defcustom gnus-group-update-tool-bar + (and (not (featurep 'xemacs)) + (boundp 'tool-bar-mode) + tool-bar-mode + ;; Using `redraw-frame' (see `gnus-tool-bar-update') in Emacs 21 might + ;; be confusing, so maybe we shouldn't call it by default. + (fboundp 'force-window-update)) + "Force updating the group buffer tool bar." + :group 'gnus-group + :version "22.1" + :initialize 'custom-initialize-default + :set (lambda (symbol value) + (set-default symbol value) + (when (gnus-alive-p) + (with-current-buffer gnus-group-buffer + ;; FIXME: Is there a better way to redraw the group buffer? + (gnus-group-get-new-news 0)))) + :type 'boolean) + (defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level gnus-tmp-marked number gnus-tmp-method) @@ -1449,8 +1592,10 @@ if it is a string, only list groups matching REGEXP." (if (member gnus-tmp-group gnus-group-marked) gnus-process-mark ? )) (buffer-read-only nil) + beg end header gnus-tmp-header) ; passed as parameter to user-funcs. (beginning-of-line) + (setq beg (point)) (gnus-add-text-properties (point) (prog1 (1+ (point)) @@ -1460,11 +1605,17 @@ if it is a string, only list groups matching REGEXP." (eval gnus-group-line-format-spec))) `(gnus-group ,(gnus-intern-safe gnus-tmp-group gnus-active-hashtb) gnus-unread ,(if (numberp number) - (string-to-int gnus-tmp-number-of-unread) + (string-to-number gnus-tmp-number-of-unread) t) gnus-marked ,gnus-tmp-marked-mark gnus-indentation ,gnus-group-indentation gnus-level ,gnus-tmp-level)) + (setq end (point)) + (when gnus-group-update-tool-bar + (gnus-put-text-property beg end 'point-entered + 'gnus-tool-bar-update) + (gnus-put-text-property beg end 'point-left + 'gnus-tool-bar-update)) (forward-line -1) (when (inline (gnus-visual-p 'group-highlight 'highlight)) (gnus-run-hooks 'gnus-group-update-hook)) @@ -1693,7 +1844,7 @@ If FIRST-TOO, the current line is also eligible as a target." (size (+ size-in-cache size-in-agent)) (suffix '("B" "K" "M" "G")) (scale 1024.0) - (cutoff (* 10 scale))) + (cutoff scale)) (while (> size cutoff) (setq size (/ size scale) suffix (cdr suffix))) @@ -1879,7 +2030,7 @@ and with point over the group in question." If the prefix argument ALL is non-nil, already read articles become readable. IF ALL is a number, fetch this number of articles. If the optional argument NO-ARTICLE is non-nil, no article will be -auto-selected upon group entry. If GROUP is non-nil, fetch that +auto-selected upon group entry. If GROUP is non-nil, fetch that group." (interactive "P") (let ((no-display (eq all 0)) @@ -1920,11 +2071,11 @@ articles in the group." (forward-line -1)) (gnus-group-read-group all t)) -(defun gnus-group-quick-select-group (&optional all) - "Select the current group \"quickly\". -This means that no highlighting or scoring will be performed. -If ALL (the prefix argument) is 0, don't even generate the summary -buffer. +(defun gnus-group-quick-select-group (&optional all group) + "Select the GROUP \"quickly\". +This means that no highlighting or scoring will be performed. If +ALL (the prefix argument) is 0, don't even generate the summary +buffer. If GROUP is nil, use current group. This might be useful if you want to toggle threading before entering the group." @@ -1935,7 +2086,7 @@ before entering the group." gnus-home-score-file gnus-apply-kill-hook gnus-summary-expunge-below) - (gnus-group-read-group all t))) + (gnus-group-read-group all t group))) (defun gnus-group-visible-select-group (&optional all) "Select the current group without hiding any articles." @@ -1959,14 +2110,30 @@ be permanent." (gnus-group-read-ephemeral-group (gnus-group-prefixed-name group method) method))) +(defun group-name-at-point () + (let ((regexp "[^-a-zA-Z+.:_]")) + (save-excursion + (buffer-substring + (progn + (re-search-backward regexp nil t) + (forward-char 1) + (point)) + (progn + (re-search-forward regexp nil t) + (forward-char -1) + (point)))))) + ;;;###autoload (defun gnus-fetch-group (group &optional articles) "Start Gnus if necessary and enter GROUP. +If ARTICLES, display those articles. Returns whether the fetching was successful or not." - (interactive (list (completing-read "Group name: " gnus-active-hashtb))) + (interactive (list (completing-read "Group name: " gnus-active-hashtb + nil nil nil nil + (group-name-at-point)))) (unless (get-buffer gnus-group-buffer) (gnus-no-server)) - (gnus-group-read-group articles nil group)) + (gnus-group-read-group (if articles nil t) nil group articles)) ;;;###autoload (defun gnus-fetch-group-other-frame (group) @@ -1990,14 +2157,14 @@ Same as `gnus-large-newsgroup', but only used for ephemeral newsgroups. 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." - :version "21.4" + :version "22.1" :group 'gnus-group-select :type '(choice (const :tag "No limit" nil) integer)) (defcustom gnus-fetch-old-ephemeral-headers nil "Same as `gnus-fetch-old-headers', but only used for ephemeral newsgroups." - :version "21.4" + :version "22.1" :group 'gnus-thread :type '(choice (const :tag "off" nil) (const some) @@ -2009,7 +2176,8 @@ confirmation is required." (defun gnus-group-read-ephemeral-group (group method &optional activate quit-config request-only select-articles - parameters) + parameters + number) "Read GROUP from METHOD as an ephemeral group. If ACTIVATE, request the group first. If QUIT-CONFIG, use that window configuration when exiting from the @@ -2017,6 +2185,7 @@ ephemeral group. If REQUEST-ONLY, don't actually read the group; just request it. If SELECT-ARTICLES, only select those articles. If PARAMETERS, use those as the group parameters. +If NUMBER, fetch this number of articles. Return the name of the group if selection was successful." (interactive @@ -2064,7 +2233,7 @@ Return the name of the group if selection was successful." (when (let ((gnus-large-newsgroup gnus-large-ephemeral-newsgroup) (gnus-fetch-old-headers gnus-fetch-old-ephemeral-headers)) - (gnus-group-read-group t t group select-articles)) + (gnus-group-read-group (or number t) t group select-articles)) group) ;;(error nil) (quit @@ -2235,6 +2404,25 @@ If EXCLUDE-GROUP, do not go to that group." (gnus-group-position-point) (and best-point (gnus-group-group-name)))) +;; Is there something like an after-point-motion-hook? +;; (inhibit-point-motion-hooks?). Is there a tool-bar-update function? + +;; (defun gnus-group-menu-bar-update () +;; (let* ((buf (list (with-current-buffer gnus-group-buffer +;; (current-buffer)))) +;; (name (buffer-name (car buf)))) +;; (setcdr buf +;; (if (> (length name) 27) +;; (concat (substring name 0 12) +;; "..." +;; (substring name -12)) +;; name)) +;; (menu-bar-update-buffers-1 buf))) + +;; (defun gnus-group-position-point () +;; (gnus-goto-colon) +;; (gnus-group-menu-bar-update)) + (defun gnus-group-first-unread-group () "Go to the first group with unread articles." (interactive) @@ -2545,7 +2733,9 @@ group already exists: (gnus-group-position-point)) (defun gnus-group-make-doc-group (file type) - "Create a group that uses a single file as the source." + "Create a group that uses a single file as the source. + +If called with a prefix argument, ask for the file type." (interactive (list (read-file-name "File name: ") (and current-prefix-arg 'ask))) @@ -2554,7 +2744,7 @@ group already exists: char found) (while (not found) (message - "%sFile type (mbox, babyl, digest, forward, mmdf, guess) [mbdfag]: " + "%sFile type (mbox, babyl, digest, forward, mmdf, guess) [m, b, d, f, a, g]: " err) (setq found (cond ((= (setq char (read-char)) ?m) 'mbox) ((= char ?b) 'babyl) @@ -2565,13 +2755,18 @@ group already exists: (t (setq err (format "%c unknown. " char)) nil)))) (setq type found))) - (let* ((file (expand-file-name file)) - (name (gnus-generate-new-group-name - (gnus-group-prefixed-name - (file-name-nondirectory file) '(nndoc ""))))) + (setq file (expand-file-name file)) + (let ((name (gnus-generate-new-group-name + (gnus-group-prefixed-name + (file-name-nondirectory file) '(nndoc "")))) + (encodable (mm-coding-system-p 'utf-8))) (gnus-group-make-group - (gnus-group-real-name name) - (list 'nndoc file + (if encodable + (mm-encode-coding-string (gnus-group-real-name name) 'utf-8) + (gnus-group-real-name name)) + (list 'nndoc (if encodable + (mm-encode-coding-string file 'utf-8) + file) (list 'nndoc-address file) (list 'nndoc-article-type (or type 'guess)))))) @@ -2705,7 +2900,7 @@ Given a prefix, create a full group." (defun gnus-group-make-directory-group (dir) "Create an nndir group. The user will be prompted for a directory. The contents of this -directory will be used as a newsgroup. The directory should contain +directory will be used as a newsgroup. The directory should contain mail messages or news articles in files that have numeric names." (interactive (list (read-file-name "Create group from directory: "))) @@ -3040,7 +3235,7 @@ sort in reverse order." (defun gnus-group-sort-by-unread (info1 info2) "Sort by number of unread articles." (let ((n1 (gnus-group-unread (gnus-info-group info1))) - (n2 (gnus-group-unread (gnus-info-group info1)))) + (n2 (gnus-group-unread (gnus-info-group info2)))) (< (or (and (numberp n1) n1) 0) (or (and (numberp n2) n2) 0)))) @@ -3079,7 +3274,8 @@ sort in reverse order." ;;; Clearing data (defun gnus-group-clear-data (&optional arg) - "Clear all marks and read ranges from the current group." + "Clear all marks and read ranges from the current group. +Obeys the process/prefix convention." (interactive "P") (gnus-group-iterate arg (lambda (group) @@ -3159,13 +3355,15 @@ up is returned." (when (eq 'nnvirtual (car method)) (nnvirtual-catchup-group (gnus-group-real-name group) (nth 1 method) all))) - (if (>= (gnus-group-level group) gnus-level-zombie) - (gnus-message 2 "Dead groups can't be caught up") - (if (prog1 - (gnus-group-goto-group group) - (gnus-group-catchup group all)) - (gnus-group-update-group-line) - (setq ret (1+ ret))))) + (cond + ((>= (gnus-group-level group) gnus-level-zombie) + (gnus-message 2 "Dead groups can't be caught up")) + ((prog1 + (gnus-group-goto-group group) + (gnus-group-catchup group all)) + (gnus-group-update-group-line)) + (t + (setq ret (1+ ret))))) (gnus-group-next-unread-group 1) ret))) @@ -3203,10 +3401,12 @@ or nil if no action could be taken." (gnus-add-marked-articles group 'dormant nil nil 'force)) ;; Do auto-expirable marks if that's required. (when (gnus-group-auto-expirable-p group) - (gnus-range-map (lambda (article) - (gnus-add-marked-articles group 'expire (list article)) - (gnus-request-set-mark group (list (list (list article) 'add '(expire))))) - unread)) + (gnus-range-map + (lambda (article) + (gnus-add-marked-articles group 'expire (list article)) + (gnus-request-set-mark group (list (list (list article) + 'add '(expire))))) + unread)) (let ((gnus-newsgroup-name group)) (gnus-run-hooks 'gnus-group-catchup-group-hook)) num))) @@ -3277,7 +3477,7 @@ Uses the process/prefix convention." (progn (unless (gnus-group-process-prefix current-prefix-arg) (error "No group on the current line")) - (string-to-int + (string-to-number (let ((s (read-string (format "Level (default %s): " (or (gnus-group-group-level) @@ -3372,7 +3572,7 @@ group line." (defun gnus-group-transpose-groups (n) "Move the current newsgroup up N places. -If given a negative prefix, move down instead. The difference between +If given a negative prefix, move down instead. The difference between N and the number of steps taken is returned." (interactive "p") (unless (gnus-group-group-name) @@ -3623,7 +3823,10 @@ re-scanning. If ARG is non-nil and not a number, this will force ;; We might read in new NoCeM messages here. (when (and gnus-use-nocem - (null arg)) + (or (and (numberp gnus-use-nocem) + (numberp arg) + (>= arg gnus-use-nocem)) + (not arg))) (gnus-nocem-scan-groups)) ;; If ARG is not a number, then we read the active file. (when (and arg (not (numberp arg))) @@ -4082,7 +4285,7 @@ and the second element is the address." (unless entry (error "Trying to change non-existent group %s" method-only-group)) ;; We have received parts of the actual group info - either the - ;; select method or the group parameters. We first check + ;; select method or the group parameters. We first check ;; whether we have to extend the info, and if so, do that. (let ((len (length info)) (total (if (eq part 'method) 5 6))) @@ -4327,6 +4530,40 @@ This command may read the active file." (gnus-add-marked-articles group 'expire (list article)))))) + +;;; +;;; Group compaction. -- dvl +;;; + +(defun gnus-group-compact-group (group) + "Compact the current group. +Compaction means removing gaps between article numbers. Hence, this +operation is only meaningful for back ends using one file per article +\(e.g. nnml). + +Note: currently only implemented in nnml." + (interactive (list (gnus-group-group-name))) + (unless group + (error "No group to compact")) + (unless (gnus-check-backend-function 'request-compact-group group) + (error "This back end does not support group compaction")) + (let ((group-decoded (gnus-group-decoded-name group))) + (gnus-message 6 "\ +Compacting group %s... (this may take a long time)" + group-decoded) + (prog1 + (if (not (gnus-request-compact-group group)) + (gnus-error 3 "Couldn't compact group %s" group-decoded) + (gnus-message 6 "Compacting group %s...done" group-decoded) + t) + ;; Invalidate the "original article" buffer which might be out of date. + ;; #### NOTE: Yes, this might be a bit rude, but since compaction + ;; #### will not happen very often, I think this is acceptable. + (let ((original (get-buffer gnus-original-article-buffer))) + (and original (gnus-kill-buffer original))) + ;; Update the group line to reflect new information (art number etc). + (gnus-group-update-group-line)))) + (provide 'gnus-group) ;;; arch-tag: 2eb5440f-0bca-4091-814c-e37817536af6