comparison lisp/gnus/gnus-group.el @ 31716:9968f55ad26e

Update to emacs-21-branch of the Gnus CVS repository.
author Gerd Moellmann <gerd@gnu.org>
date Tue, 19 Sep 2000 13:37:09 +0000
parents d0ccf995f1ae
children 51cea22fd2aa
comparison
equal deleted inserted replaced
31715:7c896543d225 31716:9968f55ad26e
1 ;;; gnus-group.el --- group mode commands for Gnus 1 ;;; gnus-group.el --- group mode commands for Gnus
2 ;; Copyright (C) 1996,97,98 Free Software Foundation, Inc. 2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000
3 ;; Free Software Foundation, Inc.
3 4
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> 5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;; Keywords: news 6 ;; Keywords: news
6 7
7 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
22 ;; Boston, MA 02111-1307, USA. 23 ;; Boston, MA 02111-1307, USA.
23 24
24 ;;; Commentary: 25 ;;; Commentary:
25 26
26 ;;; Code: 27 ;;; Code:
27
28 (eval-when-compile (require 'cl))
29 28
30 (eval-when-compile (require 'cl)) 29 (eval-when-compile (require 'cl))
31 30
32 (require 'gnus) 31 (require 'gnus)
33 (require 'gnus-start) 32 (require 'gnus-start)
35 (require 'gnus-spec) 34 (require 'gnus-spec)
36 (require 'gnus-int) 35 (require 'gnus-int)
37 (require 'gnus-range) 36 (require 'gnus-range)
38 (require 'gnus-win) 37 (require 'gnus-win)
39 (require 'gnus-undo) 38 (require 'gnus-undo)
39 (require 'time-date)
40 40
41 (defcustom gnus-group-archive-directory 41 (defcustom gnus-group-archive-directory
42 "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/" 42 "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
43 "*The address of the (ding) archives." 43 "*The address of the (ding) archives."
44 :group 'gnus-group-foreign 44 :group 'gnus-group-foreign
48 "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/" 48 "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
49 "*The address of the most recent (ding) articles." 49 "*The address of the most recent (ding) articles."
50 :group 'gnus-group-foreign 50 :group 'gnus-group-foreign
51 :type 'directory) 51 :type 'directory)
52 52
53 (defcustom gnus-no-groups-message "No news is no news" 53 (defcustom gnus-no-groups-message "No gnus is bad news"
54 "*Message displayed by Gnus when no groups are available." 54 "*Message displayed by Gnus when no groups are available."
55 :group 'gnus-start 55 :group 'gnus-start
56 :type 'string) 56 :type 'string)
57 57
58 (defcustom gnus-keep-same-level nil 58 (defcustom gnus-keep-same-level nil
160 %m Whether there is new(ish) mail in the group (char, \"%\") 160 %m Whether there is new(ish) mail in the group (char, \"%\")
161 %l Whether there are GroupLens predictions for this group (string) 161 %l Whether there are GroupLens predictions for this group (string)
162 %n Select from where (string) 162 %n Select from where (string)
163 %z A string that look like `<%s:%n>' if a foreign select method is used 163 %z A string that look like `<%s:%n>' if a foreign select method is used
164 %d The date the group was last entered. 164 %d The date the group was last entered.
165 %E Icon as defined by `gnus-group-icon-list'.
165 %u User defined specifier. The next character in the format string should 166 %u User defined specifier. The next character in the format string should
166 be a letter. Gnus will call the function gnus-user-format-function-X, 167 be a letter. Gnus will call the function gnus-user-format-function-X,
167 where X is the letter following %u. The function will be passed the 168 where X is the letter following %u. The function will be passed the
168 current header as argument. The function should return a string, which 169 current header as argument. The function should return a string, which
169 will be inserted into the buffer just like information from any other 170 will be inserted into the buffer just like information from any other
298 gnus-group-news-2-face) 299 gnus-group-news-2-face)
299 ((and (= unread 0) (not mailp) (eq level 3)) . 300 ((and (= unread 0) (not mailp) (eq level 3)) .
300 gnus-group-news-3-empty-face) 301 gnus-group-news-3-empty-face)
301 ((and (not mailp) (eq level 3)) . 302 ((and (not mailp) (eq level 3)) .
302 gnus-group-news-3-face) 303 gnus-group-news-3-face)
304 ((and (= unread 0) (not mailp) (eq level 4)) .
305 gnus-group-news-4-empty-face)
306 ((and (not mailp) (eq level 4)) .
307 gnus-group-news-4-face)
308 ((and (= unread 0) (not mailp) (eq level 5)) .
309 gnus-group-news-5-empty-face)
310 ((and (not mailp) (eq level 5)) .
311 gnus-group-news-5-face)
312 ((and (= unread 0) (not mailp) (eq level 6)) .
313 gnus-group-news-6-empty-face)
314 ((and (not mailp) (eq level 6)) .
315 gnus-group-news-6-face)
303 ((and (= unread 0) (not mailp)) . 316 ((and (= unread 0) (not mailp)) .
304 gnus-group-news-low-empty-face) 317 gnus-group-news-low-empty-face)
305 ((and (not mailp)) . 318 ((and (not mailp)) .
306 gnus-group-news-low-face) 319 gnus-group-news-low-face)
307 ;; Mail. 320 ;; Mail.
318 ((eq level 3) . 331 ((eq level 3) .
319 gnus-group-mail-3-face) 332 gnus-group-mail-3-face)
320 ((= unread 0) . 333 ((= unread 0) .
321 gnus-group-mail-low-empty-face) 334 gnus-group-mail-low-empty-face)
322 (t . 335 (t .
323 gnus-group-mail-low-face)) 336 gnus-group-mail-low-face))
324 "*Controls the highlighting of group buffer lines. 337 "*Controls the highlighting of group buffer lines.
325 338
326 Below is a list of `Form'/`Face' pairs. When deciding how a a 339 Below is a list of `Form'/`Face' pairs. When deciding how a a
327 particular group line should be displayed, each form is 340 particular group line should be displayed, each form is
328 evaluated. The content of the face field after the first true form is 341 evaluated. The content of the face field after the first true form is
346 359
347 (defcustom gnus-new-mail-mark ?% 360 (defcustom gnus-new-mail-mark ?%
348 "Mark used for groups with new mail." 361 "Mark used for groups with new mail."
349 :group 'gnus-group-visual 362 :group 'gnus-group-visual
350 :type 'character) 363 :type 'character)
364
365 (defgroup gnus-group-icons nil
366 "Add Icons to your group buffer. "
367 :group 'gnus-group-visual)
368
369 (defcustom gnus-group-icon-list
370 nil
371 "*Controls the insertion of icons into group buffer lines.
372
373 Below is a list of `Form'/`File' pairs. When deciding how a
374 particular group line should be displayed, each form is evaluated.
375 The icon from the file field after the first true form is used. You
376 can change how those group lines are displayed by editing the file
377 field. The File will either be found in the
378 `gnus-group-glyph-directory' or by designating absolute path to the
379 file.
380
381 It is also possible to change and add form fields, but currently that
382 requires an understanding of Lisp expressions. Hopefully this will
383 change in a future release. For now, you can use the following
384 variables in the Lisp expression:
385
386 group: The name of the group.
387 unread: The number of unread articles in the group.
388 method: The select method used.
389 mailp: Whether it's a mail group or not.
390 newsp: Whether it's a news group or not
391 level: The level of the group.
392 score: The score of the group.
393 ticked: The number of ticked articles."
394 :group 'gnus-group-icons
395 :type '(repeat (cons (sexp :tag "Form") file)))
396
397 (defcustom gnus-group-name-charset-method-alist nil
398 "*Alist of method and the charset for group names.
399
400 For example:
401 (((nntp \"news.com.cn\") . cn-gb-2312))
402 "
403 :group 'gnus-charset
404 :type '(repeat (cons (sexp :tag "Method") (symbol :tag "Charset"))))
405
406 (defcustom gnus-group-name-charset-group-alist nil
407 "*Alist of group regexp and the charset for group names.
408
409 For example:
410 ((\"\\.com\\.cn:\" . cn-gb-2312))
411 "
412 :group 'gnus-charset
413 :type '(repeat (cons (regexp :tag "Group") (symbol :tag "Charset"))))
351 414
352 ;;; Internal variables 415 ;;; Internal variables
353 416
354 (defvar gnus-group-sort-alist-function 'gnus-group-sort-flat 417 (defvar gnus-group-sort-alist-function 'gnus-group-sort-flat
355 "Function for sorting the group buffer.") 418 "Function for sorting the group buffer.")
391 (?O gnus-tmp-moderated-string ?s) 454 (?O gnus-tmp-moderated-string ?s)
392 (?p gnus-tmp-process-marked ?c) 455 (?p gnus-tmp-process-marked ?c)
393 (?s gnus-tmp-news-server ?s) 456 (?s gnus-tmp-news-server ?s)
394 (?n gnus-tmp-news-method ?s) 457 (?n gnus-tmp-news-method ?s)
395 (?P gnus-group-indentation ?s) 458 (?P gnus-group-indentation ?s)
459 (?E gnus-tmp-group-icon ?s)
396 (?l gnus-tmp-grouplens ?s) 460 (?l gnus-tmp-grouplens ?s)
397 (?z gnus-tmp-news-method-string ?s) 461 (?z gnus-tmp-news-method-string ?s)
398 (?m (gnus-group-new-mail gnus-tmp-group) ?c) 462 (?m (gnus-group-new-mail gnus-tmp-group) ?c)
399 (?d (gnus-group-timestamp-string gnus-tmp-group) ?s) 463 (?d (gnus-group-timestamp-string gnus-tmp-group) ?s)
400 (?u gnus-tmp-user-defined ?s))) 464 (?u gnus-tmp-user-defined ?s)))
412 "The complete topic-group alist.") 476 "The complete topic-group alist.")
413 477
414 (defvar gnus-group-marked nil) 478 (defvar gnus-group-marked nil)
415 479
416 (defvar gnus-group-list-mode nil) 480 (defvar gnus-group-list-mode nil)
481
482
483 (defvar gnus-group-icon-cache nil)
417 484
418 ;;; 485 ;;;
419 ;;; Gnus group mode 486 ;;; Gnus group mode
420 ;;; 487 ;;;
421 488
425 (gnus-define-keys gnus-group-mode-map 492 (gnus-define-keys gnus-group-mode-map
426 " " gnus-group-read-group 493 " " gnus-group-read-group
427 "=" gnus-group-select-group 494 "=" gnus-group-select-group
428 "\r" gnus-group-select-group 495 "\r" gnus-group-select-group
429 "\M-\r" gnus-group-quick-select-group 496 "\M-\r" gnus-group-quick-select-group
497 "\M- " gnus-group-visible-select-group
430 [(meta control return)] gnus-group-select-group-ephemerally 498 [(meta control return)] gnus-group-select-group-ephemerally
431 "j" gnus-group-jump-to-group 499 "j" gnus-group-jump-to-group
432 "n" gnus-group-next-unread-group 500 "n" gnus-group-next-unread-group
433 "p" gnus-group-prev-unread-group 501 "p" gnus-group-prev-unread-group
434 "\177" gnus-group-prev-unread-group 502 "\177" gnus-group-prev-unread-group
501 "d" gnus-group-make-directory-group 569 "d" gnus-group-make-directory-group
502 "h" gnus-group-make-help-group 570 "h" gnus-group-make-help-group
503 "u" gnus-group-make-useful-group 571 "u" gnus-group-make-useful-group
504 "a" gnus-group-make-archive-group 572 "a" gnus-group-make-archive-group
505 "k" gnus-group-make-kiboze-group 573 "k" gnus-group-make-kiboze-group
574 "l" gnus-group-nnimap-edit-acl
506 "m" gnus-group-make-group 575 "m" gnus-group-make-group
507 "E" gnus-group-edit-group 576 "E" gnus-group-edit-group
508 "e" gnus-group-edit-group-method 577 "e" gnus-group-edit-group-method
509 "p" gnus-group-edit-group-parameters 578 "p" gnus-group-edit-group-parameters
510 "v" gnus-group-add-to-virtual 579 "v" gnus-group-add-to-virtual
512 "D" gnus-group-enter-directory 581 "D" gnus-group-enter-directory
513 "f" gnus-group-make-doc-group 582 "f" gnus-group-make-doc-group
514 "w" gnus-group-make-web-group 583 "w" gnus-group-make-web-group
515 "r" gnus-group-rename-group 584 "r" gnus-group-rename-group
516 "c" gnus-group-customize 585 "c" gnus-group-customize
586 "x" gnus-group-nnimap-expunge
517 "\177" gnus-group-delete-group 587 "\177" gnus-group-delete-group
518 [delete] gnus-group-delete-group) 588 [delete] gnus-group-delete-group)
519 589
520 (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map) 590 (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
521 "b" gnus-group-brew-soup 591 "b" gnus-group-brew-soup
550 "A" gnus-group-list-active 620 "A" gnus-group-list-active
551 "a" gnus-group-apropos 621 "a" gnus-group-apropos
552 "d" gnus-group-description-apropos 622 "d" gnus-group-description-apropos
553 "m" gnus-group-list-matching 623 "m" gnus-group-list-matching
554 "M" gnus-group-list-all-matching 624 "M" gnus-group-list-all-matching
555 "l" gnus-group-list-level) 625 "l" gnus-group-list-level
626 "c" gnus-group-list-cached
627 "?" gnus-group-list-dormant)
556 628
557 (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map) 629 (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
558 "f" gnus-score-flush-cache) 630 "f" gnus-score-flush-cache)
559 631
560 (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map) 632 (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
626 ["Describe all groups" gnus-group-describe-all-groups t] 698 ["Describe all groups" gnus-group-describe-all-groups t]
627 ["Group apropos..." gnus-group-apropos t] 699 ["Group apropos..." gnus-group-apropos t]
628 ["Group and description apropos..." gnus-group-description-apropos t] 700 ["Group and description apropos..." gnus-group-description-apropos t]
629 ["List groups matching..." gnus-group-list-matching t] 701 ["List groups matching..." gnus-group-list-matching t]
630 ["List all groups matching..." gnus-group-list-all-matching t] 702 ["List all groups matching..." gnus-group-list-all-matching t]
631 ["List active file" gnus-group-list-active t]) 703 ["List active file" gnus-group-list-active t]
704 ["List groups with cached" gnus-group-list-cached t]
705 ["List groups with dormant" gnus-group-list-dormant t])
632 ("Sort" 706 ("Sort"
633 ["Default sort" gnus-group-sort-groups t] 707 ["Default sort" gnus-group-sort-groups t]
634 ["Sort by method" gnus-group-sort-groups-by-method t] 708 ["Sort by method" gnus-group-sort-groups-by-method t]
635 ["Sort by rank" gnus-group-sort-groups-by-rank t] 709 ["Sort by rank" gnus-group-sort-groups-by-rank t]
636 ["Sort by score" gnus-group-sort-groups-by-score t] 710 ["Sort by score" gnus-group-sort-groups-by-score t]
712 ["Send replies" gnus-soup-send-replies 786 ["Send replies" gnus-soup-send-replies
713 (fboundp 'gnus-soup-pack-packet)] 787 (fboundp 'gnus-soup-pack-packet)]
714 ["Pack packet" gnus-soup-pack-packet (fboundp 'gnus-soup-pack-packet)] 788 ["Pack packet" gnus-soup-pack-packet (fboundp 'gnus-soup-pack-packet)]
715 ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)] 789 ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)]
716 ["Brew SOUP" gnus-group-brew-soup (fboundp 'gnus-soup-pack-packet)]) 790 ["Brew SOUP" gnus-group-brew-soup (fboundp 'gnus-soup-pack-packet)])
717 ["Send a bug report" gnus-bug t]
718 ["Send a mail" gnus-group-mail t] 791 ["Send a mail" gnus-group-mail t]
719 ["Post an article..." gnus-group-post-news t] 792 ["Post an article..." gnus-group-post-news t]
720 ["Check for new news" gnus-group-get-new-news t] 793 ["Check for new news" gnus-group-get-new-news t]
721 ["Activate all groups" gnus-activate-all-groups t] 794 ["Activate all groups" gnus-activate-all-groups t]
722 ["Restart Gnus" gnus-group-restart t] 795 ["Restart Gnus" gnus-group-restart t]
763 (setq major-mode 'gnus-group-mode) 836 (setq major-mode 'gnus-group-mode)
764 (setq mode-name "Group") 837 (setq mode-name "Group")
765 (gnus-group-set-mode-line) 838 (gnus-group-set-mode-line)
766 (setq mode-line-process nil) 839 (setq mode-line-process nil)
767 (use-local-map gnus-group-mode-map) 840 (use-local-map gnus-group-mode-map)
768 (buffer-disable-undo (current-buffer)) 841 (buffer-disable-undo)
769 (setq truncate-lines t) 842 (setq truncate-lines t)
770 (setq buffer-read-only t) 843 (setq buffer-read-only t)
771 (gnus-set-default-directory) 844 (gnus-set-default-directory)
772 (gnus-update-format-specifications nil 'group 'group-mode) 845 (gnus-update-format-specifications nil 'group 'group-mode)
773 (gnus-update-group-mark-positions) 846 (gnus-update-group-mark-positions)
774 (make-local-hook 'post-command-hook)
775 (add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
776 (when gnus-use-undo 847 (when gnus-use-undo
777 (gnus-undo-mode 1)) 848 (gnus-undo-mode 1))
778 (when gnus-slave 849 (when gnus-slave
779 (gnus-slave-mode)) 850 (gnus-slave-mode))
780 (gnus-run-hooks 'gnus-group-mode-hook)) 851 (gnus-run-hooks 'gnus-group-mode-hook))
790 (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil) 861 (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
791 (goto-char (point-min)) 862 (goto-char (point-min))
792 (setq gnus-group-mark-positions 863 (setq gnus-group-mark-positions
793 (list (cons 'process (and (search-forward "\200" nil t) 864 (list (cons 'process (and (search-forward "\200" nil t)
794 (- (point) 2)))))))) 865 (- (point) 2))))))))
795
796 (defun gnus-clear-inboxes-moved ()
797 (setq nnmail-moved-inboxes nil))
798 866
799 (defun gnus-mouse-pick-group (e) 867 (defun gnus-mouse-pick-group (e)
800 "Enter the group under the mouse pointer." 868 "Enter the group under the mouse pointer."
801 (interactive "e") 869 (interactive "e")
802 (mouse-set-point e) 870 (mouse-set-point e)
824 (unless (eq major-mode 'gnus-group-mode) 892 (unless (eq major-mode 'gnus-group-mode)
825 (gnus-group-mode) 893 (gnus-group-mode)
826 (when gnus-carpal 894 (when gnus-carpal
827 (gnus-carpal-setup-buffer 'group)))) 895 (gnus-carpal-setup-buffer 'group))))
828 896
897 (defsubst gnus-group-name-charset (method group)
898 (if (null method)
899 (setq method (gnus-find-method-for-group group)))
900 (let ((item (assoc method gnus-group-name-charset-method-alist))
901 (alist gnus-group-name-charset-group-alist)
902 result)
903 (if item
904 (cdr item)
905 (while (setq item (pop alist))
906 (if (string-match (car item) group)
907 (setq alist nil
908 result (cdr item))))
909 result)))
910
911 (defsubst gnus-group-name-decode (string charset)
912 (if (and string charset (featurep 'mule))
913 (mm-decode-coding-string string charset)
914 string))
915
916 (defun gnus-group-decoded-name (string)
917 (let ((charset (gnus-group-name-charset nil string)))
918 (gnus-group-name-decode string charset)))
919
829 (defun gnus-group-list-groups (&optional level unread lowest) 920 (defun gnus-group-list-groups (&optional level unread lowest)
830 "List newsgroups with level LEVEL or lower that have unread articles. 921 "List newsgroups with level LEVEL or lower that have unread articles.
831 Default is all subscribed groups. 922 Default is all subscribed groups.
832 If argument UNREAD is non-nil, groups with no unread articles are also 923 If argument UNREAD is non-nil, groups with no unread articles are also
833 listed. 924 listed.
838 (prefix-numeric-value current-prefix-arg) 929 (prefix-numeric-value current-prefix-arg)
839 (or 930 (or
840 (gnus-group-default-level nil t) 931 (gnus-group-default-level nil t)
841 gnus-group-default-list-level 932 gnus-group-default-list-level
842 gnus-level-subscribed)))) 933 gnus-level-subscribed))))
843 ;; Just do this here, for no particular good reason.
844 (gnus-clear-inboxes-moved)
845 (unless level 934 (unless level
846 (setq level (car gnus-group-list-mode) 935 (setq level (car gnus-group-list-mode)
847 unread (cdr gnus-group-list-mode))) 936 unread (cdr gnus-group-list-mode)))
848 (setq level (gnus-group-default-level level)) 937 (setq level (gnus-group-default-level level))
849 (gnus-group-setup-buffer) 938 (gnus-group-setup-buffer)
918 (setq info (car newsrc) 1007 (setq info (car newsrc)
919 group (gnus-info-group info) 1008 group (gnus-info-group info)
920 params (gnus-info-params info) 1009 params (gnus-info-params info)
921 newsrc (cdr newsrc) 1010 newsrc (cdr newsrc)
922 unread (car (gnus-gethash group gnus-newsrc-hashtb))) 1011 unread (car (gnus-gethash group gnus-newsrc-hashtb)))
923 (and unread ; This group might be bogus 1012 (and unread ; This group might be unchecked
924 (or (not regexp) 1013 (or (not regexp)
925 (string-match regexp group)) 1014 (string-match regexp group))
926 (<= (setq clevel (gnus-info-level info)) level) 1015 (<= (setq clevel (gnus-info-level info)) level)
927 (>= clevel lowest) 1016 (>= clevel lowest)
928 (or all ; We list all groups? 1017 (or all ; We list all groups?
969 (while groups 1058 (while groups
970 (setq group (pop groups)) 1059 (setq group (pop groups))
971 (when (string-match regexp group) 1060 (when (string-match regexp group)
972 (gnus-add-text-properties 1061 (gnus-add-text-properties
973 (point) (prog1 (1+ (point)) 1062 (point) (prog1 (1+ (point))
974 (insert " " mark " *: " group "\n")) 1063 (insert " " mark " *: "
1064 (gnus-group-name-decode group
1065 (gnus-group-name-charset
1066 nil group))
1067 "\n"))
975 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb) 1068 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
976 'gnus-unread t 1069 'gnus-unread t
977 'gnus-level level)))) 1070 'gnus-level level))))
978 ;; This loop is used when listing all groups. 1071 ;; This loop is used when listing all groups.
979 (while groups 1072 (while groups
1073 (setq group (pop groups))
980 (gnus-add-text-properties 1074 (gnus-add-text-properties
981 (point) (prog1 (1+ (point)) 1075 (point) (prog1 (1+ (point))
982 (insert " " mark " *: " 1076 (insert " " mark " *: "
983 (setq group (pop groups)) "\n")) 1077 (gnus-group-name-decode group
1078 (gnus-group-name-charset
1079 nil group))
1080 "\n"))
984 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb) 1081 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
985 'gnus-unread t 1082 'gnus-unread t
986 'gnus-level level)))))) 1083 'gnus-level level))))))
987 1084
988 (defun gnus-group-update-group-line () 1085 (defun gnus-group-update-group-line ()
1030 1127
1031 (defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level 1128 (defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level
1032 gnus-tmp-marked number 1129 gnus-tmp-marked number
1033 gnus-tmp-method) 1130 gnus-tmp-method)
1034 "Insert a group line in the group buffer." 1131 "Insert a group line in the group buffer."
1035 (let* ((gnus-tmp-active (gnus-active gnus-tmp-group)) 1132 (let* ((gnus-tmp-method
1133 (gnus-server-get-method gnus-tmp-group gnus-tmp-method))
1134 (group-name-charset (gnus-group-name-charset gnus-tmp-method
1135 gnus-tmp-group))
1136 (gnus-tmp-active (gnus-active gnus-tmp-group))
1036 (gnus-tmp-number-total 1137 (gnus-tmp-number-total
1037 (if gnus-tmp-active 1138 (if gnus-tmp-active
1038 (1+ (- (cdr gnus-tmp-active) (car gnus-tmp-active))) 1139 (1+ (- (cdr gnus-tmp-active) (car gnus-tmp-active)))
1039 0)) 1140 0))
1040 (gnus-tmp-number-of-unread 1141 (gnus-tmp-number-of-unread
1047 (gnus-tmp-subscribed 1148 (gnus-tmp-subscribed
1048 (cond ((<= gnus-tmp-level gnus-level-subscribed) ? ) 1149 (cond ((<= gnus-tmp-level gnus-level-subscribed) ? )
1049 ((<= gnus-tmp-level gnus-level-unsubscribed) ?U) 1150 ((<= gnus-tmp-level gnus-level-unsubscribed) ?U)
1050 ((= gnus-tmp-level gnus-level-zombie) ?Z) 1151 ((= gnus-tmp-level gnus-level-zombie) ?Z)
1051 (t ?K))) 1152 (t ?K)))
1052 (gnus-tmp-qualified-group (gnus-group-real-name gnus-tmp-group)) 1153 (gnus-tmp-qualified-group
1154 (gnus-group-name-decode (gnus-group-real-name gnus-tmp-group)
1155 group-name-charset))
1053 (gnus-tmp-newsgroup-description 1156 (gnus-tmp-newsgroup-description
1054 (if gnus-description-hashtb 1157 (if gnus-description-hashtb
1055 (or (gnus-gethash gnus-tmp-group gnus-description-hashtb) "") 1158 (or (gnus-group-name-decode
1159 (gnus-gethash gnus-tmp-group gnus-description-hashtb)
1160 group-name-charset) "")
1056 "")) 1161 ""))
1057 (gnus-tmp-moderated 1162 (gnus-tmp-moderated
1058 (if (and gnus-moderated-hashtb 1163 (if (and gnus-moderated-hashtb
1059 (gnus-gethash gnus-tmp-group gnus-moderated-hashtb)) 1164 (gnus-gethash gnus-tmp-group gnus-moderated-hashtb))
1060 ?m ? )) 1165 ?m ? ))
1061 (gnus-tmp-moderated-string 1166 (gnus-tmp-moderated-string
1062 (if (eq gnus-tmp-moderated ?m) "(m)" "")) 1167 (if (eq gnus-tmp-moderated ?m) "(m)" ""))
1063 (gnus-tmp-method 1168 (gnus-tmp-group-icon "==&&==")
1064 (gnus-server-get-method gnus-tmp-group gnus-tmp-method)) ;
1065 (gnus-tmp-news-server (or (cadr gnus-tmp-method) "")) 1169 (gnus-tmp-news-server (or (cadr gnus-tmp-method) ""))
1066 (gnus-tmp-news-method (or (car gnus-tmp-method) "")) 1170 (gnus-tmp-news-method (or (car gnus-tmp-method) ""))
1067 (gnus-tmp-news-method-string 1171 (gnus-tmp-news-method-string
1068 (if gnus-tmp-method 1172 (if gnus-tmp-method
1069 (format "(%s:%s)" (car gnus-tmp-method) 1173 (format "(%s:%s)" (car gnus-tmp-method)
1093 (string-to-int gnus-tmp-number-of-unread) 1197 (string-to-int gnus-tmp-number-of-unread)
1094 t) 1198 t)
1095 gnus-marked ,gnus-tmp-marked-mark 1199 gnus-marked ,gnus-tmp-marked-mark
1096 gnus-indentation ,gnus-group-indentation 1200 gnus-indentation ,gnus-group-indentation
1097 gnus-level ,gnus-tmp-level)) 1201 gnus-level ,gnus-tmp-level))
1202 (forward-line -1)
1098 (when (inline (gnus-visual-p 'group-highlight 'highlight)) 1203 (when (inline (gnus-visual-p 'group-highlight 'highlight))
1099 (forward-line -1) 1204 (gnus-run-hooks 'gnus-group-update-hook))
1100 (gnus-run-hooks 'gnus-group-update-hook) 1205 (forward-line)
1101 (forward-line))
1102 ;; Allow XEmacs to remove front-sticky text properties. 1206 ;; Allow XEmacs to remove front-sticky text properties.
1103 (gnus-group-remove-excess-properties))) 1207 (gnus-group-remove-excess-properties)))
1104 1208
1105 (defun gnus-group-highlight-line () 1209 (defun gnus-group-highlight-line ()
1106 "Highlight the current line according to `gnus-group-highlight'." 1210 "Highlight the current line according to `gnus-group-highlight'."
1315 1419
1316 ;;; Gnus group mode commands 1420 ;;; Gnus group mode commands
1317 1421
1318 ;; Group marking. 1422 ;; Group marking.
1319 1423
1424 (defun gnus-group-mark-line-p ()
1425 (save-excursion
1426 (beginning-of-line)
1427 (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
1428 (eq (char-after) gnus-process-mark)))
1429
1320 (defun gnus-group-mark-group (n &optional unmark no-advance) 1430 (defun gnus-group-mark-group (n &optional unmark no-advance)
1321 "Mark the current group." 1431 "Mark the current group."
1322 (interactive "p") 1432 (interactive "p")
1323 (let ((buffer-read-only nil) 1433 (let ((buffer-read-only nil)
1324 group) 1434 group)
1327 (when (setq group (gnus-group-group-name)) 1437 (when (setq group (gnus-group-group-name))
1328 ;; Go to the mark position. 1438 ;; Go to the mark position.
1329 (beginning-of-line) 1439 (beginning-of-line)
1330 (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2)) 1440 (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
1331 (subst-char-in-region 1441 (subst-char-in-region
1332 (point) (1+ (point)) (following-char) 1442 (point) (1+ (point)) (char-after)
1333 (if unmark 1443 (if unmark
1334 (progn 1444 (progn
1335 (setq gnus-group-marked (delete group gnus-group-marked)) 1445 (setq gnus-group-marked (delete group gnus-group-marked))
1336 ? ) 1446 ? )
1337 (setq gnus-group-marked 1447 (setq gnus-group-marked
1381 (while alist 1491 (while alist
1382 (when (string-match regexp (setq group (gnus-info-group (pop alist)))) 1492 (when (string-match regexp (setq group (gnus-info-group (pop alist))))
1383 (gnus-group-set-mark group)))) 1493 (gnus-group-set-mark group))))
1384 (gnus-group-position-point)) 1494 (gnus-group-position-point))
1385 1495
1386 (defun gnus-group-remove-mark (group) 1496 (defun gnus-group-remove-mark (group &optional test-marked)
1387 "Remove the process mark from GROUP and move point there. 1497 "Remove the process mark from GROUP and move point there.
1388 Return nil if the group isn't displayed." 1498 Return nil if the group isn't displayed."
1389 (if (gnus-group-goto-group group) 1499 (if (gnus-group-goto-group group nil test-marked)
1390 (save-excursion 1500 (save-excursion
1391 (gnus-group-mark-group 1 'unmark t) 1501 (gnus-group-mark-group 1 'unmark t)
1392 t) 1502 t)
1393 (setq gnus-group-marked 1503 (setq gnus-group-marked
1394 (delete group gnus-group-marked)) 1504 (delete group gnus-group-marked))
1463 (groups (make-symbol "gnus-group-iterate-groups")) 1573 (groups (make-symbol "gnus-group-iterate-groups"))
1464 (group (make-symbol "gnus-group-iterate-group"))) 1574 (group (make-symbol "gnus-group-iterate-group")))
1465 (eval 1575 (eval
1466 `(defun gnus-group-iterate (arg ,function) 1576 `(defun gnus-group-iterate (arg ,function)
1467 "Iterate FUNCTION over all process/prefixed groups. 1577 "Iterate FUNCTION over all process/prefixed groups.
1468 FUNCTION will be called with the group name as the paremeter 1578 FUNCTION will be called with the group name as the parameter
1469 and with point over the group in question." 1579 and with point over the group in question."
1470 (let ((,groups (gnus-group-process-prefix arg)) 1580 (let ((,groups (gnus-group-process-prefix arg))
1471 (,window (selected-window)) 1581 (,window (selected-window))
1472 ,group) 1582 ,group)
1473 (while (setq ,group (pop ,groups)) 1583 (while ,groups
1584 (setq ,group (car ,groups)
1585 ,groups (cdr ,groups))
1474 (select-window ,window) 1586 (select-window ,window)
1475 (gnus-group-remove-mark ,group) 1587 (gnus-group-remove-mark ,group)
1476 (save-selected-window 1588 (save-selected-window
1477 (save-excursion 1589 (save-excursion
1478 (funcall ,function ,group))))))))) 1590 (funcall ,function ,group)))))))))
1563 1675
1564 ;;;###autoload 1676 ;;;###autoload
1565 (defun gnus-fetch-group (group) 1677 (defun gnus-fetch-group (group)
1566 "Start Gnus if necessary and enter GROUP. 1678 "Start Gnus if necessary and enter GROUP.
1567 Returns whether the fetching was successful or not." 1679 Returns whether the fetching was successful or not."
1568 (interactive "sGroup name: ") 1680 (interactive (list (completing-read "Group name: " gnus-active-hashtb)))
1569 (unless (get-buffer gnus-group-buffer) 1681 (unless (get-buffer gnus-group-buffer)
1570 (gnus-no-server)) 1682 (gnus-no-server))
1571 (gnus-group-read-group nil nil group)) 1683 (gnus-group-read-group nil nil group))
1572 1684
1573 ;;;###autoload 1685 ;;;###autoload
1595 If QUIT-CONFIG, use that window configuration when exiting from the 1707 If QUIT-CONFIG, use that window configuration when exiting from the
1596 ephemeral group. 1708 ephemeral group.
1597 If REQUEST-ONLY, don't actually read the group; just request it. 1709 If REQUEST-ONLY, don't actually read the group; just request it.
1598 If SELECT-ARTICLES, only select those articles. 1710 If SELECT-ARTICLES, only select those articles.
1599 1711
1600 Return the name of the group is selection was successful." 1712 Return the name of the group if selection was successful."
1601 ;; Transform the select method into a unique server. 1713 ;; Transform the select method into a unique server.
1602 (when (stringp method) 1714 (when (stringp method)
1603 (setq method (gnus-server-to-method method))) 1715 (setq method (gnus-server-to-method method)))
1604 (setq method 1716 (setq method
1605 `(,(car method) ,(concat (cadr method) "-ephemeral") 1717 `(,(car method) ,(concat (cadr method) "-ephemeral")
1652 (gnus-group-update-group group) 1764 (gnus-group-update-group group)
1653 (gnus-group-goto-group group))) 1765 (gnus-group-goto-group group)))
1654 ;; Adjust cursor point. 1766 ;; Adjust cursor point.
1655 (gnus-group-position-point)) 1767 (gnus-group-position-point))
1656 1768
1657 (defun gnus-group-goto-group (group &optional far) 1769 (defun gnus-group-goto-group (group &optional far test-marked)
1658 "Goto to newsgroup GROUP. 1770 "Goto to newsgroup GROUP.
1659 If FAR, it is likely that the group is not on the current line." 1771 If FAR, it is likely that the group is not on the current line.
1772 If TEST-MARKED, the line must be marked."
1660 (when group 1773 (when group
1661 (if far 1774 (beginning-of-line)
1662 (gnus-goto-char 1775 (cond
1663 (text-property-any 1776 ;; It's quite likely that we are on the right line, so
1664 (point-min) (point-max) 1777 ;; we check the current line first.
1665 'gnus-group (gnus-intern-safe group gnus-active-hashtb))) 1778 ((and (not far)
1666 (beginning-of-line) 1779 (eq (get-text-property (point) 'gnus-group)
1667 (cond 1780 (gnus-intern-safe group gnus-active-hashtb))
1668 ;; It's quite likely that we are on the right line, so 1781 (or (not test-marked) (gnus-group-mark-line-p)))
1669 ;; we check the current line first. 1782 (point))
1670 ((eq (get-text-property (point) 'gnus-group) 1783 ;; Previous and next line are also likely, so we check them as well.
1671 (gnus-intern-safe group gnus-active-hashtb)) 1784 ((and (not far)
1672 (point)) 1785 (save-excursion
1673 ;; Previous and next line are also likely, so we check them as well. 1786 (forward-line -1)
1674 ((save-excursion 1787 (and (eq (get-text-property (point) 'gnus-group)
1675 (forward-line -1) 1788 (gnus-intern-safe group gnus-active-hashtb))
1676 (eq (get-text-property (point) 'gnus-group) 1789 (or (not test-marked) (gnus-group-mark-line-p)))))
1677 (gnus-intern-safe group gnus-active-hashtb))) 1790 (forward-line -1)
1678 (forward-line -1) 1791 (point))
1679 (point)) 1792 ((and (not far)
1680 ((save-excursion 1793 (save-excursion
1681 (forward-line 1) 1794 (forward-line 1)
1682 (eq (get-text-property (point) 'gnus-group) 1795 (and (eq (get-text-property (point) 'gnus-group)
1683 (gnus-intern-safe group gnus-active-hashtb))) 1796 (gnus-intern-safe group gnus-active-hashtb))
1684 (forward-line 1) 1797 (or (not test-marked) (gnus-group-mark-line-p)))))
1685 (point)) 1798 (forward-line 1)
1686 (t 1799 (point))
1687 ;; Search through the entire buffer. 1800 (test-marked
1688 (gnus-goto-char 1801 (goto-char (point-min))
1689 (text-property-any 1802 (let (found)
1690 (point-min) (point-max) 1803 (while (and (not found)
1691 'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))))) 1804 (gnus-goto-char
1805 (text-property-any
1806 (point) (point-max)
1807 'gnus-group
1808 (gnus-intern-safe group gnus-active-hashtb))))
1809 (if (gnus-group-mark-line-p)
1810 (setq found t)
1811 (forward-line 1)))
1812 found))
1813 (t
1814 ;; Search through the entire buffer.
1815 (gnus-goto-char
1816 (text-property-any
1817 (point-min) (point-max)
1818 'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))))
1692 1819
1693 (defun gnus-group-next-group (n &optional silent) 1820 (defun gnus-group-next-group (n &optional silent)
1694 "Go to next N'th newsgroup. 1821 "Go to next N'th newsgroup.
1695 If N is negative, search backward instead. 1822 If N is negative, search backward instead.
1696 Returns the difference between N and the number of skips actually 1823 Returns the difference between N and the number of skips actually
1802 (list 1929 (list
1803 (gnus-read-group "Group name: ") 1930 (gnus-read-group "Group name: ")
1804 (gnus-read-method "From method: "))) 1931 (gnus-read-method "From method: ")))
1805 1932
1806 (when (stringp method) 1933 (when (stringp method)
1807 (setq method (gnus-server-to-method method))) 1934 (setq method (or (gnus-server-to-method method) method)))
1808 (let* ((meth (when (and method 1935 (let* ((meth (gnus-method-simplify
1809 (not (gnus-server-equal method gnus-select-method))) 1936 (when (and method
1810 (if address (list (intern method) address) 1937 (not (gnus-server-equal method gnus-select-method)))
1811 method))) 1938 (if address (list (intern method) address)
1939 method))))
1812 (nname (if method (gnus-group-prefixed-name name meth) name)) 1940 (nname (if method (gnus-group-prefixed-name name meth) name))
1813 backend info) 1941 backend info)
1814 (when (gnus-gethash nname gnus-newsrc-hashtb) 1942 (when (gnus-gethash nname gnus-newsrc-hashtb)
1815 (error "Group %s already exists" nname)) 1943 (error "Group %s already exists" nname))
1816 ;; Subscribe to the new group. 1944 ;; Subscribe to the new group.
1841 (gnus-check-server meth) 1969 (gnus-check-server meth)
1842 (when (gnus-check-backend-function 'request-create-group nname) 1970 (when (gnus-check-backend-function 'request-create-group nname)
1843 (gnus-request-create-group nname nil args)) 1971 (gnus-request-create-group nname nil args))
1844 t)) 1972 t))
1845 1973
1846 (defun gnus-group-delete-group (group &optional force) 1974 (defun gnus-group-delete-groups (&optional arg)
1847 "Delete the current group. Only meaningful with mail groups. 1975 "Delete the current group. Only meaningful with editable groups."
1976 (interactive "P")
1977 (let ((n (length (gnus-group-process-prefix arg))))
1978 (when (gnus-yes-or-no-p
1979 (if (= n 1)
1980 "Delete this 1 group? "
1981 (format "Delete these %d groups? " n)))
1982 (gnus-group-iterate arg
1983 (lambda (group)
1984 (gnus-group-delete-group group nil t))))))
1985
1986 (defun gnus-group-delete-group (group &optional force no-prompt)
1987 "Delete the current group. Only meaningful with editable groups.
1848 If FORCE (the prefix) is non-nil, all the articles in the group will 1988 If FORCE (the prefix) is non-nil, all the articles in the group will
1849 be deleted. This is \"deleted\" as in \"removed forever from the face 1989 be deleted. This is \"deleted\" as in \"removed forever from the face
1850 of the Earth\". There is no undo. The user will be prompted before 1990 of the Earth\". There is no undo. The user will be prompted before
1851 doing the deletion." 1991 doing the deletion."
1852 (interactive 1992 (interactive
1855 (unless group 1995 (unless group
1856 (error "No group to rename")) 1996 (error "No group to rename"))
1857 (unless (gnus-check-backend-function 'request-delete-group group) 1997 (unless (gnus-check-backend-function 'request-delete-group group)
1858 (error "This backend does not support group deletion")) 1998 (error "This backend does not support group deletion"))
1859 (prog1 1999 (prog1
1860 (if (not (gnus-yes-or-no-p 2000 (if (and (not no-prompt)
1861 (format 2001 (not (gnus-yes-or-no-p
1862 "Do you really want to delete %s%s? " 2002 (format
1863 group (if force " and all its contents" "")))) 2003 "Do you really want to delete %s%s? "
2004 group (if force " and all its contents" "")))))
1864 () ; Whew! 2005 () ; Whew!
1865 (gnus-message 6 "Deleting group %s..." group) 2006 (gnus-message 6 "Deleting group %s..." group)
1866 (if (not (gnus-request-delete-group group force)) 2007 (if (not (gnus-request-delete-group group force))
1867 (gnus-error 3 "Couldn't delete group %s" group) 2008 (gnus-error 3 "Couldn't delete group %s" group)
1868 (gnus-message 6 "Deleting group %s...done" group) 2009 (gnus-message 6 "Deleting group %s...done" group)
1945 "Editing the %s for `%s'." 2086 "Editing the %s for `%s'."
1946 (cond 2087 (cond
1947 ((eq part 'method) "select method") 2088 ((eq part 'method) "select method")
1948 ((eq part 'params) "group parameters") 2089 ((eq part 'params) "group parameters")
1949 (t "group info")) 2090 (t "group info"))
1950 group) 2091 (gnus-group-decoded-name group))
1951 `(lambda (form) 2092 `(lambda (form)
1952 (gnus-group-edit-group-done ',part ,group form))))) 2093 (gnus-group-edit-group-done ',part ,group form)))))
1953 2094
1954 (defun gnus-group-edit-group-method (group) 2095 (defun gnus-group-edit-group-method (group)
1955 "Edit the select method of GROUP." 2096 "Edit the select method of GROUP."
2041 (setq found (cond ((= (setq char (read-char)) ?m) 'mbox) 2182 (setq found (cond ((= (setq char (read-char)) ?m) 'mbox)
2042 ((= char ?b) 'babyl) 2183 ((= char ?b) 'babyl)
2043 ((= char ?d) 'digest) 2184 ((= char ?d) 'digest)
2044 ((= char ?f) 'forward) 2185 ((= char ?f) 'forward)
2045 ((= char ?a) 'mmfd) 2186 ((= char ?a) 'mmfd)
2187 ((= char ?g) 'guess)
2046 (t (setq err (format "%c unknown. " char)) 2188 (t (setq err (format "%c unknown. " char))
2047 nil)))) 2189 nil))))
2048 (setq type found))) 2190 (setq type found)))
2049 (let* ((file (expand-file-name file)) 2191 (let* ((file (expand-file-name file))
2050 (name (gnus-generate-new-group-name 2192 (name (gnus-generate-new-group-name
2091 (gnus-group-read-ephemeral-group 2233 (gnus-group-read-ephemeral-group
2092 group method t 2234 group method t
2093 (cons (current-buffer) 2235 (cons (current-buffer)
2094 (if (eq major-mode 'gnus-summary-mode) 'summary 'group)))))) 2236 (if (eq major-mode 'gnus-summary-mode) 'summary 'group))))))
2095 2237
2238 (defvar nnwarchive-type-definition)
2239 (defvar gnus-group-warchive-type-history nil)
2240 (defvar gnus-group-warchive-login-history nil)
2241 (defvar gnus-group-warchive-address-history nil)
2242
2243 (defun gnus-group-make-warchive-group ()
2244 "Create a nnwarchive group."
2245 (interactive)
2246 (require 'nnwarchive)
2247 (let* ((group (gnus-read-group "Group name: "))
2248 (default-type (or (car gnus-group-warchive-type-history)
2249 (symbol-name (caar nnwarchive-type-definition))))
2250 (type
2251 (gnus-string-or
2252 (completing-read
2253 (format "Warchive type (default %s): " default-type)
2254 (mapcar (lambda (elem) (list (symbol-name (car elem))))
2255 nnwarchive-type-definition)
2256 nil t nil 'gnus-group-warchive-type-history)
2257 default-type))
2258 (address (read-string "Warchive address: "
2259 nil 'gnus-group-warchive-address-history))
2260 (default-login (or (car gnus-group-warchive-login-history)
2261 user-mail-address))
2262 (login
2263 (gnus-string-or
2264 (read-string
2265 (format "Warchive login (default %s): " user-mail-address)
2266 default-login 'gnus-group-warchive-login-history)
2267 user-mail-address))
2268 (method
2269 `(nnwarchive ,address
2270 (nnwarchive-type ,(intern type))
2271 (nnwarchive-login ,login))))
2272 (gnus-group-make-group group method)))
2273
2096 (defun gnus-group-make-archive-group (&optional all) 2274 (defun gnus-group-make-archive-group (&optional all)
2097 "Create the (ding) Gnus archive group of the most recent articles. 2275 "Create the (ding) Gnus archive group of the most recent articles.
2098 Given a prefix, create a full group." 2276 Given a prefix, create a full group."
2099 (interactive "P") 2277 (interactive "P")
2100 (let ((group (gnus-group-prefixed-name 2278 (let ((group (gnus-group-prefixed-name
2155 header))))) 2333 header)))))
2156 (push (list regexp nil nil 'r) regexps)) 2334 (push (list regexp nil nil 'r) regexps))
2157 (push (cons header regexps) scores)) 2335 (push (cons header regexps) scores))
2158 scores))) 2336 scores)))
2159 (gnus-group-make-group group "nnkiboze" address) 2337 (gnus-group-make-group group "nnkiboze" address)
2160 (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group)) 2338 (with-temp-file (gnus-score-file-name (concat "nnkiboze:" group))
2161 (let (emacs-lisp-mode-hook) 2339 (let (emacs-lisp-mode-hook)
2162 (pp scores (current-buffer))))) 2340 (pp scores (current-buffer)))))
2163 2341
2164 (defun gnus-group-add-to-virtual (n vgroup) 2342 (defun gnus-group-add-to-virtual (n vgroup)
2165 "Add the current group to a virtual group." 2343 "Add the current group to a virtual group."
2209 (cons (current-buffer) 2387 (cons (current-buffer)
2210 (if (eq major-mode 'gnus-summary-mode) 2388 (if (eq major-mode 'gnus-summary-mode)
2211 'summary 'group))) 2389 'summary 'group)))
2212 (error "Couldn't enter %s" dir)))) 2390 (error "Couldn't enter %s" dir))))
2213 2391
2392 (eval-and-compile
2393 (autoload 'nnimap-expunge "nnimap")
2394 (autoload 'nnimap-acl-get "nnimap")
2395 (autoload 'nnimap-acl-edit "nnimap"))
2396
2397 (defun gnus-group-nnimap-expunge (group)
2398 "Expunge deleted articles in current nnimap GROUP."
2399 (interactive (list (gnus-group-group-name)))
2400 (let ((mailbox (gnus-group-real-name group)) method)
2401 (unless group
2402 (error "No group on current line"))
2403 (unless (gnus-get-info group)
2404 (error "Killed group; can't be edited"))
2405 (unless (eq 'nnimap (car (setq method (gnus-find-method-for-group group))))
2406 (error "%s is not an nnimap group" group))
2407 (nnimap-expunge mailbox (cadr method))))
2408
2409 (defun gnus-group-nnimap-edit-acl (group)
2410 "Edit the Access Control List of current nnimap GROUP."
2411 (interactive (list (gnus-group-group-name)))
2412 (let ((mailbox (gnus-group-real-name group)) method acl)
2413 (unless group
2414 (error "No group on current line"))
2415 (unless (gnus-get-info group)
2416 (error "Killed group; can't be edited"))
2417 (unless (eq (car (setq method (gnus-find-method-for-group group))) 'nnimap)
2418 (error "%s is not an nnimap group" group))
2419 (gnus-edit-form (setq acl (nnimap-acl-get mailbox (cadr method)))
2420 (format "Editing the access control list for `%s'.
2421
2422 An access control list is a list of (identifier . rights) elements.
2423
2424 The identifier string specifies the corresponding user. The
2425 identifier \"anyone\" is reserved to refer to the universal identity.
2426
2427 Rights is a string listing a (possibly empty) set of alphanumeric
2428 characters, each character listing a set of operations which is being
2429 controlled. Letters are reserved for ``standard'' rights, listed
2430 below. Digits are reserved for implementation or site defined rights.
2431
2432 l - lookup (mailbox is visible to LIST/LSUB commands)
2433 r - read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
2434 SEARCH, COPY from mailbox)
2435 s - keep seen/unseen information across sessions (STORE \\SEEN flag)
2436 w - write (STORE flags other than \\SEEN and \\DELETED)
2437 i - insert (perform APPEND, COPY into mailbox)
2438 p - post (send mail to submission address for mailbox,
2439 not enforced by IMAP4 itself)
2440 c - create and delete mailbox (CREATE new sub-mailboxes in any
2441 implementation-defined hierarchy, RENAME or DELETE mailbox)
2442 d - delete messages (STORE \\DELETED flag, perform EXPUNGE)
2443 a - administer (perform SETACL)" group)
2444 `(lambda (form)
2445 (nnimap-acl-edit
2446 ,mailbox ',method ',acl form)))))
2447
2214 ;; Group sorting commands 2448 ;; Group sorting commands
2215 ;; Suggested by Joe Hildebrand <hildjj@idaho.fuentez.com>. 2449 ;; Suggested by Joe Hildebrand <hildjj@idaho.fuentez.com>.
2216 2450
2217 (defun gnus-group-sort-groups (func &optional reverse) 2451 (defun gnus-group-sort-groups (func &optional reverse)
2218 "Sort the group buffer according to FUNC. 2452 "Sort the group buffer according to FUNC.
2300 (when reverse 2534 (when reverse
2301 (setq infos (nreverse infos))) 2535 (setq infos (nreverse infos)))
2302 ;; Go through all the infos and replace the old entries 2536 ;; Go through all the infos and replace the old entries
2303 ;; with the new infos. 2537 ;; with the new infos.
2304 (while infos 2538 (while infos
2305 (setcar entries (pop infos)) 2539 (setcar (car entries) (pop infos))
2306 (pop entries)) 2540 (pop entries))
2307 ;; Update the hashtable. 2541 ;; Update the hashtable.
2308 (gnus-make-hashtable-from-newsrc-alist))) 2542 (gnus-make-hashtable-from-newsrc-alist)))
2309 2543
2310 (defun gnus-group-sort-selected-groups-by-alphabet (&optional reverse) 2544 (defun gnus-group-sort-selected-groups-by-alphabet (&optional n reverse)
2311 "Sort the group buffer alphabetically by group name. 2545 "Sort the group buffer alphabetically by group name.
2312 If REVERSE, sort in reverse order." 2546 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2313 (interactive "P") 2547 sort in reverse order."
2314 (gnus-group-sort-selected-groups 'gnus-group-sort-by-alphabet reverse)) 2548 (interactive (gnus-interactive "P\ny"))
2315 2549 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-alphabet reverse))
2316 (defun gnus-group-sort-selected-groups-by-unread (&optional reverse) 2550
2551 (defun gnus-group-sort-selected-groups-by-unread (&optional n reverse)
2317 "Sort the group buffer by number of unread articles. 2552 "Sort the group buffer by number of unread articles.
2318 If REVERSE, sort in reverse order." 2553 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2319 (interactive "P") 2554 sort in reverse order."
2320 (gnus-group-sort-selected-groups 'gnus-group-sort-by-unread reverse)) 2555 (interactive (gnus-interactive "P\ny"))
2321 2556 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-unread reverse))
2322 (defun gnus-group-sort-selected-groups-by-level (&optional reverse) 2557
2558 (defun gnus-group-sort-selected-groups-by-level (&optional n reverse)
2323 "Sort the group buffer by group level. 2559 "Sort the group buffer by group level.
2324 If REVERSE, sort in reverse order." 2560 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2325 (interactive "P") 2561 sort in reverse order."
2326 (gnus-group-sort-selected-groups 'gnus-group-sort-by-level reverse)) 2562 (interactive (gnus-interactive "P\ny"))
2327 2563 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-level reverse))
2328 (defun gnus-group-sort-selected-groups-by-score (&optional reverse) 2564
2565 (defun gnus-group-sort-selected-groups-by-score (&optional n reverse)
2329 "Sort the group buffer by group score. 2566 "Sort the group buffer by group score.
2330 If REVERSE, sort in reverse order." 2567 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2331 (interactive "P") 2568 sort in reverse order."
2332 (gnus-group-sort-selected-groups 'gnus-group-sort-by-score reverse)) 2569 (interactive (gnus-interactive "P\ny"))
2333 2570 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-score reverse))
2334 (defun gnus-group-sort-selected-groups-by-rank (&optional reverse) 2571
2572 (defun gnus-group-sort-selected-groups-by-rank (&optional n reverse)
2335 "Sort the group buffer by group rank. 2573 "Sort the group buffer by group rank.
2336 If REVERSE, sort in reverse order." 2574 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2337 (interactive "P") 2575 sort in reverse order."
2338 (gnus-group-sort-selected-groups 'gnus-group-sort-by-rank reverse)) 2576 (interactive (gnus-interactive "P\ny"))
2339 2577 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-rank reverse))
2340 (defun gnus-group-sort-selected-groups-by-method (&optional reverse) 2578
2579 (defun gnus-group-sort-selected-groups-by-method (&optional n reverse)
2341 "Sort the group buffer alphabetically by backend name. 2580 "Sort the group buffer alphabetically by backend name.
2342 If REVERSE, sort in reverse order." 2581 Obeys the process/prefix convention. If REVERSE (the symbolic prefix),
2343 (interactive "P") 2582 sort in reverse order."
2344 (gnus-group-sort-selected-groups 'gnus-group-sort-by-method reverse)) 2583 (interactive (gnus-interactive "P\ny"))
2584 (gnus-group-sort-selected-groups n 'gnus-group-sort-by-method reverse))
2345 2585
2346 ;;; Sorting predicates. 2586 ;;; Sorting predicates.
2347 2587
2348 (defun gnus-group-sort-by-alphabet (info1 info2) 2588 (defun gnus-group-sort-by-alphabet (info1 info2)
2349 "Sort alphabetically." 2589 "Sort alphabetically."
2426 (gnus-info-set-marks info nil)))) 2666 (gnus-info-set-marks info nil))))
2427 2667
2428 ;; Group catching up. 2668 ;; Group catching up.
2429 2669
2430 (defun gnus-group-catchup-current (&optional n all) 2670 (defun gnus-group-catchup-current (&optional n all)
2431 "Mark all articles not marked as unread in current newsgroup as read. 2671 "Mark all unread articles in the current newsgroup as read.
2432 If prefix argument N is numeric, the next N newsgroups will be 2672 If prefix argument N is numeric, the next N newsgroups will be
2433 caught up. If ALL is non-nil, marked articles will also be marked as 2673 caught up. If ALL is non-nil, marked articles will also be marked as
2434 read. Cross references (Xref: header) of articles are ignored. 2674 read. Cross references (Xref: header) of articles are ignored.
2435 The number of newsgroups that this function was unable to catch 2675 The number of newsgroups that this function was unable to catch
2436 up is returned." 2676 up is returned."
2437 (interactive "P") 2677 (interactive "P")
2438 (let ((groups (gnus-group-process-prefix n)) 2678 (let ((groups (gnus-group-process-prefix n))
2439 (ret 0)) 2679 (ret 0)
2680 group)
2440 (unless groups (error "No groups selected")) 2681 (unless groups (error "No groups selected"))
2441 (if (not 2682 (if (not
2442 (or (not gnus-interactive-catchup) ;Without confirmation? 2683 (or (not gnus-interactive-catchup) ;Without confirmation?
2443 gnus-expert-user 2684 gnus-expert-user
2444 (gnus-y-or-n-p 2685 (gnus-y-or-n-p
2448 "Mark all unread articles in %s as read? ") 2689 "Mark all unread articles in %s as read? ")
2449 (if (= (length groups) 1) 2690 (if (= (length groups) 1)
2450 (car groups) 2691 (car groups)
2451 (format "these %d groups" (length groups))))))) 2692 (format "these %d groups" (length groups)))))))
2452 n 2693 n
2453 (while groups 2694 (while (setq group (pop groups))
2695 (gnus-group-remove-mark group)
2454 ;; Virtual groups have to be given special treatment. 2696 ;; Virtual groups have to be given special treatment.
2455 (let ((method (gnus-find-method-for-group (car groups)))) 2697 (let ((method (gnus-find-method-for-group group)))
2456 (when (eq 'nnvirtual (car method)) 2698 (when (eq 'nnvirtual (car method))
2457 (nnvirtual-catchup-group 2699 (nnvirtual-catchup-group
2458 (gnus-group-real-name (car groups)) (nth 1 method) all))) 2700 (gnus-group-real-name group) (nth 1 method) all)))
2459 (gnus-group-remove-mark (car groups)) 2701 (if (>= (gnus-group-level group) gnus-level-zombie)
2460 (if (>= (gnus-group-group-level) gnus-level-zombie)
2461 (gnus-message 2 "Dead groups can't be caught up") 2702 (gnus-message 2 "Dead groups can't be caught up")
2462 (if (prog1 2703 (if (prog1
2463 (gnus-group-goto-group (car groups)) 2704 (gnus-group-goto-group group)
2464 (gnus-group-catchup (car groups) all)) 2705 (gnus-group-catchup group all))
2465 (gnus-group-update-group-line) 2706 (gnus-group-update-group-line)
2466 (setq ret (1+ ret)))) 2707 (setq ret (1+ ret)))))
2467 (setq groups (cdr groups)))
2468 (gnus-group-next-unread-group 1) 2708 (gnus-group-next-unread-group 1)
2469 ret))) 2709 ret)))
2470 2710
2471 (defun gnus-group-catchup-current-all (&optional n) 2711 (defun gnus-group-catchup-current-all (&optional n)
2472 "Mark all articles in current newsgroup as read. 2712 "Mark all articles in current newsgroup as read.
2479 If ALL is non-nil, all articles are marked as read. 2719 If ALL is non-nil, all articles are marked as read.
2480 The return value is the number of articles that were marked as read, 2720 The return value is the number of articles that were marked as read,
2481 or nil if no action could be taken." 2721 or nil if no action could be taken."
2482 (let* ((entry (gnus-gethash group gnus-newsrc-hashtb)) 2722 (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
2483 (num (car entry))) 2723 (num (car entry)))
2724 ;; Remove entries for this group.
2725 (nnmail-purge-split-history (gnus-group-real-name group))
2484 ;; Do the updating only if the newsgroup isn't killed. 2726 ;; Do the updating only if the newsgroup isn't killed.
2485 (if (not (numberp (car entry))) 2727 (if (not (numberp (car entry)))
2486 (gnus-message 1 "Can't catch up %s; non-active group" group) 2728 (gnus-message 1 "Can't catch up %s; non-active group" group)
2487 ;; Do auto-expirable marks if that's required. 2729 ;; Do auto-expirable marks if that's required.
2488 (when (gnus-group-auto-expirable-p group) 2730 (when (gnus-group-auto-expirable-p group)
2511 group) 2753 group)
2512 (unless groups 2754 (unless groups
2513 (error "No groups to expire")) 2755 (error "No groups to expire"))
2514 (while (setq group (pop groups)) 2756 (while (setq group (pop groups))
2515 (gnus-group-remove-mark group) 2757 (gnus-group-remove-mark group)
2516 (when (gnus-check-backend-function 'request-expire-articles group) 2758 (gnus-group-expire-articles-1 group)
2517 (gnus-message 6 "Expiring articles in %s..." group)
2518 (let* ((info (gnus-get-info group))
2519 (expirable (if (gnus-group-total-expirable-p group)
2520 (cons nil (gnus-list-of-read-articles group))
2521 (assq 'expire (gnus-info-marks info))))
2522 (expiry-wait (gnus-group-find-parameter group 'expiry-wait)))
2523 (when expirable
2524 (setcdr
2525 expirable
2526 (gnus-compress-sequence
2527 (if expiry-wait
2528 ;; We set the expiry variables to the group
2529 ;; parameter.
2530 (let ((nnmail-expiry-wait-function nil)
2531 (nnmail-expiry-wait expiry-wait))
2532 (gnus-request-expire-articles
2533 (gnus-uncompress-sequence (cdr expirable)) group))
2534 ;; Just expire using the normal expiry values.
2535 (gnus-request-expire-articles
2536 (gnus-uncompress-sequence (cdr expirable)) group))))
2537 (gnus-close-group group))
2538 (gnus-message 6 "Expiring articles in %s...done" group)))
2539 (gnus-dribble-touch) 2759 (gnus-dribble-touch)
2540 (gnus-group-position-point)))) 2760 (gnus-group-position-point))))
2761
2762 (defun gnus-group-expire-articles-1 (group)
2763 (when (gnus-check-backend-function 'request-expire-articles group)
2764 (gnus-message 6 "Expiring articles in %s..." group)
2765 (let* ((info (gnus-get-info group))
2766 (expirable (if (gnus-group-total-expirable-p group)
2767 (cons nil (gnus-list-of-read-articles group))
2768 (assq 'expire (gnus-info-marks info))))
2769 (expiry-wait (gnus-group-find-parameter group 'expiry-wait))
2770 (nnmail-expiry-target
2771 (or (gnus-group-find-parameter group 'expiry-target)
2772 nnmail-expiry-target)))
2773 (when expirable
2774 (gnus-check-group group)
2775 (setcdr
2776 expirable
2777 (gnus-compress-sequence
2778 (if expiry-wait
2779 ;; We set the expiry variables to the group
2780 ;; parameter.
2781 (let ((nnmail-expiry-wait-function nil)
2782 (nnmail-expiry-wait expiry-wait))
2783 (gnus-request-expire-articles
2784 (gnus-uncompress-sequence (cdr expirable)) group))
2785 ;; Just expire using the normal expiry values.
2786 (gnus-request-expire-articles
2787 (gnus-uncompress-sequence (cdr expirable)) group))))
2788 (gnus-close-group group))
2789 (gnus-message 6 "Expiring articles in %s...done" group)
2790 ;; Return the list of un-expired articles.
2791 (cdr expirable))))
2541 2792
2542 (defun gnus-group-expire-all-groups () 2793 (defun gnus-group-expire-all-groups ()
2543 "Expire all expirable articles in all newsgroups." 2794 "Expire all expirable articles in all newsgroups."
2544 (interactive) 2795 (interactive)
2545 (save-excursion 2796 (save-excursion
2563 (if (string-match "^\\s-*$" s) 2814 (if (string-match "^\\s-*$" s)
2564 (int-to-string (or (gnus-group-group-level) 2815 (int-to-string (or (gnus-group-group-level)
2565 gnus-level-default-subscribed)) 2816 gnus-level-default-subscribed))
2566 s))))) 2817 s)))))
2567 (unless (and (>= level 1) (<= level gnus-level-killed)) 2818 (unless (and (>= level 1) (<= level gnus-level-killed))
2568 (error "Illegal level: %d" level)) 2819 (error "Invalid level: %d" level))
2569 (let ((groups (gnus-group-process-prefix n)) 2820 (let ((groups (gnus-group-process-prefix n))
2570 group) 2821 group)
2571 (while (setq group (pop groups)) 2822 (while (setq group (pop groups))
2572 (gnus-group-remove-mark group) 2823 (gnus-group-remove-mark group)
2573 (gnus-message 6 "Changed level of %s from %d to %d" 2824 (gnus-message 6 "Changed level of %s from %d to %d"
2664 (prog1 2915 (prog1
2665 (forward-line (- n)) 2916 (forward-line (- n))
2666 (gnus-group-yank-group) 2917 (gnus-group-yank-group)
2667 (gnus-group-position-point))) 2918 (gnus-group-position-point)))
2668 2919
2669 (defun gnus-group-kill-all-zombies () 2920 (defun gnus-group-kill-all-zombies (&optional dummy)
2670 "Kill all zombie newsgroups." 2921 "Kill all zombie newsgroups.
2671 (interactive) 2922 The optional DUMMY should always be nil."
2672 (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list)) 2923 (interactive (list (not (gnus-yes-or-no-p "Really kill all zombies? "))))
2673 (setq gnus-zombie-list nil) 2924 (unless dummy
2674 (gnus-dribble-touch) 2925 (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list))
2675 (gnus-group-list-groups)) 2926 (setq gnus-zombie-list nil)
2927 (gnus-dribble-touch)
2928 (gnus-group-list-groups)))
2676 2929
2677 (defun gnus-group-kill-region (begin end) 2930 (defun gnus-group-kill-region (begin end)
2678 "Kill newsgroups in current region (excluding current point). 2931 "Kill newsgroups in current region (excluding current point).
2679 The killed newsgroups can be yanked by using \\[gnus-group-yank-group]." 2932 The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
2680 (interactive "r") 2933 (interactive "r")
2719 (gnus-group-goto-group ,(gnus-group-group-name)) 2972 (gnus-group-goto-group ,(gnus-group-group-name))
2720 (gnus-group-yank-group))) 2973 (gnus-group-yank-group)))
2721 (push (cons (car entry) (nth 2 entry)) 2974 (push (cons (car entry) (nth 2 entry))
2722 gnus-list-of-killed-groups)) 2975 gnus-list-of-killed-groups))
2723 (gnus-group-change-level 2976 (gnus-group-change-level
2724 (if entry entry group) gnus-level-killed (if entry nil level))) 2977 (if entry entry group) gnus-level-killed (if entry nil level))
2978 (message "Killed group %s" group))
2725 ;; If there are lots and lots of groups to be killed, we use 2979 ;; If there are lots and lots of groups to be killed, we use
2726 ;; this thing instead. 2980 ;; this thing instead.
2727 (let (entry) 2981 (let (entry)
2728 (setq groups (nreverse groups)) 2982 (setq groups (nreverse groups))
2729 (while groups 2983 (while groups
2805 (setq prev alist)) 3059 (setq prev alist))
2806 (setq alist (cdr alist))) 3060 (setq alist (cdr alist)))
2807 (gnus-make-hashtable-from-newsrc-alist) 3061 (gnus-make-hashtable-from-newsrc-alist)
2808 (gnus-group-list-groups))) 3062 (gnus-group-list-groups)))
2809 (t 3063 (t
2810 (error "Can't kill; illegal level: %d" level)))) 3064 (error "Can't kill; invalid level: %d" level))))
2811 3065
2812 (defun gnus-group-list-all-groups (&optional arg) 3066 (defun gnus-group-list-all-groups (&optional arg)
2813 "List all newsgroups with level ARG or lower. 3067 "List all newsgroups with level ARG or lower.
2814 Default is gnus-level-unsubscribed, which lists all subscribed and most 3068 Default is gnus-level-unsubscribed, which lists all subscribed and most
2815 unsubscribed groups." 3069 unsubscribed groups."
2848 (defun gnus-group-list-active () 3102 (defun gnus-group-list-active ()
2849 "List all groups that are available from the server(s)." 3103 "List all groups that are available from the server(s)."
2850 (interactive) 3104 (interactive)
2851 ;; First we make sure that we have really read the active file. 3105 ;; First we make sure that we have really read the active file.
2852 (unless (gnus-read-active-file-p) 3106 (unless (gnus-read-active-file-p)
2853 (let ((gnus-read-active-file t)) 3107 (let ((gnus-read-active-file t)
3108 (gnus-agent nil)) ; Trick the agent into ignoring the active file.
2854 (gnus-read-active-file))) 3109 (gnus-read-active-file)))
2855 ;; Find all groups and sort them. 3110 ;; Find all groups and sort them.
2856 (let ((groups 3111 (let ((groups
2857 (sort 3112 (sort
2858 (let (list) 3113 (let (list)
2866 'string<)) 3121 'string<))
2867 (buffer-read-only nil) 3122 (buffer-read-only nil)
2868 group) 3123 group)
2869 (erase-buffer) 3124 (erase-buffer)
2870 (while groups 3125 (while groups
3126 (setq group (pop groups))
2871 (gnus-add-text-properties 3127 (gnus-add-text-properties
2872 (point) (prog1 (1+ (point)) 3128 (point) (prog1 (1+ (point))
2873 (insert " *: " 3129 (insert " *: "
2874 (setq group (pop groups)) "\n")) 3130 (gnus-group-name-decode group
3131 (gnus-group-name-charset
3132 nil group))
3133 "\n"))
2875 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb) 3134 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
2876 'gnus-unread t 3135 'gnus-unread t
2877 'gnus-level (inline (gnus-group-level group))))) 3136 'gnus-level (inline (gnus-group-level group)))))
2878 (goto-char (point-min)))) 3137 (goto-char (point-min))))
2879 3138
2888 "Get newly arrived articles. 3147 "Get newly arrived articles.
2889 If ARG is a number, it specifies which levels you are interested in 3148 If ARG is a number, it specifies which levels you are interested in
2890 re-scanning. If ARG is non-nil and not a number, this will force 3149 re-scanning. If ARG is non-nil and not a number, this will force
2891 \"hard\" re-reading of the active files from all servers." 3150 \"hard\" re-reading of the active files from all servers."
2892 (interactive "P") 3151 (interactive "P")
2893 (let ((gnus-inhibit-demon t)) 3152 (require 'nnmail)
3153 (let ((gnus-inhibit-demon t)
3154 ;; Binding this variable will inhibit multiple fetchings
3155 ;; of the same mail source.
3156 (nnmail-fetched-sources (list t)))
2894 (gnus-run-hooks 'gnus-get-new-news-hook) 3157 (gnus-run-hooks 'gnus-get-new-news-hook)
2895 3158
2896 ;; Read any slave files. 3159 ;; Read any slave files.
2897 (unless gnus-slave 3160 (unless gnus-slave
2898 (gnus-master-read-slave-newsrc)) 3161 (gnus-master-read-slave-newsrc))
2929 (interactive "P") 3192 (interactive "P")
2930 (let* ((groups (gnus-group-process-prefix n)) 3193 (let* ((groups (gnus-group-process-prefix n))
2931 (ret (if (numberp n) (- n (length groups)) 0)) 3194 (ret (if (numberp n) (- n (length groups)) 0))
2932 (beg (unless n 3195 (beg (unless n
2933 (point))) 3196 (point)))
2934 group method) 3197 group method
3198 (gnus-inhibit-demon t)
3199 ;; Binding this variable will inhibit multiple fetchings
3200 ;; of the same mail source.
3201 (nnmail-fetched-sources (list t)))
3202 (gnus-run-hooks 'gnus-get-new-news-hook)
2935 (while (setq group (pop groups)) 3203 (while (setq group (pop groups))
2936 (gnus-group-remove-mark group) 3204 (gnus-group-remove-mark group)
2937 ;; Bypass any previous denials from the server. 3205 ;; Bypass any previous denials from the server.
2938 (gnus-remove-denial (setq method (gnus-find-method-for-group group))) 3206 (gnus-remove-denial (setq method (gnus-find-method-for-group group)))
2939 (if (gnus-activate-group group (if dont-scan nil 'scan)) 3207 (if (gnus-activate-group group (if dont-scan nil 'scan))
2940 (progn 3208 (progn
2941 (gnus-get-unread-articles-in-group 3209 (gnus-get-unread-articles-in-group
2942 (gnus-get-info group) (gnus-active group) t) 3210 (gnus-get-info group) (gnus-active group) t)
2943 (unless (gnus-virtual-group-p group) 3211 (unless (gnus-virtual-group-p group)
2944 (gnus-close-group group)) 3212 (gnus-close-group group))
2945 (gnus-agent-save-group-info 3213 (when gnus-agent
2946 method (gnus-group-real-name group) (gnus-active group)) 3214 (gnus-agent-save-group-info
3215 method (gnus-group-real-name group) (gnus-active group)))
2947 (gnus-group-update-group group)) 3216 (gnus-group-update-group group))
2948 (if (eq (gnus-server-status (gnus-find-method-for-group group)) 3217 (if (eq (gnus-server-status (gnus-find-method-for-group group))
2949 'denied) 3218 'denied)
2950 (gnus-error 3 "Server denied access") 3219 (gnus-error 3 "Server denied access")
2951 (gnus-error 3 "%s error: %s" group (gnus-status-message group))))) 3220 (gnus-error 3 "%s error: %s" group (gnus-status-message group)))))
3018 b) 3287 b)
3019 (erase-buffer) 3288 (erase-buffer)
3020 (mapatoms 3289 (mapatoms
3021 (lambda (group) 3290 (lambda (group)
3022 (setq b (point)) 3291 (setq b (point))
3023 (insert (format " *: %-20s %s\n" (symbol-name group) 3292 (let ((charset (gnus-group-name-charset nil (symbol-name group))))
3024 (symbol-value group))) 3293 (insert (format " *: %-20s %s\n"
3294 (gnus-group-name-decode
3295 (symbol-name group) charset)
3296 (gnus-group-name-decode
3297 (symbol-value group) charset))))
3025 (gnus-add-text-properties 3298 (gnus-add-text-properties
3026 b (1+ b) (list 'gnus-group group 3299 b (1+ b) (list 'gnus-group group
3027 'gnus-unread t 'gnus-marked nil 3300 'gnus-unread t 'gnus-marked nil
3028 'gnus-level (1+ gnus-level-subscribed)))) 3301 'gnus-level (1+ gnus-level-subscribed))))
3029 gnus-description-hashtb) 3302 gnus-description-hashtb)
3055 (if (not groups) 3328 (if (not groups)
3056 (gnus-message 3 "No groups matched \"%s\"." regexp) 3329 (gnus-message 3 "No groups matched \"%s\"." regexp)
3057 ;; Print out all the groups. 3330 ;; Print out all the groups.
3058 (save-excursion 3331 (save-excursion
3059 (pop-to-buffer "*Gnus Help*") 3332 (pop-to-buffer "*Gnus Help*")
3060 (buffer-disable-undo (current-buffer)) 3333 (buffer-disable-undo)
3061 (erase-buffer) 3334 (erase-buffer)
3062 (setq groups (sort groups 'string<)) 3335 (setq groups (sort groups 'string<))
3063 (while groups 3336 (while groups
3064 ;; Groups may be entered twice into the list of groups. 3337 ;; Groups may be entered twice into the list of groups.
3065 (when (not (string= (car groups) prev)) 3338 (when (not (string= (car groups) prev))
3066 (insert (setq prev (car groups)) "\n") 3339 (setq prev (car groups))
3067 (when (and gnus-description-hashtb 3340 (let ((charset (gnus-group-name-charset nil prev)))
3068 (setq des (gnus-gethash (car groups) 3341 (insert (gnus-group-name-decode prev charset) "\n")
3069 gnus-description-hashtb))) 3342 (when (and gnus-description-hashtb
3070 (insert " " des "\n"))) 3343 (setq des (gnus-gethash (car groups)
3344 gnus-description-hashtb)))
3345 (insert " " (gnus-group-name-decode des charset) "\n"))))
3071 (setq groups (cdr groups))) 3346 (setq groups (cdr groups)))
3072 (goto-char (point-min)))) 3347 (goto-char (point-min))))
3073 (pop-to-buffer obuf))) 3348 (pop-to-buffer obuf)))
3074 3349
3075 (defun gnus-group-description-apropos (regexp) 3350 (defun gnus-group-description-apropos (regexp)
3265 ;; We got a server name. 3540 ;; We got a server name.
3266 how)))) 3541 how))))
3267 (gnus-browse-foreign-server method)) 3542 (gnus-browse-foreign-server method))
3268 3543
3269 (defun gnus-group-set-info (info &optional method-only-group part) 3544 (defun gnus-group-set-info (info &optional method-only-group part)
3270 (let* ((entry (gnus-gethash 3545 (when (or info part)
3271 (or method-only-group (gnus-info-group info)) 3546 (let* ((entry (gnus-gethash
3272 gnus-newsrc-hashtb)) 3547 (or method-only-group (gnus-info-group info))
3273 (part-info info) 3548 gnus-newsrc-hashtb))
3274 (info (if method-only-group (nth 2 entry) info)) 3549 (part-info info)
3275 method) 3550 (info (if method-only-group (nth 2 entry) info))
3276 (when method-only-group 3551 method)
3552 (when method-only-group
3553 (unless entry
3554 (error "Trying to change non-existent group %s" method-only-group))
3555 ;; We have received parts of the actual group info - either the
3556 ;; select method or the group parameters. We first check
3557 ;; whether we have to extend the info, and if so, do that.
3558 (let ((len (length info))
3559 (total (if (eq part 'method) 5 6)))
3560 (when (< len total)
3561 (setcdr (nthcdr (1- len) info)
3562 (make-list (- total len) nil)))
3563 ;; Then we enter the new info.
3564 (setcar (nthcdr (1- total) info) part-info)))
3277 (unless entry 3565 (unless entry
3278 (error "Trying to change non-existent group %s" method-only-group)) 3566 ;; This is a new group, so we just create it.
3279 ;; We have received parts of the actual group info - either the
3280 ;; select method or the group parameters. We first check
3281 ;; whether we have to extend the info, and if so, do that.
3282 (let ((len (length info))
3283 (total (if (eq part 'method) 5 6)))
3284 (when (< len total)
3285 (setcdr (nthcdr (1- len) info)
3286 (make-list (- total len) nil)))
3287 ;; Then we enter the new info.
3288 (setcar (nthcdr (1- total) info) part-info)))
3289 (unless entry
3290 ;; This is a new group, so we just create it.
3291 (save-excursion
3292 (set-buffer gnus-group-buffer)
3293 (setq method (gnus-info-method info))
3294 (when (gnus-server-equal method "native")
3295 (setq method nil))
3296 (save-excursion 3567 (save-excursion
3297 (set-buffer gnus-group-buffer) 3568 (set-buffer gnus-group-buffer)
3298 (if method 3569 (setq method (gnus-info-method info))
3299 ;; It's a foreign group... 3570 (when (gnus-server-equal method "native")
3300 (gnus-group-make-group 3571 (setq method nil))
3301 (gnus-group-real-name (gnus-info-group info)) 3572 (save-excursion
3302 (if (stringp method) method 3573 (set-buffer gnus-group-buffer)
3303 (prin1-to-string (car method))) 3574 (if method
3304 (and (consp method) 3575 ;; It's a foreign group...
3305 (nth 1 (gnus-info-method info)))) 3576 (gnus-group-make-group
3306 ;; It's a native group. 3577 (gnus-group-real-name (gnus-info-group info))
3307 (gnus-group-make-group (gnus-info-group info)))) 3578 (if (stringp method) method
3308 (gnus-message 6 "Note: New group created") 3579 (prin1-to-string (car method)))
3309 (setq entry 3580 (and (consp method)
3310 (gnus-gethash (gnus-group-prefixed-name 3581 (nth 1 (gnus-info-method info))))
3311 (gnus-group-real-name (gnus-info-group info)) 3582 ;; It's a native group.
3312 (or (gnus-info-method info) gnus-select-method)) 3583 (gnus-group-make-group (gnus-info-group info))))
3313 gnus-newsrc-hashtb)))) 3584 (gnus-message 6 "Note: New group created")
3314 ;; Whether it was a new group or not, we now have the entry, so we 3585 (setq entry
3315 ;; can do the update. 3586 (gnus-gethash (gnus-group-prefixed-name
3316 (if entry 3587 (gnus-group-real-name (gnus-info-group info))
3317 (progn 3588 (or (gnus-info-method info) gnus-select-method))
3318 (setcar (nthcdr 2 entry) info) 3589 gnus-newsrc-hashtb))))
3319 (when (and (not (eq (car entry) t)) 3590 ;; Whether it was a new group or not, we now have the entry, so we
3320 (gnus-active (gnus-info-group info))) 3591 ;; can do the update.
3321 (setcar entry (length (gnus-list-of-unread-articles (car info)))))) 3592 (if entry
3322 (error "No such group: %s" (gnus-info-group info))))) 3593 (progn
3594 (setcar (nthcdr 2 entry) info)
3595 (when (and (not (eq (car entry) t))
3596 (gnus-active (gnus-info-group info)))
3597 (setcar entry (length (gnus-list-of-unread-articles (car info))))))
3598 (error "No such group: %s" (gnus-info-group info))))))
3323 3599
3324 (defun gnus-group-set-method-info (group select-method) 3600 (defun gnus-group-set-method-info (group select-method)
3325 (gnus-group-set-info select-method group 'method)) 3601 (gnus-group-set-info select-method group 'method))
3326 3602
3327 (defun gnus-group-set-params-info (group params) 3603 (defun gnus-group-set-params-info (group params)
3328 (gnus-group-set-info params group 'params)) 3604 (gnus-group-set-info params group 'params))
3329 3605
3330 (defun gnus-add-marked-articles (group type articles &optional info force) 3606 (defun gnus-add-marked-articles (group type articles &optional info force)
3331 ;; Add ARTICLES of TYPE to the info of GROUP. 3607 ;; Add ARTICLES of TYPE to the info of GROUP.
3332 ;; If INFO is non-nil, use that info. If FORCE is non-nil, don't 3608 ;; If INFO is non-nil, use that info. If FORCE is non-nil, don't
3333 ;; add, but replace marked articles of TYPE with ARTICLES. 3609 ;; add, but replace marked articles of TYPE with ARTICLES.
3334 (let ((info (or info (gnus-get-info group))) 3610 (let ((info (or info (gnus-get-info group)))
3335 marked m) 3611 marked m)
3336 (or (not info) 3612 (or (not info)
3337 (and (not (setq marked (nthcdr 3 info))) 3613 (and (not (setq marked (nthcdr 3 info)))
3371 (gnus-group-get-parameter group 'timestamp t)) 3647 (gnus-group-get-parameter group 'timestamp t))
3372 3648
3373 (defun gnus-group-timestamp-delta (group) 3649 (defun gnus-group-timestamp-delta (group)
3374 "Return the offset in seconds from the timestamp for GROUP to the current time, as a floating point number." 3650 "Return the offset in seconds from the timestamp for GROUP to the current time, as a floating point number."
3375 (let* ((time (or (gnus-group-timestamp group) 3651 (let* ((time (or (gnus-group-timestamp group)
3376 (list 0 0))) 3652 (list 0 0)))
3377 (delta (gnus-time-minus (current-time) time))) 3653 (delta (subtract-time (current-time) time)))
3378 (+ (* (nth 0 delta) 65536.0) 3654 (+ (* (nth 0 delta) 65536.0)
3379 (nth 1 delta)))) 3655 (nth 1 delta))))
3380 3656
3381 (defun gnus-group-timestamp-string (group) 3657 (defun gnus-group-timestamp-string (group)
3382 "Return a string of the timestamp for GROUP." 3658 "Return a string of the timestamp for GROUP."
3383 (let ((time (gnus-group-timestamp group))) 3659 (let ((time (gnus-group-timestamp group)))
3384 (if (not time) 3660 (if (not time)
3385 "" 3661 ""
3386 (gnus-time-iso8601 time)))) 3662 (gnus-time-iso8601 time))))
3387 3663
3664 (defun gnus-group-prepare-flat-list-dead-predicate
3665 (groups level mark predicate)
3666 (let (group)
3667 (if predicate
3668 ;; This loop is used when listing groups that match some
3669 ;; regexp.
3670 (while (setq group (pop groups))
3671 (when (funcall predicate group)
3672 (gnus-add-text-properties
3673 (point) (prog1 (1+ (point))
3674 (insert " " mark " *: "
3675 (gnus-group-name-decode group
3676 (gnus-group-name-charset
3677 nil group))
3678 "\n"))
3679 (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
3680 'gnus-unread t
3681 'gnus-level level)))))))
3682
3683 (defun gnus-group-prepare-flat-predicate (level predicate &optional lowest
3684 dead-predicate)
3685 "List all newsgroups with unread articles of level LEVEL or lower.
3686 If LOWEST is non-nil, list all newsgroups of level LOWEST or higher.
3687 If PREDICATE, only list groups which PREDICATE returns non-nil.
3688 If DEAD-PREDICATE, list dead groups which DEAD-PREDICATE returns non-nil."
3689 (set-buffer gnus-group-buffer)
3690 (let ((buffer-read-only nil)
3691 (newsrc (cdr gnus-newsrc-alist))
3692 (lowest (or lowest 1))
3693 info clevel unread group params)
3694 (erase-buffer)
3695 ;; List living groups.
3696 (while newsrc
3697 (setq info (car newsrc)
3698 group (gnus-info-group info)
3699 params (gnus-info-params info)
3700 newsrc (cdr newsrc)
3701 unread (car (gnus-gethash group gnus-newsrc-hashtb)))
3702 (and unread ; This group might be unchecked
3703 (funcall predicate info)
3704 (<= (setq clevel (gnus-info-level info)) level)
3705 (>= clevel lowest)
3706 (gnus-group-insert-group-line
3707 group (gnus-info-level info)
3708 (gnus-info-marks info) unread (gnus-info-method info))))
3709
3710 ;; List dead groups.
3711 (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie)
3712 (gnus-group-prepare-flat-list-dead-predicate
3713 (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
3714 gnus-level-zombie ?Z
3715 dead-predicate))
3716 (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)
3717 (gnus-group-prepare-flat-list-dead-predicate
3718 (setq gnus-killed-list (sort gnus-killed-list 'string<))
3719 gnus-level-killed ?K dead-predicate))
3720
3721 (gnus-group-set-mode-line)
3722 (setq gnus-group-list-mode (cons level t))
3723 (gnus-run-hooks 'gnus-group-prepare-hook)
3724 t))
3725
3726 (defun gnus-group-list-cached (level &optional lowest)
3727 "List all groups with cached articles.
3728 If the prefix LEVEL is non-nil, it should be a number that says which
3729 level to cut off listing groups.
3730 If LOWEST, don't list groups with level lower than LOWEST.
3731
3732 This command may read the active file."
3733 (interactive "P")
3734 (when level
3735 (setq level (prefix-numeric-value level)))
3736 (when (or (not level) (>= level gnus-level-zombie))
3737 (gnus-cache-open))
3738 (gnus-group-prepare-flat-predicate (or level gnus-level-subscribed)
3739 #'(lambda (info)
3740 (let ((marks (gnus-info-marks info)))
3741 (assq 'cache marks)))
3742 lowest
3743 #'(lambda (group)
3744 (or (gnus-gethash group
3745 gnus-cache-active-hashtb)
3746 ;; Cache active file might use "."
3747 ;; instead of ":".
3748 (gnus-gethash
3749 (mapconcat 'identity
3750 (split-string group ":")
3751 ".")
3752 gnus-cache-active-hashtb))))
3753 (goto-char (point-min))
3754 (gnus-group-position-point))
3755
3756 (defun gnus-group-list-dormant (level &optional lowest)
3757 "List all groups with dormant articles.
3758 If the prefix LEVEL is non-nil, it should be a number that says which
3759 level to cut off listing groups.
3760 If LOWEST, don't list groups with level lower than LOWEST.
3761
3762 This command may read the active file."
3763 (interactive "P")
3764 (when level
3765 (setq level (prefix-numeric-value level)))
3766 (when (or (not level) (>= level gnus-level-zombie))
3767 (gnus-cache-open))
3768 (gnus-group-prepare-flat-predicate (or level gnus-level-subscribed)
3769 #'(lambda (info)
3770 (let ((marks (gnus-info-marks info)))
3771 (assq 'dormant marks)))
3772 lowest)
3773 (goto-char (point-min))
3774 (gnus-group-position-point))
3775
3388 (provide 'gnus-group) 3776 (provide 'gnus-group)
3389 3777
3390 ;;; gnus-group.el ends here 3778 ;;; gnus-group.el ends here