(mml2015-epg-encrypt): Save the recipient keys in message-options.
[gnus] / lisp / gnus-group.el
1 ;;; gnus-group.el --- group mode commands for Gnus
2
3 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 ;;   2005, 2006 Free Software Foundation, Inc.
5
6 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
7 ;; Keywords: news
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 (eval-when-compile
31   (require 'cl)
32   (defvar tool-bar-mode))
33
34 (require 'gnus)
35 (require 'gnus-start)
36 (require 'nnmail)
37 (require 'gnus-spec)
38 (require 'gnus-int)
39 (require 'gnus-range)
40 (require 'gnus-win)
41 (require 'gnus-undo)
42 (require 'gmm-utils)
43 (require 'time-date)
44 (require 'gnus-ems)
45
46 (eval-when-compile
47   (require 'mm-url)
48   (let ((features (cons 'gnus-group features)))
49     (require 'gnus-sum))
50   (unless (boundp 'gnus-cache-active-hashtb)
51     (defvar gnus-cache-active-hashtb nil)))
52
53 (autoload 'gnus-agent-total-fetched-for "gnus-agent")
54 (autoload 'gnus-cache-total-fetched-for "gnus-cache")
55
56 (defcustom gnus-group-archive-directory
57   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
58   "*The address of the (ding) archives."
59   :group 'gnus-group-foreign
60   :type 'directory)
61
62 (defcustom gnus-group-recent-archive-directory
63   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
64   "*The address of the most recent (ding) articles."
65   :group 'gnus-group-foreign
66   :type 'directory)
67
68 (defcustom gnus-no-groups-message "No Gnus is good news"
69   "*Message displayed by Gnus when no groups are available."
70   :group 'gnus-start
71   :type 'string)
72
73 (defcustom gnus-keep-same-level nil
74   "*Non-nil means that the next newsgroup after the current will be on the same level.
75 When you type, for instance, `n' after reading the last article in the
76 current newsgroup, you will go to the next newsgroup.  If this variable
77 is nil, the next newsgroup will be the next from the group
78 buffer.
79 If this variable is non-nil, Gnus will either put you in the
80 next newsgroup with the same level, or, if no such newsgroup is
81 available, the next newsgroup with the lowest possible level higher
82 than the current level.
83 If this variable is `best', Gnus will make the next newsgroup the one
84 with the best level."
85   :group 'gnus-group-levels
86   :type '(choice (const nil)
87                  (const best)
88                  (sexp :tag "other" t)))
89
90 (defcustom gnus-group-goto-unread t
91   "*If non-nil, movement commands will go to the next unread and subscribed group."
92   :link '(custom-manual "(gnus)Group Maneuvering")
93   :group 'gnus-group-various
94   :type 'boolean)
95
96 (defcustom gnus-goto-next-group-when-activating t
97   "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group."
98   :link '(custom-manual "(gnus)Scanning New Messages")
99   :group 'gnus-group-various
100   :type 'boolean)
101
102 (defcustom gnus-permanently-visible-groups nil
103   "*Regexp to match groups that should always be listed in the group buffer.
104 This means that they will still be listed even when there are no
105 unread articles in the groups.
106
107 If nil, no groups are permanently visible."
108   :group 'gnus-group-listing
109   :type '(choice regexp (const nil)))
110
111 (defcustom gnus-list-groups-with-ticked-articles t
112   "*If non-nil, list groups that have only ticked articles.
113 If nil, only list groups that have unread articles."
114   :group 'gnus-group-listing
115   :type 'boolean)
116
117 (defcustom gnus-group-default-list-level gnus-level-subscribed
118   "*Default listing level.
119 Ignored if `gnus-group-use-permanent-levels' is non-nil."
120   :group 'gnus-group-listing
121   :type 'integer)
122
123 (defcustom gnus-group-list-inactive-groups t
124   "*If non-nil, inactive groups will be listed."
125   :group 'gnus-group-listing
126   :group 'gnus-group-levels
127   :type 'boolean)
128
129 (defcustom gnus-group-sort-function 'gnus-group-sort-by-alphabet
130   "*Function used for sorting the group buffer.
131 This function will be called with group info entries as the arguments
132 for the groups to be sorted.  Pre-made functions include
133 `gnus-group-sort-by-alphabet', `gnus-group-sort-by-real-name',
134 `gnus-group-sort-by-unread', `gnus-group-sort-by-level',
135 `gnus-group-sort-by-score', `gnus-group-sort-by-method',
136 `gnus-group-sort-by-server', and `gnus-group-sort-by-rank'.
137
138 This variable can also be a list of sorting functions.  In that case,
139 the most significant sort function should be the last function in the
140 list."
141   :group 'gnus-group-listing
142   :link '(custom-manual "(gnus)Sorting Groups")
143   :type '(repeat :value-to-internal (lambda (widget value)
144                                       (if (listp value) value (list value)))
145                  :match (lambda (widget value)
146                           (or (symbolp value)
147                               (widget-editable-list-match widget value)))
148                  (choice (function-item gnus-group-sort-by-alphabet)
149                          (function-item gnus-group-sort-by-real-name)
150                          (function-item gnus-group-sort-by-unread)
151                          (function-item gnus-group-sort-by-level)
152                          (function-item gnus-group-sort-by-score)
153                          (function-item gnus-group-sort-by-method)
154                          (function-item gnus-group-sort-by-server)
155                          (function-item gnus-group-sort-by-rank)
156                          (function :tag "other" nil))))
157
158 (defcustom gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%g%)%O\n"
159   "*Format of group lines.
160 It works along the same lines as a normal formatting string,
161 with some simple extensions.
162
163 %M    Only marked articles (character, \"*\" or \" \")
164 %S    Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
165 %L    Level of subscribedness (integer)
166 %N    Number of unread articles (integer)
167 %I    Number of dormant articles (integer)
168 %i    Number of ticked and dormant (integer)
169 %T    Number of ticked articles (integer)
170 %R    Number of read articles (integer)
171 %U    Number of unseen articles (integer)
172 %t    Estimated total number of articles (integer)
173 %y    Number of unread, unticked articles (integer)
174 %G    Group name (string)
175 %g    Qualified group name (string)
176 %c    Short (collapsed) group name.  See `gnus-group-uncollapsed-levels'.
177 %C    Group comment (string)
178 %D    Group description (string)
179 %s    Select method (string)
180 %o    Moderated group (char, \"m\")
181 %p    Process mark (char)
182 %B    Whether a summary buffer for the group is open (char, \"*\")
183 %O    Moderated group (string, \"(m)\" or \"\")
184 %P    Topic indentation (string)
185 %m    Whether there is new(ish) mail in the group (char, \"%\")
186 %n    Select from where (string)
187 %z    A string that look like `<%s:%n>' if a foreign select method is used
188 %d    The date the group was last entered.
189 %E    Icon as defined by `gnus-group-icon-list'.
190 %F    The disk space used by the articles fetched by both the cache and agent.
191 %u    User defined specifier.  The next character in the format string should
192       be a letter.  Gnus will call the function gnus-user-format-function-X,
193       where X is the letter following %u.  The function will be passed a
194       single dummy parameter as argument.  The function should return a
195       string, which will be inserted into the buffer just like information
196       from any other group specifier.
197
198 Note that this format specification is not always respected.  For
199 reasons of efficiency, when listing killed groups, this specification
200 is ignored altogether.  If the spec is changed considerably, your
201 output may end up looking strange when listing both alive and killed
202 groups.
203
204 If you use %o or %O, reading the active file will be slower and quite
205 a bit of extra memory will be used.  %D and %F will also worsen
206 performance.  Also note that if you change the format specification to
207 include any of these specs, you must probably re-start Gnus to see
208 them go into effect.
209
210 General format specifiers can also be used.
211 See Info node `(gnus)Formatting Variables'."
212   :link '(custom-manual "(gnus)Formatting Variables")
213   :group 'gnus-group-visual
214   :type 'string)
215
216 (defcustom gnus-group-mode-line-format "Gnus: %%b {%M\%:%S}"
217   "*The format specification for the group mode line.
218 It works along the same lines as a normal formatting string,
219 with some simple extensions:
220
221 %S   The native news server.
222 %M   The native select method.
223 %:   \":\" if %S isn't \"\"."
224   :group 'gnus-group-visual
225   :type 'string)
226
227 ;; Extracted from gnus-xmas-redefine in order to preserve user settings
228 (when (featurep 'xemacs)
229   (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
230   (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar))
231
232 (defcustom gnus-group-menu-hook nil
233   "Hook run after the creation of the group mode menu."
234   :group 'gnus-group-various
235   :type 'hook)
236
237 (defcustom gnus-group-catchup-group-hook nil
238   "Hook run when catching up a group from the group buffer."
239   :group 'gnus-group-various
240   :link '(custom-manual "(gnus)Group Data")
241   :type 'hook)
242
243 (defcustom gnus-group-update-group-hook nil
244   "Hook called when updating group lines."
245   :group 'gnus-group-visual
246   :type 'hook)
247
248 (defcustom gnus-group-prepare-function 'gnus-group-prepare-flat
249   "*A function that is called to generate the group buffer.
250 The function is called with three arguments: The first is a number;
251 all group with a level less or equal to that number should be listed,
252 if the second is non-nil, empty groups should also be displayed.  If
253 the third is non-nil, it is a number.  No groups with a level lower
254 than this number should be displayed.
255
256 The only current function implemented is `gnus-group-prepare-flat'."
257   :group 'gnus-group-listing
258   :type 'function)
259
260 (defcustom gnus-group-prepare-hook nil
261   "Hook called after the group buffer has been generated.
262 If you want to modify the group buffer, you can use this hook."
263   :group 'gnus-group-listing
264   :type 'hook)
265
266 (defcustom gnus-suspend-gnus-hook nil
267   "Hook called when suspending (not exiting) Gnus."
268   :group 'gnus-exit
269   :type 'hook)
270
271 (defcustom gnus-exit-gnus-hook nil
272   "Hook called when exiting Gnus."
273   :group 'gnus-exit
274   :type 'hook)
275
276 (defcustom gnus-after-exiting-gnus-hook nil
277   "Hook called after exiting Gnus."
278   :group 'gnus-exit
279   :type 'hook)
280
281 (defcustom gnus-group-update-hook '(gnus-group-highlight-line)
282   "Hook called when a group line is changed.
283 The hook will not be called if `gnus-visual' is nil.
284
285 The default function `gnus-group-highlight-line' will
286 highlight the line according to the `gnus-group-highlight'
287 variable."
288   :group 'gnus-group-visual
289   :type 'hook)
290
291 (defcustom gnus-useful-groups
292   '(("(ding) mailing list mirrored at gmane.org"
293      "gmane.emacs.gnus.general"
294      (nntp "Gmane"
295            (nntp-address "news.gmane.org")))
296     ("Gnus bug archive"
297      "gnus.gnus-bug"
298      (nntp "news.gnus.org"
299            (nntp-address "news.gnus.org")))
300     ("Local Gnus help group"
301      "gnus-help"
302      (nndoc "gnus-help"
303             (nndoc-article-type mbox)
304             (eval `(nndoc-address
305                     ,(let ((file (nnheader-find-etc-directory
306                                   "gnus-tut.txt" t)))
307                        (unless file
308                          (error "Couldn't find doc group"))
309                        file))))))
310   "*Alist of useful group-server pairs."
311   :group 'gnus-group-listing
312   :type '(repeat (list (string :tag "Description")
313                        (string :tag "Name")
314                        (sexp :tag "Method"))))
315
316 (defcustom gnus-group-highlight
317   '(;; Mail.
318     ((and mailp (= unread 0) (eq level 1)) .
319      gnus-group-mail-1-empty)
320     ((and mailp (eq level 1)) .
321      gnus-group-mail-1)
322     ((and mailp (= unread 0) (eq level 2)) .
323      gnus-group-mail-2-empty)
324     ((and mailp (eq level 2)) .
325      gnus-group-mail-2)
326     ((and mailp (= unread 0) (eq level 3)) .
327      gnus-group-mail-3-empty)
328     ((and mailp (eq level 3)) .
329      gnus-group-mail-3)
330     ((and mailp (= unread 0)) .
331      gnus-group-mail-low-empty)
332     ((and mailp) .
333      gnus-group-mail-low)
334     ;; News.
335     ((and (= unread 0) (eq level 1)) .
336      gnus-group-news-1-empty)
337     ((and (eq level 1)) .
338      gnus-group-news-1)
339     ((and (= unread 0) (eq level 2)) .
340      gnus-group-news-2-empty)
341     ((and (eq level 2)) .
342      gnus-group-news-2)
343     ((and (= unread 0) (eq level 3)) .
344      gnus-group-news-3-empty)
345     ((and (eq level 3)) .
346      gnus-group-news-3)
347     ((and (= unread 0) (eq level 4)) .
348      gnus-group-news-4-empty)
349     ((and (eq level 4)) .
350      gnus-group-news-4)
351     ((and (= unread 0) (eq level 5)) .
352      gnus-group-news-5-empty)
353     ((and (eq level 5)) .
354      gnus-group-news-5)
355     ((and (= unread 0) (eq level 6)) .
356      gnus-group-news-6-empty)
357     ((and (eq level 6)) .
358      gnus-group-news-6)
359     ((and (= unread 0)) .
360      gnus-group-news-low-empty)
361     (t .
362      gnus-group-news-low))
363   "*Controls the highlighting of group buffer lines.
364
365 Below is a list of `Form'/`Face' pairs.  When deciding how a a
366 particular group line should be displayed, each form is
367 evaluated.  The content of the face field after the first true form is
368 used.  You can change how those group lines are displayed by
369 editing the face field.
370
371 It is also possible to change and add form fields, but currently that
372 requires an understanding of Lisp expressions.  Hopefully this will
373 change in a future release.  For now, you can use the following
374 variables in the Lisp expression:
375
376 group: The name of the group.
377 unread: The number of unread articles in the group.
378 method: The select method used.
379 mailp: Whether it's a mail group or not.
380 level: The level of the group.
381 score: The score of the group.
382 ticked: The number of ticked articles."
383   :group 'gnus-group-visual
384   :type '(repeat (cons (sexp :tag "Form") face)))
385
386 (defcustom gnus-new-mail-mark ?%
387   "Mark used for groups with new mail."
388   :group 'gnus-group-visual
389   :type 'character)
390
391 (defgroup gnus-group-icons nil
392   "Add Icons to&n