* mm-uu.el (mm-uu-copy-to-buffer): Copy
[gnus] / lisp / gnus-sum.el
1 ;;; gnus-sum.el --- summary mode commands for Gnus
2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 ;;        Free Software Foundation, Inc.
4
5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
6 ;; Keywords: news
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Commentary:
26
27 ;;; Code:
28
29 (eval-when-compile
30   (require 'cl)
31   (defvar tool-bar-map))
32
33 (require 'gnus)
34 (require 'gnus-group)
35 (require 'gnus-spec)
36 (require 'gnus-range)
37 (require 'gnus-int)
38 (require 'gnus-undo)
39 (require 'gnus-util)
40 (require 'mm-decode)
41 (require 'nnoo)
42
43 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
44 (autoload 'gnus-cache-write-active "gnus-cache")
45 (autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
46 (autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
47 (autoload 'mm-uu-dissect "mm-uu")
48 (autoload 'gnus-article-outlook-deuglify-article "deuglify"
49   "Deuglify broken Outlook (Express) articles and redisplay."
50   t)
51 (autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t)
52 (autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t)
53 (autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t)
54
55 (defcustom gnus-kill-summary-on-exit t
56   "*If non-nil, kill the summary buffer when you exit from it.
57 If nil, the summary will become a \"*Dead Summary*\" buffer, and
58 it will be killed sometime later."
59   :group 'gnus-summary-exit
60   :type 'boolean)
61
62 (defcustom gnus-fetch-old-headers nil
63   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
64 If an unread article in the group refers to an older, already read (or
65 just marked as read) article, the old article will not normally be
66 displayed in the Summary buffer.  If this variable is non-nil, Gnus
67 will attempt to grab the headers to the old articles, and thereby
68 build complete threads.  If it has the value `some', only enough
69 headers to connect otherwise loose threads will be displayed.  This
70 variable can also be a number.  In that case, no more than that number
71 of old headers will be fetched.  If it has the value `invisible', all
72 old headers will be fetched, but none will be displayed.
73
74 The server has to support NOV for any of this to work."
75   :group 'gnus-thread
76   :type '(choice (const :tag "off" nil)
77                  (const some)
78                  number
79                  (sexp :menu-tag "other" t)))
80
81 (defcustom gnus-refer-thread-limit 200
82   "*The number of old headers to fetch when doing \\<gnus-summary-mode-map>\\[gnus-summary-refer-thread].
83 If t, fetch all the available old headers."
84   :group 'gnus-thread
85   :type '(choice number
86                  (sexp :menu-tag "other" t)))
87
88 (defcustom gnus-summary-make-false-root 'adopt
89   "*nil means that Gnus won't gather loose threads.
90 If the root of a thread has expired or been read in a previous
91 session, the information necessary to build a complete thread has been
92 lost.  Instead of having many small sub-threads from this original thread
93 scattered all over the summary buffer, Gnus can gather them.
94
95 If non-nil, Gnus will try to gather all loose sub-threads from an
96 original thread into one large thread.
97
98 If this variable is non-nil, it should be one of `none', `adopt',
99 `dummy' or `empty'.
100
101 If this variable is `none', Gnus will not make a false root, but just
102 present the sub-threads after another.
103 If this variable is `dummy', Gnus will create a dummy root that will
104 have all the sub-threads as children.
105 If this variable is `adopt', Gnus will make one of the \"children\"
106 the parent and mark all the step-children as such.
107 If this variable is `empty', the \"children\" are printed with empty
108 subject fields.  (Or rather, they will be printed with a string
109 given by the `gnus-summary-same-subject' variable.)"
110   :group 'gnus-thread
111   :type '(choice (const :tag "off" nil)
112                  (const none)
113                  (const dummy)
114                  (const adopt)
115                  (const empty)))
116
117 (defcustom gnus-summary-make-false-root-always nil
118   "Always make a false dummy root."
119   :group 'gnus-thread
120   :type 'boolean)
121
122 (defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
123   "*A regexp to match subjects to be excluded from loose thread gathering.
124 As loose thread gathering is done on subjects only, that means that
125 there can be many false gatherings performed.  By rooting out certain
126 common subjects, gathering might become saner."
127   :group 'gnus-thread
128   :type 'regexp)
129
130 (defcustom gnus-summary-gather-subject-limit nil
131   "*Maximum length of subject comparisons when gathering loose threads.
132 Use nil to compare full subjects.  Setting this variable to a low
133 number will help gather threads that have been corrupted by
134 newsreaders chopping off subject lines, but it might also mean that
135 unrelated articles that have subject that happen to begin with the
136 same few characters will be incorrectly gathered.
137
138 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
139 comparing subjects."
140   :group 'gnus-thread
141   :type '(choice (const :tag "off" nil)
142                  (const fuzzy)
143                  (sexp :menu-tag "on" t)))
144
145 (defcustom gnus-simplify-subject-functions nil
146   "List of functions taking a string argument that simplify subjects.
147 The functions are applied recursively.
148
149 Useful functions to put in this list include:
150 `gnus-simplify-subject-re', `gnus-simplify-subject-fuzzy',
151 `gnus-simplify-whitespace', and `gnus-simplify-all-whitespace'."
152   :group 'gnus-thread
153   :type '(repeat function))
154
155 (defcustom gnus-simplify-ignored-prefixes nil
156   "*Remove matches for this regexp from subject lines when simplifying fuzzily."
157   :group 'gnus-thread
158   :type '(choice (const :tag "off" nil)
159                  regexp))
160
161 (defcustom gnus-build-sparse-threads nil
162   "*If non-nil, fill in the gaps in threads.
163 If `some', only fill in the gaps that are needed to tie loose threads
164 together.  If `more', fill in all leaf nodes that Gnus can find.  If
165 non-nil and non-`some', fill in all gaps that Gnus manages to guess."
166   :group 'gnus-thread
167   :type '(choice (const :tag "off" nil)
168                  (const some)
169                  (const more)
170                  (sexp :menu-tag "all" t)))
171
172 (defcustom gnus-summary-thread-gathering-function
173   'gnus-gather-threads-by-subject
174   "*Function used for gathering loose threads.
175 There are two pre-defined functions: `gnus-gather-threads-by-subject',
176 which only takes Subjects into consideration; and
177 `gnus-gather-threads-by-references', which compared the References
178 headers of the articles to find matches."
179   :group 'gnus-thread
180   :type '(radio (function-item gnus-gather-threads-by-subject)
181                 (function-item gnus-gather-threads-by-references)
182                 (function :tag "other")))
183
184 (defcustom gnus-summary-same-subject ""
185   "*String indicating that the current article has the same subject as the previous.
186 This variable will only be used if the value of
187 `gnus-summary-make-false-root' is `empty'."
188   :group 'gnus-summary-format
189   :type 'string)
190
191 (defcustom gnus-summary-goto-unread t
192   "*If t, many commands will go to the next unread article.
193 This applies to marking commands as well as other commands that
194 \"naturally\" select the next article, like, for instance, `SPC' at
195 the end of an article.
196
197 If nil, the marking commands do NOT go to the next unread article
198 \(they go to the next article instead).  If `never', commands that
199 usually go to the next unread article, will go to the next article,
200 whether it is read or not."
201   :group 'gnus-summary-marks
202   :link '(custom-manual "(gnus)Setting Marks")
203   :type '(choice (const :tag "off" nil)
204                  (const never)
205                  (sexp :menu-tag "on" t)))
206
207 (defcustom gnus-summary-default-score 0
208   "*Default article score level.
209 All scores generated by the score files will be added to this score.
210 If this variable is nil, scoring will be disabled."
211   :group 'gnus-score-default
212   :type '(choice (const :tag "disable")
213                  integer))
214
215 (defcustom gnus-summary-default-high-score 0
216   "*Default threshold for a high scored article.
217 An article will be highlighted as high scored if its score is greater
218 than this score."
219   :group 'gnus-score-default
220   :type 'integer)
221
222 (defcustom gnus-summary-default-low-score 0
223   "*Default threshold for a low scored article.
224 An article will be highlighted as low scored if its score is smaller
225 than this score."
226   :group 'gnus-score-default
227   :type 'integer)
228
229 (defcustom gnus-summary-zcore-fuzz 0
230   "*Fuzziness factor for the zcore in the summary buffer.
231 Articles with scores closer than this to `gnus-summary-default-score'
232 will not be marked."
233   :group 'gnus-summary-format
234   :type 'integer)
235
236 (defcustom gnus-simplify-subject-fuzzy-regexp nil
237   "*Strings to be removed when doing fuzzy matches.
238 This can either be a regular expression or list of regular expressions
239 that will be removed from subject strings if fuzzy subject
240 simplification is selected."
241   :group 'gnus-thread
242   :type '(repeat regexp))
243
244 (defcustom gnus-show-threads t
245   "*If non-nil, display threads in summary mode."
246   :group 'gnus-thread
247   :type 'boolean)
248
249 (defcustom gnus-thread-hide-subtree nil
250   "*If non-nil, hide all threads initially.
251 This can be a predicate specifier which says which threads to hide.
252 If threads are hidden, you have to run the command
253 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
254 to expose hidden threads."
255   :group 'gnus-thread
256   :type 'boolean)
257
258 (defcustom gnus-thread-hide-killed t
259   "*If non-nil, hide killed threads automatically."
260   :group 'gnus-thread
261   :type 'boolean)
262
263 (defcustom gnus-thread-ignore-subject t
264   "*If non-nil, which is the default, ignore subjects and do all threading based on the Reference header.
265 If nil, articles that have different subjects from their parents will
266 start separate threads."
267   :group 'gnus-thread
268   :type 'boolean)
269
270 (defcustom gnus-thread-operation-ignore-subject t
271   "*If non-nil, subjects will be ignored when doing thread commands.
272 This affects commands like `gnus-summary-kill-thread' and
273 `gnus-summary-lower-thread'.
274
275 If this variable is nil, articles in the same thread with different
276 subjects will not be included in the operation in question.  If this
277 variable is `fuzzy', only articles that have subjects that are fuzzily
278 equal will be included."
279   :group 'gnus-thread
280   :type '(choice (const :tag "off" nil)
281                  (const fuzzy)
282                  (sexp :tag "on" t)))
283
284 (defcustom gnus-thread-indent-level 4
285   "*Number that says how much each sub-thread should be indented."
286   :group 'gnus-thread
287   :type 'integer)
288
289 (defcustom gnus-auto-extend-newsgroup t
290   "*If non-nil, extend newsgroup forward and backward when requested."
291   :group 'gnus-summary-choose
292   :type 'boolean)
293
294 (defcustom gnus-auto-select-first t
295   "*If non-nil, select the article under point.
296 Which article this is is controlled by the `gnus-auto-select-subject'
297 variable.
298
299 If you want to prevent automatic selection of articles in some
300 newsgroups, set the variable to nil in `gnus-select-group-hook'."
301   :group 'gnus-group-select
302   :type '(choice (const :tag "none" nil)
303                  (sexp :menu-tag "first" t)))
304
305 (defcustom gnus-auto-select-subject 'unread
306   "*Says what subject to place under point when entering a group.
307
308 This variable can either be the symbols `first' (place point on the
309 first subject), `unread' (place point on the subject line of the first
310 unread article), `best' (place point on the subject line of the
311 higest-scored article), `unseen' (place point on the subject line of
312 the first unseen article), 'unseen-or-unread' (place point on the subject
313 line of the first unseen article or, if all article have been seen, on the
314 subject line of the first unread article), or a function to be called to
315 place point on some subject line."
316   :group 'gnus-group-select
317   :type '(choice (const best)
318                  (const unread)
319                  (const first)
320                  (const unseen)
321                  (const unseen-or-unread)))
322
323 (defcustom gnus-auto-select-next t
324   "*If non-nil, offer to go to the next group from the end of the previous.
325 If the value is t and the next newsgroup is empty, Gnus will exit
326 summary mode and go back to group mode.  If the value is neither nil
327 nor t, Gnus will select the following unread newsgroup.  In
328 particular, if the value is the symbol `quietly', the next unread
329 newsgroup will be selected without any confirmation, and if it is
330 `almost-quietly', the next group will be selected without any
331 confirmation if you are located on the last article in the group.
332 Finally, if this variable is `slightly-quietly', the `\\<gnus-summary-mode-map>\\[gnus-summary-catchup-and-goto-next-group]' command
333 will go to the next group without confirmation."
334   :group 'gnus-summary-maneuvering
335   :type '(choice (const :tag "off" nil)
336                  (const quietly)
337                  (const almost-quietly)
338                  (const slightly-quietly)
339                  (sexp :menu-tag "on" t)))
340
341 (defcustom gnus-auto-select-same nil
342   "*If non-nil, select the next article with the same subject.
343 If there are no more articles with the same subject, go to
344 the first unread article."
345   :group 'gnus-summary-maneuvering
346   :type 'boolean)
347
348 (defcustom gnus-auto-goto-ignores 'unfetched
349   "*Says how to handle unfetched articles when maneuvering.
350
351 This variable can either be the symbols `nil' (maneuver to any
352 article), `undownloaded' (maneuvering while unplugged ignores articles
353 that have not been fetched), `always-undownloaded' (maneuvering always
354 ignores articles that have not been fetched), `unfetched' (maneuvering
355 ignores articles whose headers have not been fetched).
356
357 NOTE: The list of unfetched articles will always be nil when plugged
358 and, when unplugged, a subset of the undownloaded article list."
359   :group 'gnus-summary-maneuvering
360   :type '(choice (const :tag "None" nil)
361                  (const :tag "Undownloaded when unplugged" undownloaded)
362                  (const :tag "Undownloaded" always-undownloaded)
363                  (const :tag "Unfetched" unfetched)))
364
365 (defcustom gnus-summary-check-current nil
366   "*If non-nil, consider the current article when moving.
367 The \"unread\" movement commands will stay on the same line if the
368 current article is unread."
369   :group 'gnus-summary-maneuvering
370   :type 'boolean)
371
372 (defcustom gnus-auto-center-summary t
373   "*If non-nil, always center the current summary buffer.
374 In particular, if `vertical' do only vertical recentering.  If non-nil
375 and non-`vertical', do both horizontal and vertical recentering."
376   :group 'gnus-summary-maneuvering
377   :type '(choice (const :tag "none" nil)
378                  (const vertical)
379                  (integer :tag "height")
380                  (sexp :menu-tag "both" t)))
381
382 (defvar gnus-auto-center-group t
383   "*If non-nil, always center the group buffer.")
384
385 (defcustom gnus-show-all-headers nil
386   "*If non-nil, don't hide any headers."
387   :group 'gnus-article-hiding
388   :group 'gnus-article-headers
389   :type 'boolean)
390
391 (defcustom gnus-summary-ignore-duplicates nil
392   "*If non-nil, ignore articles with identical Message-ID headers."
393   :group 'gnus-summary
394   :type 'boolean)
395
396 (defcustom gnus-single-article-buffer t
397   "*If non-nil, display all articles in the same buffer.
398 If nil, each group will get its own article buffer."
399   :group 'gnus-article-various
400   :type 'boolean)
401
402 (defcustom gnus-break-pages t
403   "*If non-nil, do page breaking on articles.
404 The page delimiter is specified by the `gnus-page-delimiter'
405 variable."
406   :group 'gnus-article-various
407   :type 'boolean)
408
409 (defcustom gnus-move-split-methods nil
410   "*Variable used to suggest where articles are to be moved to.
411 It uses the same syntax as the `gnus-split-methods' variable.
412 However, whereas `gnus-split-methods' specifies file names as targets,
413 this variable specifies group names."
414   :group 'gnus-summary-mail
415   :type '(repeat (choice (list :value (fun) function)
416                          (cons :value ("" "") regexp (repeat string))
417                          (sexp :value nil))))
418
419 (defcustom gnus-unread-mark ?           ;Whitespace
420   "*Mark used for unread articles."
421   :group 'gnus-summary-marks
422   :type 'character)
423
424 (defcustom gnus-ticked-mark ?!
425   "*Mark used for ticked articles."
426   :group 'gnus-summary-marks
427   :type 'character)
428
429 (defcustom gnus-dormant-mark ??
430   "*Mark used for dormant articles."
431   :group 'gnus-summary-marks
432   :type 'character)
433
434 (defcustom gnus-del-mark ?r
435   "*Mark used for del'd articles."
436   :group 'gnus-summary-marks
437   :type 'character)
438
439 (defcustom gnus-read-mark ?R
440   "*Mark used for read articles."
441   :group 'gnus-summary-marks
442   :type 'character)
443
444 (defcustom gnus-expirable-mark ?E
445   "*Mark used for expirable articles."
446   :group 'gnus-summary-marks
447   :type 'character)
448
449 (defcustom gnus-killed-mark ?K
450   "*Mark used for killed articles."
451   :group 'gnus-summary-marks
452   :type 'character)
453
454 (defcustom gnus-spam-mark ?$
455   "*Mark used for spam articles."
456   :group 'gnus-summary-marks
457   :type 'character)
458
459 (defcustom gnus-souped-mark ?F
460   "*Mark used for souped articles."
461   :group 'gnus-summary-marks
462   :type 'character)
463
464 (defcustom gnus-kill-file-mark ?X
465   "*Mark used for articles killed by kill files."
466   :group 'gnus-summary-marks
467   :type 'character)
468
469 (defcustom gnus-low-score-mark ?Y
470   "*Mark used for articles with a low score."
471   :group 'gnus-summary-marks
472   :type 'character)
473
474 (defcustom gnus-catchup-mark ?C
475   "*Mark used for articles that are caught up."
476   :group 'gnus-summary-marks
477   :type 'character)
478
479 (defcustom gnus-replied-mark ?A
480   "*Mark used for articles that have been replied to."
481   :group 'gnus-summary-marks
482   :type 'character)
483
484 (defcustom gnus-forwarded-mark ?F
485   "*Mark used for articles that have been forwarded."
486   :group 'gnus-summary-marks
487   :type 'character)
488
489 (defcustom gnus-recent-mark ?N
490   "*Mark used for articles that are recent."
491   :group 'gnus-summary-marks
492   :type 'character)
493
494 (defcustom gnus-cached-mark ?*
495   "*Mark used for articles that are in the cache."
496   :group 'gnus-summary-marks
497   :type 'character)
498
499 (defcustom gnus-saved-mark ?S
500   "*Mark used for articles that have been saved."
501   :group 'gnus-summary-marks
502   :type 'character)
503
504 (defcustom gnus-unseen-mark ?.
505   "*Mark used for articles that haven't been seen."
506   :group 'gnus-summary-marks
507   :type 'character)
508
509 (defcustom gnus-no-mark ?               ;Whitespace
510   "*Mark used for articles that have no other secondary mark."
511   :group 'gnus-summary-marks
512   :type 'character)
513
514 (defcustom gnus-ancient-mark ?O
515   "*Mark used for ancient articles."
516   :group 'gnus-summary-marks
517   :type 'character)
518
519 (defcustom gnus-sparse-mark ?Q
520   "*Mark used for sparsely reffed articles."
521   :group 'gnus-summary-marks
522   :type 'character)
523
524 (defcustom gnus-canceled-mark ?G
525   "*Mark used for canceled articles."
526   :group 'gnus-summary-marks
527   :type 'character)
528
529 (defcustom gnus-duplicate-mark ?M
530   "*Mark used for duplicate articles."
531   :group 'gnus-summary-marks
532   :type 'character)
533
534 (defcustom gnus-undownloaded-mark ?-
535   "*Mark used for articles that weren't downloaded."
536   :group 'gnus-summary-marks
537   :type 'character)
538
539 (defcustom gnus-downloaded-mark ?+
540   "*Mark used for articles that were downloaded."
541   :group 'gnus-summary-marks
542   :type 'character)
543
544 (defcustom gnus-downloadable-mark ?%
545   "*Mark used for articles that are to be downloaded."
546   :group 'gnus-summary-marks
547   :type 'character)
548
549 (defcustom gnus-unsendable-mark ?=
550   "*Mark used for articles that won't be sent."
551   :group 'gnus-summary-marks
552   :type 'character)
553
554 (defcustom gnus-score-over-mark ?+
555   "*Score mark used for articles with high scores."
556   :group 'gnus-summary-marks
557   :type 'character)
558
559 (defcustom gnus-score-below-mark ?-
560   "*Score mark used for articles with low scores."
561   :group 'gnus-summary-marks
562   :type 'character)
563
564 (defcustom gnus-empty-thread-mark ?     ;Whitespace
565   "*There is no thread under the article."
566   :group 'gnus-summary-marks
567   :type 'character)
568
569 (defcustom gnus-not-empty-thread-mark ?=
570   "*There is a thread under the article."
571   :group 'gnus-summary-marks
572   :type 'character)
573
574 (defcustom gnus-view-pseudo-asynchronously nil
575   "*If non-nil, Gnus will view pseudo-articles asynchronously."
576   :group 'gnus-extract-view
577   :type 'boolean)
578
579 (defcustom gnus-auto-expirable-marks
580   (list gnus-killed-mark gnus-del-mark gnus-catchup-mark
581         gnus-low-score-mark gnus-ancient-mark gnus-read-mark
582         gnus-souped-mark gnus-duplicate-mark)
583   "*The list of marks converted into expiration if a group is auto-expirable."
584   :version "21.1"
585   :group 'gnus-summary
586   :type '(repeat character))
587
588 (defcustom gnus-inhibit-user-auto-expire t
589   "*If non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on."
590   :version "21.1"
591   :group 'gnus-summary
592   :type 'boolean)
593
594 (defcustom gnus-view-pseudos nil
595   "*If `automatic', pseudo-articles will be viewed automatically.
596 If `not-confirm', pseudos will be viewed automatically, and the user
597 will not be asked to confirm the command."
598   :group 'gnus-extract-view
599   :type '(choice (const :tag "off" nil)
600                  (const automatic)
601                  (const not-confirm)))
602
603 (defcustom gnus-view-pseudos-separately t
604   "*If non-nil, one pseudo-article will be created for each file to be viewed.
605 If nil, all files that use the same viewing command will be given as a
606 list of parameters to that command."
607   :group 'gnus-extract-view
608   :type 'boolean)
609
610 (defcustom gnus-insert-pseudo-articles t
611   "*If non-nil, insert pseudo-articles when decoding articles."
612   :group 'gnus-extract-view
613   :type 'boolean)
614
615 (defcustom gnus-summary-dummy-line-format
616   "   %(:                             :%) %S\n"
617   "*The format specification for the dummy roots in the summary buffer.
618 It works along the same lines as a normal formatting string,
619 with some simple extensions.
620
621 %S  The subject
622
623 General format specifiers can also be used.
624 See `(gnus)Formatting Variables'."
625   :link '(custom-manual "(gnus)Formatting Variables")
626   :group 'gnus-threading
627   :type 'string)
628
629 (defcustom gnus-summary-mode-line-format "Gnus: %g [%A] %Z"
630   "*The format specification for the summary mode line.
631 It works along the same lines as a normal formatting string,
632 with some simple extensions:
633
634 %G  Group name
635 %p  Unprefixed group name
636 %A  Current article number
637 %z  Current article score
638 %V  Gnus version
639 %U  Number of unread articles in the group
640 %e  Number of unselected articles in the group
641 %Z  A string with unread/unselected article counts
642 %g  Shortish group name
643 %S  Subject of the current article
644 %u  User-defined spec
645 %s  Current score file name
646 %d  Number of dormant articles
647 %r  Number of articles that have been marked as read in this session
648 %E  Number of articles expunged by the score files"
649   :group 'gnus-summary-format
650   :type 'string)
651
652 (defcustom gnus-list-identifiers nil
653   "Regexp that matches list identifiers to be removed from subject.
654 This can also be a list of regexps."
655   :version "21.1"
656   :group 'gnus-summary-format
657   :group 'gnus-article-hiding
658   :type '(choice (const :tag "none" nil)
659                  (regexp :value ".*")
660                  (repeat :value (".*") regexp)))
661
662 (defcustom gnus-summary-mark-below 0
663   "*Mark all articles with a score below this variable as read.
664 This variable is local to each summary buffer and usually set by the
665 score file."
666   :group 'gnus-score-default
667   :type 'integer)
668
669 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
670   "*List of functions used for sorting articles in the summary buffer.
671
672 Each function takes two articles and returns non-nil if the first
673 article should be sorted before the other.  If you use more than one
674 function, the primary sort function should be the last.  You should
675 probably always include `gnus-article-sort-by-number' in the list of
676 sorting functions -- preferably first.  Also note that sorting by date
677 is often much slower than sorting by number, and the sorting order is
678 very similar.  (Sorting by date means sorting by the time the message
679 was sent, sorting by number means sorting by arrival time.)
680
681 Ready-made functions include `gnus-article-sort-by-number',
682 `gnus-article-sort-by-author', `gnus-article-sort-by-subject',
683 `gnus-article-sort-by-date', `gnus-article-sort-by-random'
684 and `gnus-article-sort-by-score'.
685
686 When threading is turned on, the variable `gnus-thread-sort-functions'
687 controls how articles are sorted."
688   :group 'gnus-summary-sort
689   :type '(repeat (choice (function-item gnus-article-sort-by-number)
690                          (function-item gnus-article-sort-by-author)
691                          (function-item gnus-article-sort-by-subject)
692                          (function-item gnus-article-sort-by-date)
693                          (function-item gnus-article-sort-by-score)
694                          (function-item gnus-article-sort-by-random)
695                          (function :tag "other"))))
696
697 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
698   "*List of functions used for sorting threads in the summary buffer.
699 By default, threads are sorted by article number.
700
701 Each function takes two threads and returns non-nil if the first
702 thread should be sorted before the other.  If you use more than one
703 function, the primary sort function should be the last.  You should
704 probably always include `gnus-thread-sort-by-number' in the list of
705 sorting functions -- preferably first.  Also note that sorting by date
706 is often much slower than sorting by number, and the sorting order is
707 very similar.  (Sorting by date means sorting by the time the message
708 was sent, sorting by number means sorting by arrival time.)
709
710 Ready-made functions include `gnus-thread-sort-by-number',
711 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
712 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score',
713 `gnus-thread-sort-by-most-recent-number',
714 `gnus-thread-sort-by-most-recent-date',
715 `gnus-thread-sort-by-random', and
716 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
717
718 When threading is turned off, the variable
719 `gnus-article-sort-functions' controls how articles are sorted."
720   :group 'gnus-summary-sort
721   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
722                          (function-item gnus-thread-sort-by-author)
723                          (function-item gnus-thread-sort-by-subject)
724                          (function-item gnus-thread-sort-by-date)
725                          (function-item gnus-thread-sort-by-score)
726                          (function-item gnus-thread-sort-by-total-score)
727                          (function-item gnus-thread-sort-by-random)
728                          (function :tag "other"))))
729
730 (defcustom gnus-thread-score-function '+
731   "*Function used for calculating the total score of a thread.
732
733 The function is called with the scores of the article and each
734 subthread and should then return the score of the thread.
735
736 Some functions you can use are `+', `max', or `min'."
737   :group 'gnus-summary-sort
738   :type 'function)
739
740 (defcustom gnus-summary-expunge-below nil
741   "All articles that have a score less than this variable will be expunged.
742 This variable is local to the summary buffers."
743   :group 'gnus-score-default
744   :type '(choice (const :tag "off" nil)
745                  integer))
746
747 (defcustom gnus-thread-expunge-below nil
748   "All threads that have a total score less than this variable will be expunged.
749 See `gnus-thread-score-function' for en explanation of what a
750 \"thread score\" is.
751
752 This variable is local to the summary buffers."
753   :group 'gnus-threading
754   :group 'gnus-score-default
755   :type '(choice (const :tag "off" nil)
756                  integer))
757
758 (defcustom gnus-summary-mode-hook nil
759   "*A hook for Gnus summary mode.
760 This hook is run before any variables are set in the summary buffer."
761   :options '(turn-on-gnus-mailing-list-mode gnus-pick-mode)
762   :group 'gnus-summary-various
763   :type 'hook)
764
765 ;; Extracted from gnus-xmas-redefine in order to preserve user settings
766 (when (featurep 'xemacs)
767   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
768   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
769   (add-hook 'gnus-summary-mode-hook
770             'gnus-xmas-switch-horizontal-scrollbar-off))
771
772 (defcustom gnus-summary-menu-hook nil
773   "*Hook run after the creation of the summary mode menu."
774   :group 'gnus-summary-visual
775   :type 'hook)
776
777 (defcustom gnus-summary-exit-hook nil
778   "*A hook called on exit from the summary buffer.
779 It will be called with point in the group buffer."
780   :group 'gnus-summary-exit
781   :type 'hook)
782
783 (defcustom gnus-summary-prepare-hook nil
784   "*A hook called after the summary buffer has been generated.
785 If you want to modify the summary buffer, you can use this hook."
786   :group 'gnus-summary-various
787   :type 'hook)
788
789 (defcustom gnus-summary-prepared-hook nil
790   "*A hook called as the last thing after the summary buffer has been generated."
791   :group 'gnus-summary-various
792   :type 'hook)
793
794 (defcustom gnus-summary-generate-hook nil
795   "*A hook run just before generating the summary buffer.
796 This hook is commonly used to customize threading variables and the
797 like."
798   :group 'gnus-summary-various
799   :type 'hook)
800
801 (defcustom gnus-select-group-hook nil
802   "*A hook called when a newsgroup is selected.
803
804 If you'd like to simplify subjects like the
805 `gnus-summary-next-same-subject' command does, you can use the
806 following hook:
807
808  (add-hook gnus-select-group-hook
809            (lambda ()
810              (mapcar (lambda (header)
811                        (mail-header-set-subject
812                         header
813                         (gnus-simplify-subject
814                          (mail-header-subject header) 're-only)))
815                      gnus-newsgroup-headers)))"
816   :group 'gnus-group-select
817   :type 'hook)
818
819 (defcustom gnus-select-article-hook nil
820   "*A hook called when an article is selected."
821   :group 'gnus-summary-choose
822   :options '(gnus-agent-fetch-selected-article)
823   :type 'hook)
824
825 (defcustom gnus-visual-mark-article-hook
826   (list 'gnus-highlight-selected-summary)
827   "*Hook run after selecting an article in the summary buffer.
828 It is meant to be used for highlighting the article in some way.  It
829 is not run if `gnus-visual' is nil."
830   :group 'gnus-summary-visual
831   :type 'hook)
832
833 (defcustom gnus-parse-headers-hook nil