*** empty log message ***
[gnus] / lisp / gnus-group.el
1 ;;; gnus-group.el --- group mode commands for Gnus
2 ;; Copyright (C) 1996 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Keywords: news
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;;; Code:
27
28 (require 'gnus-load)
29 (require 'gnus-start)
30 (require 'nnmail)
31 (require 'gnus-spec)
32 (require 'gnus-int)
33 (require 'gnus-range)
34 (require 'gnus-win)
35 (require 'gnus-undo)
36
37 (defvar gnus-group-archive-directory
38   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
39   "*The address of the (ding) archives.")
40
41 (defvar gnus-group-recent-archive-directory
42   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
43   "*The address of the most recent (ding) articles.")
44
45 ;; Suggested by Andrew Eskilsson <pi92ae@lelle.pt.hk-r.se>.
46 (defvar gnus-no-groups-message "No news is horrible news"
47   "*Message displayed by Gnus when no groups are available.")
48
49 (defvar gnus-keep-same-level nil
50   "*Non-nil means that the next newsgroup after the current will be on the same level.
51 When you type, for instance, `n' after reading the last article in the
52 current newsgroup, you will go to the next newsgroup.  If this variable
53 is nil, the next newsgroup will be the next from the group
54 buffer.
55 If this variable is non-nil, Gnus will either put you in the
56 next newsgroup with the same level, or, if no such newsgroup is
57 available, the next newsgroup with the lowest possible level higher
58 than the current level.
59 If this variable is `best', Gnus will make the next newsgroup the one
60 with the best level.")
61
62 (defvar gnus-group-goto-unread t
63   "*If non-nil, movement commands will go to the next unread and subscribed group.")
64
65 (defvar gnus-goto-next-group-when-activating t
66   "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
67
68 (defvar gnus-permanently-visible-groups nil
69   "*Regexp to match groups that should always be listed in the group buffer.
70 This means that they will still be listed when there are no unread
71 articles in the groups.")
72
73 (defvar gnus-list-groups-with-ticked-articles t
74   "*If non-nil, list groups that have only ticked articles.
75 If nil, only list groups that have unread articles.")
76
77 (defvar gnus-group-default-list-level gnus-level-subscribed
78   "*Default listing level.
79 Ignored if `gnus-group-use-permanent-levels' is non-nil.")
80
81 (defvar gnus-group-list-inactive-groups t
82   "*If non-nil, inactive groups will be listed.")
83
84 (defvar gnus-group-sort-function 'gnus-group-sort-by-alphabet
85   "*Function used for sorting the group buffer.
86 This function will be called with group info entries as the arguments
87 for the groups to be sorted.  Pre-made functions include
88 `gnus-group-sort-by-alphabet', `gnus-group-sort-by-real-name',
89 `gnus-group-sort-by-unread', `gnus-group-sort-by-level',
90 `gnus-group-sort-by-score', `gnus-group-sort-by-method', and
91 `gnus-group-sort-by-rank'.
92
93 This variable can also be a list of sorting functions.  In that case,
94 the most significant sort function should be the last function in the
95 list.")
96
97 (defvar gnus-group-line-format "%M\%S\%p\%P\%5y: %(%g%)%l\n"
98   "*Format of group lines.
99 It works along the same lines as a normal formatting string,
100 with some simple extensions.
101
102 %M    Only marked articles (character, \"*\" or \" \")
103 %S    Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
104 %L    Level of subscribedness (integer)
105 %N    Number of unread articles (integer)
106 %I    Number of dormant articles (integer)
107 %i    Number of ticked and dormant (integer)
108 %T    Number of ticked articles (integer)
109 %R    Number of read articles (integer)
110 %t    Estimated total number of articles (integer)
111 %y    Number of unread, unticked articles (integer)
112 %G    Group name (string)
113 %g    Qualified group name (string)
114 %D    Group description (string)
115 %s    Select method (string)
116 %o    Moderated group (char, \"m\")
117 %p    Process mark (char)
118 %O    Moderated group (string, \"(m)\" or \"\")
119 %P    Topic indentation (string)
120 %l    Whether there are GroupLens predictions for this group (string)
121 %n    Select from where (string)
122 %z    A string that look like `<%s:%n>' if a foreign select method is used
123 %u    User defined specifier.  The next character in the format string should
124       be a letter.  Gnus will call the function gnus-user-format-function-X,
125       where X is the letter following %u.  The function will be passed the
126       current header as argument.  The function should return a string, which
127       will be inserted into the buffer just like information from any other
128       group specifier.
129
130 Text between %( and %) will be highlighted with `gnus-mouse-face' when
131 the mouse point move inside the area.  There can only be one such area.
132
133 Note that this format specification is not always respected.  For
134 reasons of efficiency, when listing killed groups, this specification
135 is ignored altogether.  If the spec is changed considerably, your
136 output may end up looking strange when listing both alive and killed
137 groups.
138
139 If you use %o or %O, reading the active file will be slower and quite
140 a bit of extra memory will be used. %D will also worsen performance.
141 Also note that if you change the format specification to include any
142 of these specs, you must probably re-start Gnus to see them go into
143 effect.")
144
145 (defvar gnus-group-mode-line-format "Gnus: %%b {%M\%:%S}"
146   "*The format specification for the group mode line.
147 It works along the same lines as a normal formatting string,
148 with some simple extensions:
149
150 %S   The native news server.
151 %M   The native select method.
152 %:   \":\" if %S isn't \"\".")
153
154 (defvar gnus-group-mode-hook nil
155   "*A hook for Gnus group mode.")
156
157 (defvar gnus-group-menu-hook nil
158   "*Hook run after the creation of the group mode menu.")
159
160 (defvar gnus-group-catchup-group-hook nil
161   "*A hook run when catching up a group from the group buffer.")
162
163 (defvar gnus-group-update-group-hook nil
164   "*A hook called when updating group lines.")
165
166 (defvar gnus-group-prepare-function 'gnus-group-prepare-flat
167   "*A function that is called to generate the group buffer.
168 The function is called with three arguments: The first is a number;
169 all group with a level less or equal to that number should be listed,
170 if the second is non-nil, empty groups should also be displayed.  If
171 the third is non-nil, it is a number.  No groups with a level lower
172 than this number should be displayed.
173
174 The only current function implemented is `gnus-group-prepare-flat'.")
175
176 (defvar gnus-group-prepare-hook nil
177   "*A hook called after the group buffer has been generated.
178 If you want to modify the group buffer, you can use this hook.")
179
180 (defvar gnus-suspend-gnus-hook nil
181   "*A hook called when suspending (not exiting) Gnus.")
182
183 (defvar gnus-exit-gnus-hook nil
184   "*A hook called when exiting Gnus.")
185
186 (defvar gnus-after-exiting-gnus-hook nil
187   "*A hook called after exiting Gnus.")
188
189 (defvar gnus-group-update-hook '(gnus-group-highlight-line)
190   "*A hook called when a group line is changed.
191 The hook will not be called if `gnus-visual' is nil.
192
193 The default function `gnus-group-highlight-line' will
194 highlight the line according to the `gnus-group-highlight'
195 variable.")
196
197 ;;; Internal variables
198
199 (defvar gnus-group-indentation-function nil)
200 (defvar gnus-goto-missing-group-function nil)
201 (defvar gnus-group-update-group-function nil)
202 (defvar gnus-group-goto-next-group-function nil
203   "Function to override finding the next group after listing groups.")
204
205 (defvar gnus-group-edit-buffer nil)
206
207 (defvar gnus-group-line-format-alist
208   `((?M gnus-tmp-marked-mark ?c)
209     (?S gnus-tmp-subscribed ?c)
210     (?L gnus-tmp-level ?d)
211     (?N (cond ((eq number t) "*" )
212               ((numberp number) 
213                (int-to-string
214                 (+ number
215                    (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
216                    (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
217               (t number)) ?s)
218     (?R gnus-tmp-number-of-read ?s)
219     (?t gnus-tmp-number-total ?d)
220     (?y gnus-tmp-number-of-unread ?s)
221     (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
222     (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
223     (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
224            (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
225     (?g gnus-tmp-group ?s)
226     (?G gnus-tmp-qualified-group ?s)
227     (?c (gnus-short-group-name gnus-tmp-group) ?s)
228     (?D gnus-tmp-newsgroup-description ?s)
229     (?o gnus-tmp-moderated ?c)
230     (?O gnus-tmp-moderated-string ?s)
231     (?p gnus-tmp-process-marked ?c)
232     (?s gnus-tmp-news-server ?s)
233     (?n gnus-tmp-news-method ?s)
234     (?P gnus-group-indentation ?s)
235     (?l gnus-tmp-grouplens ?s)
236     (?z gnus-tmp-news-method-string ?s)
237     (?u gnus-tmp-user-defined ?s)))
238
239 (defvar gnus-group-mode-line-format-alist
240   `((?S gnus-tmp-news-server ?s)
241     (?M gnus-tmp-news-method ?s)
242     (?u gnus-tmp-user-defined ?s)
243     (?: gnus-tmp-colon ?s)))
244
245 (defvar gnus-topic-topology nil
246   "The complete topic hierarchy.")
247
248 (defvar gnus-topic-alist nil
249   "The complete topic-group alist.")
250
251 (defvar gnus-group-marked nil)
252
253 (defvar gnus-group-list-mode nil)
254
255 ;;;
256 ;;; Gnus group mode
257 ;;;
258
259 (put 'gnus-group-mode 'mode-class 'special)
260
261 (when t
262   (gnus-define-keys gnus-group-mode-map
263     " " gnus-group-read-group
264     "=" gnus-group-select-group
265     "\r" gnus-group-select-group
266     "\M-\r" gnus-group-quick-select-group
267     "j" gnus-group-jump-to-group
268     "n" gnus-group-next-unread-group
269     "p" gnus-group-prev-unread-group
270     "\177" gnus-group-prev-unread-group
271     [delete] gnus-group-prev-unread-group
272     "N" gnus-group-next-group
273     "P" gnus-group-prev-group
274     "\M-n" gnus-group-next-unread-group-same-level
275     "\M-p" gnus-group-prev-unread-group-same-level
276     "," gnus-group-best-unread-group
277     "." gnus-group-first-unread-group
278     "u" gnus-group-unsubscribe-current-group
279     "U" gnus-group-unsubscribe-group
280     "c" gnus-group-catchup-current
281     "C" gnus-group-catchup-current-all
282     "\M-c" gnus-group-clear-data
283     "l" gnus-group-list-groups
284     "L" gnus-group-list-all-groups
285     "m" gnus-group-mail
286     "g" gnus-group-get-new-news
287     "\M-g" gnus-group-get-new-news-this-group
288     "R" gnus-group-restart
289     "r" gnus-group-read-init-file
290     "B" gnus-group-browse-foreign-server
291     "b" gnus-group-check-bogus-groups
292     "F" gnus-find-new-newsgroups
293     "\C-c\C-d" gnus-group-describe-group
294     "\M-d" gnus-group-describe-all-groups
295     "\C-c\C-a" gnus-group-apropos
296     "\C-c\M-\C-a" gnus-group-description-apropos
297     "a" gnus-group-post-news
298     "\ek" gnus-group-edit-local-kill
299     "\eK" gnus-group-edit-global-kill
300     "\C-k" gnus-group-kill-group
301     "\C-y" gnus-group-yank-group
302     "\C-w" gnus-group-kill-region
303     "\C-x\C-t" gnus-group-transpose-groups
304     "\C-c\C-l" gnus-group-list-killed
305     "\C-c\C-x" gnus-group-expire-articles
306     "\C-c\M-\C-x" gnus-group-expire-all-groups
307     "V" gnus-version
308     "s" gnus-group-save-newsrc
309     "z" gnus-group-suspend
310     "q" gnus-group-exit
311     "Q" gnus-group-quit
312     "?" gnus-group-describe-briefly
313     "\C-c\C-i" gnus-info-find-node
314     "\M-e" gnus-group-edit-group-method
315     "^" gnus-group-enter-server-mode
316     gnus-mouse-2 gnus-mouse-pick-group
317     "<" beginning-of-buffer
318     ">" end-of-buffer
319     "\C-c\C-b" gnus-bug
320     "\C-c\C-s" gnus-group-sort-groups
321     "t" gnus-topic-mode
322     "\C-c\M-g" gnus-activate-all-groups
323     "\M-&" gnus-group-universal-argument
324     "#" gnus-group-mark-group
325     "\M-#" gnus-group-unmark-group)
326
327   (gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map)
328     "m" gnus-group-mark-group
329     "u" gnus-group-unmark-group
330     "w" gnus-group-mark-region
331     "m" gnus-group-mark-buffer
332     "r" gnus-group-mark-regexp
333     "U" gnus-group-unmark-all-groups)
334
335   (gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map)
336     "d" gnus-group-make-directory-group
337     "h" gnus-group-make-help-group
338     "a" gnus-group-make-archive-group
339     "k" gnus-group-make-kiboze-group
340     "m" gnus-group-make-group
341     "E" gnus-group-edit-group
342     "e" gnus-group-edit-group-method
343     "p" gnus-group-edit-group-parameters
344     "v" gnus-group-add-to-virtual
345     "V" gnus-group-make-empty-virtual
346     "D" gnus-group-enter-directory
347     "f" gnus-group-make-doc-group
348     "w" gnus-group-make-web-group
349     "r" gnus-group-rename-group
350     "\177" gnus-group-delete-group
351     [delete] gnus-group-delete-group)
352
353   (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
354     "b" gnus-group-brew-soup
355     "w" gnus-soup-save-areas
356     "s" gnus-soup-send-replies
357     "p" gnus-soup-pack-packet
358     "r" nnsoup-pack-replies)
359
360   (gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map)
361     "s" gnus-group-sort-groups
362     "a" gnus-group-sort-groups-by-alphabet
363     "u" gnus-group-sort-groups-by-unread
364     "l" gnus-group-sort-groups-by-level
365     "v" gnus-group-sort-groups-by-score
366     "r" gnus-group-sort-groups-by-rank
367     "m" gnus-group-sort-groups-by-method)
368
369   (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
370     "k" gnus-group-list-killed
371     "z" gnus-group-list-zombies
372     "s" gnus-group-list-groups
373     "u" gnus-group-list-all-groups
374     "A" gnus-group-list-active
375     "a" gnus-group-apropos
376     "d" gnus-group-description-apropos
377     "m" gnus-group-list-matching
378     "M" gnus-group-list-all-matching
379     "l" gnus-group-list-level)
380
381   (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
382     "f" gnus-score-flush-cache)
383
384   (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
385     "f" gnus-group-fetch-faq)
386
387   (gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map)
388     "l" gnus-group-set-current-level
389     "t" gnus-group-unsubscribe-current-group
390     "s" gnus-group-unsubscribe-group
391     "k" gnus-group-kill-group
392     "y" gnus-group-yank-group
393     "w" gnus-group-kill-region
394     "\C-k" gnus-group-kill-level
395     "z" gnus-group-kill-all-zombies))
396
397 (defun gnus-group-make-menu-bar ()
398   (gnus-turn-off-edit-menu 'group)
399   (unless (boundp 'gnus-group-reading-menu)
400
401     (easy-menu-define
402      gnus-group-reading-menu gnus-group-mode-map ""
403      '("Group"
404        ["Read" gnus-group-read-group (gnus-group-group-name)]
405        ["Select" gnus-group-select-group (gnus-group-group-name)]
406        ["See old articles" (gnus-group-select-group 'all)
407         :keys "C-u SPC" :active (gnus-group-group-name)]
408        ["Catch up" gnus-group-catchup-current (gnus-group-group-name)]
409        ["Catch up all articles" gnus-group-catchup-current-all
410         (gnus-group-group-name)]
411        ["Check for new articles" gnus-group-get-new-news-this-group
412         (gnus-group-group-name)]
413        ["Toggle subscription" gnus-group-unsubscribe-current-group
414         (gnus-group-group-name)]
415        ["Kill" gnus-group-kill-group (gnus-group-group-name)]
416        ["Yank" gnus-group-yank-group gnus-list-of-killed-groups]
417        ["Describe" gnus-group-describe-group (gnus-group-group-name)]
418        ["Fetch FAQ" gnus-group-fetch-faq (gnus-group-group-name)]
419        ["Edit kill file" gnus-group-edit-local-kill
420         (gnus-group-group-name)]
421        ;; Actually one should check, if any of the marked groups gives t for
422        ;; (gnus-check-backend-function 'request-expire-articles ...)
423        ["Expire articles" gnus-group-expire-articles
424         (or (and (gnus-group-group-name)
425                  (gnus-check-backend-function
426                   'request-expire-articles
427                   (gnus-group-group-name))) gnus-group-marked)]
428        ["Set group level" gnus-group-set-current-level
429         (gnus-group-group-name)]
430        ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)]
431        ))
432   
433     (easy-menu-define
434      gnus-group-group-menu gnus-group-mode-map ""
435      '("Groups"
436        ("Listing"
437         ["List unread subscribed groups" gnus-group-list-groups t]
438         ["List (un)subscribed groups" gnus-group-list-all-groups t]
439         ["List killed groups" gnus-group-list-killed gnus-killed-list]
440         ["List zombie groups" gnus-group-list-zombies gnus-zombie-list]
441         ["List level..." gnus-group-list-level t]
442         ["Describe all groups" gnus-group-describe-all-groups t]
443         ["Group apropos..." gnus-group-apropos t]
444         ["Group and description apropos..." gnus-group-description-apropos t]
445         ["List groups matching..." gnus-group-list-matching t]
446         ["List all groups matching..." gnus-group-list-all-matching t]
447         ["List active file" gnus-group-list-active t])
448        ("Sort"
449         ["Default sort" gnus-group-sort-groups
450          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
451         ["Sort by method" gnus-group-sort-groups-by-method
452          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
453         ["Sort by rank" gnus-group-sort-groups-by-rank
454          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
455         ["Sort by score" gnus-group-sort-groups-by-score
456          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
457         ["Sort by level" gnus-group-sort-groups-by-level
458          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
459         ["Sort by unread" gnus-group-sort-groups-by-unread
460          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
461         ["Sort by name" gnus-group-sort-groups-by-alphabet
462          (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))])
463        ("Mark"
464         ["Mark group" gnus-group-mark-group
465          (and (gnus-group-group-name)
466               (not (memq (gnus-group-group-name) gnus-group-marked)))]
467         ["Unmark group" gnus-group-unmark-group
468          (and (gnus-group-group-name)
469               (memq (gnus-group-group-name) gnus-group-marked))]
470         ["Unmark all" gnus-group-unmark-all-groups gnus-group-marked]
471         ["Mark regexp..." gnus-group-mark-regexp t]
472         ["Mark region" gnus-group-mark-region t]
473         ["Mark buffer" gnus-group-mark-buffer t]
474         ["Execute command" gnus-group-universal-argument
475          (or gnus-group-marked (gnus-group-group-name))])
476        ("Subscribe"
477         ["Subscribe to a group" gnus-group-unsubscribe-group t]
478         ["Kill all newsgroups in region" gnus-group-kill-region t]
479         ["Kill all zombie groups" gnus-group-kill-all-zombies
480          gnus-zombie-list]
481         ["Kill all groups on level..." gnus-group-kill-level t])
482        ("Foreign groups"
483         ["Make a foreign group" gnus-group-make-group t]
484         ["Add a directory group" gnus-group-make-directory-group t]
485         ["Add the help group" gnus-group-make-help-group t]
486         ["Add the archive group" gnus-group-make-archive-group t]
487         ["Make a doc group" gnus-group-make-doc-group t]
488         ["Make a kiboze group" gnus-group-make-kiboze-group t]
489         ["Make a virtual group" gnus-group-make-empty-virtual t]
490         ["Add a group to a virtual" gnus-group-add-to-virtual t]
491         ["Rename group" gnus-group-rename-group
492          (gnus-check-backend-function
493           'request-rename-group (gnus-group-group-name))]
494         ["Delete group" gnus-group-delete-group
495          (gnus-check-backend-function
496           'request-delete-group (gnus-group-group-name))])
497        ("Editing groups"
498         ["Parameters" gnus-group-edit-group-parameters
499          (gnus-group-group-name)]
500         ["Select method" gnus-group-edit-group-method
501          (gnus-group-group-name)]
502         ["Info" gnus-group-edit-group (gnus-group-group-name)])
503        ("Score file"
504         ["Flush cache" gnus-score-flush-cache t])
505        ("Move"
506         ["Next" gnus-group-next-group t]
507         ["Previous" gnus-group-prev-group t]
508         ["Next unread" gnus-group-next-unread-group t]
509         ["Previous unread" gnus-group-prev-unread-group t]
510         ["Next unread same level" gnus-group-next-unread-group-same-level t]
511         ["Previous unread same level"
512          gnus-group-previous-unread-group-same-level t]
513         ["Jump to group" gnus-group-jump-to-group t]
514         ["First unread group" gnus-group-first-unread-group t]
515         ["Best unread group" gnus-group-best-unread-group t])
516        ["Transpose" gnus-group-transpose-groups
517         (gnus-group-group-name)]
518        ["Read a directory as a group..." gnus-group-enter-directory t]
519        ))
520
521     (easy-menu-define
522      gnus-group-misc-menu gnus-group-mode-map ""
523      '("Misc"
524        ["Send a bug report" gnus-bug t]
525        ["Send a mail" gnus-group-mail t]
526        ["Post an article..." gnus-group-post-news t]
527        ["Customize score file" gnus-score-customize t]
528        ["Check for new news" gnus-group-get-new-news t]     
529        ["Activate all groups" gnus-activate-all-groups t]
530        ["Delete bogus groups" gnus-group-check-bogus-groups t]
531        ["Find new newsgroups" gnus-find-new-newsgroups t]
532        ["Restart Gnus" gnus-group-restart t]
533        ["Read init file" gnus-group-read-init-file t]
534        ["Browse foreign server" gnus-group-browse-foreign-server t]
535        ["Enter server buffer" gnus-group-enter-server-mode t]
536        ["Expire all expirable articles" gnus-group-expire-all-groups t]
537        ["Generate any kiboze groups" nnkiboze-generate-groups t]
538        ["Gnus version" gnus-version t]
539        ["Save .newsrc files" gnus-group-save-newsrc t]
540        ["Suspend Gnus" gnus-group-suspend t]
541        ["Clear dribble buffer" gnus-group-clear-dribble t]
542        ["Edit global kill file" gnus-group-edit-global-kill t]
543        ["Read manual" gnus-info-find-node t]
544        ["Toggle topics" gnus-topic-mode t]
545        ("SOUP"
546         ["Pack replies" nnsoup-pack-replies (fboundp 'nnsoup-request-group)]
547         ["Send replies" gnus-soup-send-replies
548          (fboundp 'gnus-soup-pack-packet)]
549         ["Pack packet" gnus-soup-pack-packet (fboundp 'gnus-soup-pack-packet)]
550         ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)]
551         ["Brew SOUP" gnus-soup-brew-soup (fboundp 'gnus-soup-pack-packet)])
552        ["Exit from Gnus" gnus-group-exit t]
553        ["Exit without saving" gnus-group-quit t]
554        ))
555
556     (run-hooks 'gnus-group-menu-hook)
557     ))
558
559 (defun gnus-group-mode ()
560   "Major mode for reading news.
561
562 All normal editing commands are switched off.
563 \\<gnus-group-mode-map>
564 The group buffer lists (some of) the groups available.  For instance,
565 `\\[gnus-group-list-groups]' will list all subscribed groups with unread articles, while `\\[gnus-group-list-zombies]'
566 lists all zombie groups.
567
568 Groups that are displayed can be entered with `\\[gnus-group-read-group]'.  To subscribe
569 to a group not displayed, type `\\[gnus-group-unsubscribe-group]'.
570
571 For more in-depth information on this mode, read the manual (`\\[gnus-info-find-node]').
572
573 The following commands are available:
574
575 \\{gnus-group-mode-map}"
576   (interactive)
577   (when (and menu-bar-mode
578              (gnus-visual-p 'group-menu 'menu))
579     (gnus-group-make-menu-bar))
580   (kill-all-local-variables)
581   (gnus-simplify-mode-line)
582   (setq major-mode 'gnus-group-mode)
583   (setq mode-name "Group")
584   (gnus-group-set-mode-line)
585   (setq mode-line-process nil)
586   (use-local-map gnus-group-mode-map)
587   (buffer-disable-undo (current-buffer))
588   (setq truncate-lines t)
589   (setq buffer-read-only t)
590   (gnus-set-default-directory)
591   (gnus-update-format-specifications nil 'group 'group-mode)
592   (gnus-update-group-mark-positions)
593   (gnus-make-local-hook 'post-command-hook)
594   (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
595   (when gnus-use-undo
596     (gnus-undo-mode 1))
597   (run-hooks 'gnus-group-mode-hook))
598
599 (defun gnus-update-group-mark-positions ()
600   (save-excursion
601     (let ((gnus-process-mark 128)
602           (gnus-group-marked '("dummy.group"))
603           (gnus-active-hashtb (make-vector 10 0)))
604       (gnus-set-active "dummy.group" '(0 . 0))
605       (gnus-set-work-buffer)
606       (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
607       (goto-char (point-min))
608       (setq gnus-group-mark-positions
609             (list (cons 'process (and (search-forward "\200" nil t)
610                                       (- (point) 2))))))))
611
612 (defun gnus-clear-inboxes-moved ()
613   (setq nnmail-moved-inboxes nil))
614
615 (defun gnus-mouse-pick-group (e)
616   "Enter the group under the mouse pointer."
617   (interactive "e")
618   (mouse-set-point e)
619   (gnus-group-read-group nil))
620
621 ;; Look at LEVEL and find out what the level is really supposed to be.
622 ;; If LEVEL is non-nil, LEVEL will be returned, if not, what happens
623 ;; will depend on whether `gnus-group-use-permanent-levels' is used.
624 (defun gnus-group-default-level (&optional level number-or-nil)
625   (cond
626    (gnus-group-use-permanent-levels
627     (or (setq gnus-group-use-permanent-levels
628               (or level (if (numberp gnus-group-use-permanent-levels)
629                             gnus-group-use-permanent-levels
630                           (or gnus-group-default-list-level
631                               gnus-level-subscribed))))
632         gnus