| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
(require 'wid-edit) |
|---|
| 31 |
(require 'gnus) |
|---|
| 32 |
(require 'gnus-agent) |
|---|
| 33 |
(require 'gnus-score) |
|---|
| 34 |
(require 'gnus-topic) |
|---|
| 35 |
(require 'gnus-art) |
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
(defun gnus-custom-mode () |
|---|
| 40 |
"Major mode for editing Gnus customization buffers. |
|---|
| 41 |
|
|---|
| 42 |
The following commands are available: |
|---|
| 43 |
|
|---|
| 44 |
\\[widget-forward] Move to next button or editable field. |
|---|
| 45 |
\\[widget-backward] Move to previous button or editable field. |
|---|
| 46 |
\\[widget-button-click] Activate button under the mouse pointer. |
|---|
| 47 |
\\[widget-button-press] Activate button under point. |
|---|
| 48 |
|
|---|
| 49 |
Entry to this mode calls the value of `gnus-custom-mode-hook' |
|---|
| 50 |
if that value is non-nil." |
|---|
| 51 |
(kill-all-local-variables) |
|---|
| 52 |
(setq major-mode 'gnus-custom-mode |
|---|
| 53 |
mode-name "Gnus Customize") |
|---|
| 54 |
(use-local-map widget-keymap) |
|---|
| 55 |
|
|---|
| 56 |
(when (and (facep 'custom-button-face) |
|---|
| 57 |
(facep 'custom-button-pressed-face)) |
|---|
| 58 |
(set (make-local-variable 'widget-button-face) |
|---|
| 59 |
'custom-button-face) |
|---|
| 60 |
(set (make-local-variable 'widget-button-pressed-face) |
|---|
| 61 |
'custom-button-pressed-face) |
|---|
| 62 |
(set (make-local-variable 'widget-mouse-face) |
|---|
| 63 |
'custom-button-pressed-face)) |
|---|
| 64 |
(when (and (boundp 'custom-raised-buttons) |
|---|
| 65 |
(symbol-value 'custom-raised-buttons)) |
|---|
| 66 |
(set (make-local-variable 'widget-push-button-prefix) "") |
|---|
| 67 |
(set (make-local-variable 'widget-push-button-suffix) "") |
|---|
| 68 |
(set (make-local-variable 'widget-link-prefix) "") |
|---|
| 69 |
(set (make-local-variable 'widget-link-suffix) "")) |
|---|
| 70 |
(gnus-run-mode-hooks 'gnus-custom-mode-hook)) |
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
(defconst gnus-group-parameters |
|---|
| 75 |
'((extra-aliases (choice |
|---|
| 76 |
:tag "Extra Aliases" |
|---|
| 77 |
(list |
|---|
| 78 |
:tag "List" |
|---|
| 79 |
(editable-list |
|---|
| 80 |
:inline t |
|---|
| 81 |
(gnus-email-address :tag "Address"))) |
|---|
| 82 |
(gnus-email-address :tag "Address")) "\ |
|---|
| 83 |
Store messages posted from or to this address in this group. |
|---|
| 84 |
|
|---|
| 85 |
You must be using gnus-group-split for this to work. The VALUE of the |
|---|
| 86 |
nnmail-split-fancy SPLIT generated for this group will match these |
|---|
| 87 |
addresses.") |
|---|
| 88 |
|
|---|
| 89 |
(split-regexp (regexp :tag "gnus-group-split Regular Expression") "\ |
|---|
| 90 |
Like gnus-group-split Address, but expects a regular expression.") |
|---|
| 91 |
|
|---|
| 92 |
(split-exclude (list :tag "gnus-group-split Restricts" |
|---|
| 93 |
(editable-list |
|---|
| 94 |
:inline t (regexp :tag "Restrict"))) "\ |
|---|
| 95 |
Regular expression that cancels gnus-group-split matches. |
|---|
| 96 |
|
|---|
| 97 |
Each entry is added to the nnmail-split-fancy SPLIT as a separate |
|---|
| 98 |
RESTRICT clause.") |
|---|
| 99 |
|
|---|
| 100 |
(split-spec (choice :tag "gnus-group-split Overrider" |
|---|
| 101 |
(sexp :tag "Fancy Split") |
|---|
| 102 |
(const :tag "Catch All" catch-all) |
|---|
| 103 |
(const :tag "Ignore" nil)) "\ |
|---|
| 104 |
Override all other gnus-group-split fields. |
|---|
| 105 |
|
|---|
| 106 |
In `Fancy Split', you can enter any nnmail-split-fancy SPLIT. Note |
|---|
| 107 |
that the name of this group won't be automatically assumed, you have |
|---|
| 108 |
to add it to the SPLITs yourself. This means you can use such splits |
|---|
| 109 |
to split messages to other groups too. |
|---|
| 110 |
|
|---|
| 111 |
If you select `Catch All', this group will get postings for any |
|---|
| 112 |
messages not matched in any other group. It overrides the variable |
|---|
| 113 |
gnus-group-split-default-catch-all-group. |
|---|
| 114 |
|
|---|
| 115 |
Selecting `Ignore' forces no SPLIT to be generated for this group, |
|---|
| 116 |
disabling all other gnus-group-split fields.") |
|---|
| 117 |
|
|---|
| 118 |
(broken-reply-to (const :tag "Broken Reply To" t) "\ |
|---|
| 119 |
Ignore `Reply-To' headers in this group. |
|---|
| 120 |
|
|---|
| 121 |
That can be useful if you're reading a mailing list group where the |
|---|
| 122 |
listserv has inserted `Reply-To' headers that point back to the |
|---|
| 123 |
listserv itself. This is broken behavior. So there!") |
|---|
| 124 |
|
|---|
| 125 |
(to-group (string :tag "To Group") "\ |
|---|
| 126 |
All posts will be sent to the specified group.") |
|---|
| 127 |
|
|---|
| 128 |
(gcc-self (choice :tag "GCC" |
|---|
| 129 |
:value t |
|---|
| 130 |
(const :tag "To current group" t) |
|---|
| 131 |
(const none) |
|---|
| 132 |
(string :format "%v" :hide-front-space t)) "\ |
|---|
| 133 |
Specify default value for GCC header. |
|---|
| 134 |
|
|---|
| 135 |
If this symbol is present in the group parameter list and set to t, |
|---|
| 136 |
new composed messages will be `Gcc''d to the current group. If it is |
|---|
| 137 |
present and set to `none', no `Gcc:' header will be generated, if it |
|---|
| 138 |
is present and a string, this string will be inserted literally as a |
|---|
| 139 |
`gcc' header (this symbol takes precedence over any default `Gcc' |
|---|
| 140 |
rules as described later).") |
|---|
| 141 |
|
|---|
| 142 |
(expiry-wait (choice :tag "Expire Wait" |
|---|
| 143 |
:value never |
|---|
| 144 |
(const never) |
|---|
| 145 |
(const immediate) |
|---|
| 146 |
(number :hide-front-space t |
|---|
| 147 |
:format "%v")) "\ |
|---|
| 148 |
When to expire. |
|---|
| 149 |
|
|---|
| 150 |
Overrides any `nnmail-expiry-wait' and `nnmail-expiry-wait-function' |
|---|
| 151 |
when expiring expirable messages. The value can either be a number of |
|---|
| 152 |
days (not necessarily an integer) or the symbols `never' or |
|---|
| 153 |
`immediate'.") |
|---|
| 154 |
|
|---|
| 155 |
(expiry-target (choice :tag "Expiry Target" |
|---|
| 156 |
:value delete |
|---|
| 157 |
(const delete) |
|---|
| 158 |
(function :format "%v" nnmail-) |
|---|
| 159 |
string) "\ |
|---|
| 160 |
Where expired messages end up. |
|---|
| 161 |
|
|---|
| 162 |
Overrides `nnmail-expiry-target'.") |
|---|
| 163 |
|
|---|
| 164 |
(score-file (file :tag "Score File") "\ |
|---|
| 165 |
Make the specified file into the current score file. |
|---|
| 166 |
This means that all score commands you issue will end up in this file.") |
|---|
| 167 |
|
|---|
| 168 |
(adapt-file (file :tag "Adapt File") "\ |
|---|
| 169 |
Make the specified file into the current adaptive file. |
|---|
| 170 |
All adaptive score entries will be put into this file.") |
|---|
| 171 |
|
|---|
| 172 |
(admin-address (gnus-email-address :tag "Admin Address") "\ |
|---|
| 173 |
Administration address for a mailing list. |
|---|
| 174 |
|
|---|
| 175 |
When unsubscribing to a mailing list you should never send the |
|---|
| 176 |
unsubscription notice to the mailing list itself. Instead, you'd |
|---|
| 177 |
send messages to the administrative address. This parameter allows |
|---|
| 178 |
you to put the admin address somewhere convenient.") |
|---|
| 179 |
|
|---|
| 180 |
(display (choice :tag "Display" |
|---|
| 181 |
:value default |
|---|
| 182 |
(const all) |
|---|
| 183 |
(integer) |
|---|
| 184 |
(const default) |
|---|
| 185 |
(sexp :tag "Other")) "\ |
|---|
| 186 |
Which articles to display on entering the group. |
|---|
| 187 |
|
|---|
| 188 |
`all' |
|---|
| 189 |
Display all articles, both read and unread. |
|---|
| 190 |
|
|---|
| 191 |
`integer' |
|---|
| 192 |
Display the last NUMBER articles in the group. This is the same as |
|---|
| 193 |
entering the group with C-u NUMBER. |
|---|
| 194 |
|
|---|
| 195 |
`default' |
|---|
| 196 |
Display the default visible articles, which normally includes |
|---|
| 197 |
unread and ticked articles. |
|---|
| 198 |
|
|---|
| 199 |
`Other' |
|---|
| 200 |
Display the articles that satisfy the S-expression. The S-expression |
|---|
| 201 |
should be in an array form.") |
|---|
| 202 |
|
|---|
| 203 |
(comment (string :tag "Comment") "\ |
|---|
| 204 |
An arbitrary comment on the group.") |
|---|
| 205 |
|
|---|
| 206 |
(visible (const :tag "Permanently visible" t) "\ |
|---|
| 207 |
Always display this group, even when there are no unread articles in it.") |
|---|
| 208 |
|
|---|
| 209 |
(highlight-words |
|---|
| 210 |
(choice :tag "Highlight words" |
|---|
| 211 |
:value nil |
|---|
| 212 |
(repeat (list (regexp :tag "Highlight regexp") |
|---|
| 213 |
(number :tag "Group for entire word" 0) |
|---|
| 214 |
(number :tag "Group for displayed part" 0) |
|---|
| 215 |
(symbol :tag "Face" |
|---|
| 216 |
gnus-emphasis-highlight-words)))) |
|---|
| 217 |
"highlight regexps. |
|---|
| 218 |
See `gnus-emphasis-alist'.") |
|---|
| 219 |
|
|---|
| 220 |
(posting-style |
|---|
| 221 |
(choice :tag "Posting style" |
|---|
| 222 |
:value nil |
|---|
| 223 |
(repeat (list |
|---|
| 224 |
(choice :tag "Type" |
|---|
| 225 |
:value nil |
|---|
| 226 |
(const signature) |
|---|
| 227 |
(const signature-file) |
|---|
| 228 |
(const organization) |
|---|
| 229 |
(const address) |
|---|
| 230 |
(const x-face-file) |
|---|
| 231 |
(const name) |
|---|
| 232 |
(const body) |
|---|
| 233 |
(symbol) |
|---|
| 234 |
(string :tag "Header")) |
|---|
| 235 |
(string :format "%v")))) |
|---|
| 236 |
"post style. |
|---|
| 237 |
See `gnus-posting-styles'.")) |
|---|
| 238 |
"Alist of valid group or topic parameters. |
|---|
| 239 |
|
|---|
| 240 |
Each entry has the form (NAME TYPE DOC), where NAME is the parameter |
|---|
| 241 |
itself (a symbol), TYPE is the parameters type (a sexp widget), and |
|---|
| 242 |
DOC is a documentation string for the parameter.") |
|---|
| 243 |
|
|---|
| 244 |
(defconst gnus-extra-topic-parameters |
|---|
| 245 |
'((subscribe (regexp :tag "Subscribe") "\ |
|---|
| 246 |
If `gnus-subscribe-newsgroup-method' or |
|---|
| 247 |
`gnus-subscribe-options-newsgroup-method' is set to |
|---|
| 248 |
`gnus-subscribe-topics', new groups that matches this regexp will |
|---|
| 249 |
automatically be subscribed to this topic") |
|---|
| 250 |
(subscribe-level (integer :tag "Subscribe Level" :value 1) "\ |
|---|
| 251 |
If this topic parameter is set, when new groups are subscribed |
|---|
| 252 |
automatically under this topic (via the `subscribe' topic parameter) |
|---|
| 253 |
assign this level to the group, rather than the default level |
|---|
| 254 |
set in `gnus-level-default-subscribed'")) |
|---|
| 255 |
"Alist of topic parameters that are not also group parameters. |
|---|
| 256 |
|
|---|
| 257 |
Each entry has the form (NAME TYPE DOC), where NAME is the parameter |
|---|
| 258 |
itself (a symbol), TYPE is the parameters type (a sexp widget), and |
|---|
| 259 |
DOC is a documentation string for the parameter.") |
|---|
| 260 |
|
|---|
| 261 |
(defconst gnus-extra-group-parameters |
|---|
| 262 |
'((uidvalidity (string :tag "IMAP uidvalidity") "\ |
|---|
| 263 |
Server-assigned value attached to IMAP groups, used to maintain consistency.")) |
|---|
| 264 |
"Alist of group parameters that are not also topic parameters. |
|---|
| 265 |
|
|---|
| 266 |
Each entry has the form (NAME TYPE DOC), where NAME is the parameter |
|---|
| 267 |
itself (a symbol), TYPE is the parameters type (a sexp widget), and |
|---|
| 268 |
DOC is a documentation string for the parameter.") |
|---|
| 269 |
|
|---|
| 270 |
(eval-and-compile |
|---|
| 271 |
(defconst gnus-agent-parameters |
|---|
| 272 |
'((agent-predicate |
|---|
| 273 |
(sexp :tag "Selection Predicate" :value false) |
|---|
| 274 |
"Predicate used to automatically select articles for downloading." |
|---|
| 275 |
gnus-agent-cat-predicate) |
|---|
| 276 |
(agent-score |
|---|
| 277 |
(choice :tag "Score File" :value nil |
|---|
| 278 |
(const file :tag "Use group's score files") |
|---|
| 279 |
(repeat (list (string :format "%v" :tag "File name")))) |
|---|
| 280 |
"Which score files to use when using score to select articles to fetch. |
|---|
| 281 |
|
|---|
| 282 |
`nil' |
|---|
| 283 |
All articles will be scored to zero (0). |
|---|
| 284 |
|
|---|
| 285 |
`file' |
|---|
| 286 |
The group's score files will be used to score the articles. |
|---|
| 287 |
|
|---|
| 288 |
`List' |
|---|
| 289 |
A list of score file names." |
|---|
| 290 |
gnus-agent-cat-score-file) |
|---|
| 291 |
(agent-short-article |
|---|
| 292 |
(integer :tag "Max Length of Short Article" :value "") |
|---|
| 293 |
"The SHORT predicate will evaluate to true when the article is |
|---|
| 294 |
shorter than this length." gnus-agent-cat-length-when-short) |
|---|
| 295 |
(agent-long-article |
|---|
| 296 |
(integer :tag "Min Length of Long Article" :value "") |
|---|
| 297 |
"The LONG predicate will evaluate to true when the article is |
|---|
| 298 |
longer than this length." gnus-agent-cat-length-when-long) |
|---|
| 299 |
(agent-low-score |
|---|
| 300 |
(integer :tag "Low Score Limit" :value "") |
|---|
| 301 |
"The LOW predicate will evaluate to true when the article scores |
|---|
| 302 |
lower than this limit." gnus-agent-cat-low-score) |
|---|
| 303 |
(agent-high-score |
|---|
| 304 |
(integer :tag "High Score Limit" :value "") |
|---|
| 305 |
"The HIGH predicate will evaluate to true when the article scores |
|---|
| 306 |
higher than this limit." gnus-agent-cat-high-score) |
|---|
| 307 |
(agent-days-until-old |
|---|
| 308 |
(integer :tag "Days Until Old" :value "") |
|---|
| 309 |
"The OLD predicate will evaluate to true when the fetched article |
|---|
| 310 |
has been stored locally for at least this many days." |
|---|
| 311 |
gnus-agent-cat-days-until-old) |
|---|
| 312 |
(agent-enable-expiration |
|---|
| 313 |
(radio :tag "Expire in this Group or Topic" :value nil |
|---|
| 314 |
(const :format "Enable " ENABLE) |
|---|
| 315 |
(const :format "Disable " DISABLE)) |
|---|
| 316 |
"\nEnable, or disable, agent expiration in this group or topic." |
|---|
| 317 |
gnus-agent-cat-enable-expiration) |
|---|
| 318 |
(agent-enable-undownloaded-faces |
|---|
| 319 |
(boolean :tag "Enable Agent Faces") |
|---|
| 320 |
"Have the summary buffer use the agent's undownloaded faces. |
|---|
| 321 |
These faces, when enabled, act as a warning that an article has not |
|---|
| 322 |
been fetched into either the agent nor the cache. This is of most use |
|---|
| 323 |
to users who use the agent as a cache (i.e. they only operate on |
|---|
| 324 |
articles that have been downloaded). Leave disabled to display normal |
|---|
| 325 |
article faces even when the article hasn't been downloaded." |
|---|
| 326 |
gnus-agent-cat-enable-undownloaded-faces)) |
|---|
| 327 |
"Alist of group parameters that are not also topic parameters. |
|---|
| 328 |
|
|---|
| 329 |
Each entry has the form (NAME TYPE DOC ACCESSOR), where NAME is the |
|---|
| 330 |
parameter itself (a symbol), TYPE is the parameters type (a sexp |
|---|
| 331 |
widget), DOC is a documentation string for the parameter, and ACCESSOR |
|---|
| 332 |
is a function (symbol) that extracts the current value from the |
|---|
| 333 |
category.")) |
|---|
| 334 |
|
|---|
| 335 |
(defvar gnus-custom-params) |
|---|
| 336 |
(defvar gnus-custom-method) |
|---|
| 337 |
(defvar gnus-custom-group) |
|---|
| 338 |
(defvar gnus-custom-topic) |
|---|
| 339 |
|
|---|
| 340 |
(defun gnus-group-customize (group &optional topic) |
|---|
| 341 |
"Edit the group or topic on the current line." |
|---|
| 342 |
(interactive (list (gnus-group-group-name) (gnus-group-topic-name))) |
|---|
| 343 |
(let (info |
|---|
| 344 |
(types (mapcar (lambda (entry) |
|---|
| 345 |
`(cons :format "%v%h\n" |
|---|
| 346 |
:doc ,(nth 2 entry) |
|---|
| 347 |
(const :format "" ,(nth 0 entry)) |
|---|
| 348 |
,(nth 1 entry))) |
|---|
| 349 |
(append (reverse gnus-group-parameters-more) |
|---|
| 350 |
gnus-group-parameters |
|---|
| 351 |
(if group |
|---|
| 352 |
gnus-extra-group-parameters |
|---|
| 353 |
gnus-extra-topic-parameters)))) |
|---|
| 354 |
(agent (mapcar (lambda (entry) |
|---|
| 355 |
(let ((type (nth 1 entry)) |
|---|
| 356 |
vcons) |
|---|
| 357 |
(if (listp type) |
|---|
| 358 |
(setq type (copy-sequence type))) |
|---|
| 359 |
|
|---|
| 360 |
(setq vcons (cdr (memq :value type))) |
|---|
| 361 |
|
|---|
| 362 |
(if (symbolp (car vcons)) |
|---|
| 363 |
(condition-case nil |
|---|
| 364 |
(setcar vcons (symbol-value (car vcons))) |
|---|
| 365 |
(error))) |
|---|
| 366 |
`(cons :format "%v%h\n" |
|---|
| 367 |
:doc ,(nth 2 entry) |
|---|
| 368 |
(const :format "" ,(nth 0 entry)) |
|---|
| 369 |
,type))) |
|---|
| 370 |
(if gnus-agent |
|---|
| 371 |
gnus-agent-parameters)))) |
|---|
| 372 |
(unless (or group topic) |
|---|
| 373 |
(error "No group on current line")) |
|---|
| 374 |
(when (and group topic) |
|---|
| 375 |
(error "Both a group an topic on current line")) |
|---|
| 376 |
(unless (or topic (setq info (gnus-get-info group))) |
|---|
| 377 |
(error "Killed group; can't be edited")) |
|---|
| 378 |
|
|---|
| 379 |
(gnus-kill-buffer (gnus-get-buffer-create "*Gnus Customize*")) |
|---|
| 380 |
(switch-to-buffer (gnus-get-buffer-create "*Gnus Customize*")) |
|---|
| 381 |
(gnus-custom-mode) |
|---|
| 382 |
(make-local-variable 'gnus-custom-group) |
|---|
| 383 |
(setq gnus-custom-group group) |
|---|
| 384 |
(make-local-variable 'gnus-custom-topic) |
|---|
| 385 |
(setq gnus-custom-topic topic) |
|---|
| 386 |
(buffer-disable-undo) |
|---|
| 387 |
(widget-insert "Customize the ") |
|---|
| 388 |
(if group |
|---|
| 389 |
(widget-create 'info-link |
|---|
| 390 |
:help-echo "Push me to learn more." |
|---|
| 391 |
:tag "group parameters" |
|---|
| 392 |
"(gnus)Group Parameters") |
|---|
| 393 |
(widget-create 'info-link |
|---|
| 394 |
:help-echo "Push me to learn more." |
|---|
| 395 |
:tag "topic parameters" |
|---|
| 396 |
"(gnus)Topic Parameters")) |
|---|
| 397 |
(widget-insert " for <") |
|---|
| 398 |
(widget-insert (gnus-group-decoded-name (or group topic))) |
|---|
| 399 |
(widget-insert "> and press ") |
|---|
| 400 |
(widget-create 'push-button |
|---|
| 401 |
:tag "done" |
|---|
| 402 |
:help-echo "Push me when done customizing." |
|---|
| 403 |
:action 'gnus-group-customize-done) |
|---|
| 404 |
(widget-insert ".\n\n") |
|---|
| 405 |
(make-local-variable 'gnus-custom-params) |
|---|
| 406 |
|
|---|
| 407 |
(let ((values (if group |
|---|
| 408 |
(gnus-info-params info) |
|---|
| 409 |
(gnus-topic-parameters topic)))) |
|---|
| 410 |
|
|---|
| 411 |
|
|---|
| 412 |
|
|---|
| 413 |
|
|---|
| 414 |
|
|---|
| 415 |
|
|---|
| 416 |
(let ((tmp (setq values (gnus-copy-sequence values))) |
|---|
| 417 |
elem) |
|---|
| 418 |
(while (cdr tmp) |
|---|
| 419 |
(while (setq elem (assq (caar tmp) (cdr tmp))) |
|---|
| 420 |
(delq elem tmp)) |
|---|
| 421 |
(setq tmp (cdr tmp)))) |
|---|
| 422 |
|
|---|
| 423 |
(setq gnus-custom-params |
|---|
| 424 |
(apply 'widget-create 'group |
|---|
| 425 |
:value values |
|---|
| 426 |
(delq nil |
|---|
| 427 |
(list `(set :inline t |
|---|
| 428 |
:greedy t |
|---|
| 429 |
:tag "Parameters" |
|---|
| 430 |
:format "%t:\n%h%v" |
|---|
| 431 |
:doc "\ |
|---|
| 432 |
These special parameters are recognized by Gnus. |
|---|
| 433 |
Check the [ ] for the parameters you want to apply to this group or |
|---|
| 434 |
to the groups in this topic, then edit the value to suit your taste." |
|---|
| 435 |
,@types) |
|---|
| 436 |
(when gnus-agent |
|---|
| 437 |
`(set :inline t |
|---|
| 438 |
:greedy t |
|---|
| 439 |
:tag "Agent Parameters" |
|---|
| 440 |
:format "%t:\n%h%v" |
|---|
| 441 |
:doc "\ These agent parameters are |
|---|
| 442 |
recognized by Gnus. They control article selection and expiration for |
|---|
| 443 |
use in the unplugged cache. Check the [ ] for the parameters you want |
|---|
| 444 |
to apply to this group or to the groups in this topic, then edit the |
|---|
| 445 |
value to suit your taste. |
|---|
| 446 |
|
|---|
| 447 |
For those interested, group parameters override topic parameters while |
|---|
| 448 |
topic parameters override agent category parameters. Underlying |
|---|
| 449 |
category parameters are the customizable variables." ,@agent)) |
|---|
| 450 |
'(repeat :inline t |
|---|
| 451 |
:tag "Variables" |
|---|
| 452 |
:format "%t:\n%h%v%i\n\n" |
|---|
| 453 |
:doc "\ |
|---|
| 454 |
Set variables local to the group you are entering. |
|---|
| 455 |
|
|---|
| 456 |
If you want to turn threading off in `news.answers', you could put |
|---|
| 457 |
`(gnus-show-threads nil)' in the group parameters of that group. |
|---|
| 458 |
`gnus-show-threads' will be made into a local variable in the summary |
|---|
| 459 |
buffer you enter, and the form nil will be `eval'ed there. |
|---|
| 460 |
|
|---|
| 461 |
This can also be used as a group-specific hook function, if you'd |
|---|
| 462 |
like. If you want to hear a beep when you enter a group, you could |
|---|
| 463 |
put something like `(dummy-variable (ding))' in the parameters of that |
|---|
| 464 |
group. `dummy-variable' will be set to the result of the `(ding)' |
|---|
| 465 |
form, but who cares?" |
|---|
| 466 |
(list :format "%v" :value (nil nil) |
|---|
| 467 |
(symbol :tag "Variable") |
|---|
| 468 |
(sexp :tag |
|---|
| 469 |
"Value"))) |
|---|
| 470 |
|
|---|
| 471 |
'(repeat :inline t |
|---|
| 472 |
:tag "Unknown entries" |
|---|
| 473 |
sexp)))))) |
|---|
| 474 |
(when group |
|---|
| 475 |
(widget-insert "\n\nYou can also edit the ") |
|---|
| 476 |
(widget-create 'info-link |
|---|
| 477 |
:tag "select method" |
|---|
| 478 |
:help-echo "Push me to learn more about select methods." |
|---|
| 479 |
"(gnus)Select Methods") |
|---|
| 480 |
(widget-insert " for the group.\n") |
|---|
| 481 |
(setq gnus-custom-method |
|---|
| 482 |
(widget-create 'sexp |
|---|
| 483 |
:tag "Method" |
|---|
| 484 |
:value (gnus-info-method info)))) |
|---|
| 485 |
(use-local-map widget-keymap) |
|---|
| 486 |
(widget-setup) |
|---|
| 487 |
(buffer-enable-undo) |
|---|
| 488 |
(goto-char (point-min)))) |
|---|
| 489 |
|
|---|
| 490 |
(defun gnus-group-customize-done (&rest ignore) |
|---|
| 491 |
"Apply changes and bury the buffer." |
|---|
| 492 |
(interactive) |
|---|
| 493 |
(if gnus-custom-topic |
|---|
| 494 |
(gnus-topic-set-parameters gnus-custom-topic |
|---|
| 495 |
(widget-value gnus-custom-params)) |
|---|
| 496 |
(gnus-group-edit-group-done 'params gnus-custom-group |
|---|
| 497 |
(widget-value gnus-custom-params)) |
|---|
| 498 |
(gnus-group-edit-group-done 'method gnus-custom-group |
|---|
| 499 |
(widget-value gnus-custom-method))) |
|---|
| 500 |
(bury-buffer)) |
|---|
| 501 |
|
|---|
| 502 |
|
|---|
| 503 |
|
|---|
| 504 |
(defconst gnus-score-parameters |
|---|
| 505 |
'((mark (number :tag "Mark") "\ |
|---|
| 506 |
The value of this entry should be a number. |
|---|
| 507 |
Any articles with a score lower than this number will be marked as read.") |
|---|
| 508 |
|
|---|
| 509 |
(expunge (number :tag "Expunge") "\ |
|---|
| 510 |
The value of this entry should be a number. |
|---|
| 511 |
Any articles with a score lower than this number will be removed from |
|---|
| 512 |
the summary buffer.") |
|---|
| 513 |
|
|---|
| 514 |
(mark-and-expunge (number :tag "Mark-and-expunge") "\ |
|---|
| 515 |
The value of this entry should be a number. |
|---|
| 516 |
Any articles with a score lower than this number will be marked as |
|---|
| 517 |
read and removed from the summary buffer.") |
|---|
| 518 |
|
|---|
| 519 |
(thread-mark-and-expunge (number :tag "Thread-mark-and-expunge") "\ |
|---|
| 520 |
The value of this entry should be a number. |
|---|
| 521 |
All articles that belong to a thread that has a total score below this |
|---|
| 522 |
number will be marked as read and removed from the summary buffer. |
|---|
| 523 |
`gnus-thread-score-function' says how to compute the total score |
|---|
| 524 |
for a thread.") |
|---|
| 525 |
|
|---|
| 526 |
(files (repeat :inline t :tag "Files" file) "\ |
|---|
| 527 |
The value of this entry should be any number of file names. |
|---|
| 528 |
These files are assumed to be score files as well, and will be loaded |
|---|
| 529 |
the same way this one was.") |
|---|
| 530 |
|
|---|
| 531 |
(exclude-files (repeat :inline t :tag "Exclude-files" file) "\ |
|---|
| 532 |
The clue of this entry should be any number of files. |
|---|
| 533 |
These files will not be loaded, even though they would normally be so, |
|---|
| 534 |
for some reason or other.") |
|---|
| 535 |
|
|---|
| 536 |
(eval (sexp :tag "Eval" :value nil) "\ |
|---|
| 537 |
The value of this entry will be `eval'el. |
|---|
| 538 |
This element will be ignored when handling global score files.") |
|---|
| 539 |
|
|---|
| 540 |
(read-only (boolean :tag "Read-only" :value t) "\ |
|---|
| 541 |
Read-only score files will not be updated or saved. |
|---|
| 542 |
Global score files should feature this atom.") |
|---|
| 543 |
|
|---|
| 544 |
(orphan (number :tag "Orphan") "\ |
|---|
| 545 |
The value of this entry should be a number. |
|---|
| 546 |
Articles that do not have parents will get this number added to their |
|---|
| 547 |
scores. Imagine you follow some high-volume newsgroup, like |
|---|
| 548 |
`comp.lang.c'. Most likely you will only follow a few of the threads, |
|---|
| 549 |
also want to see any new threads. |
|---|
| 550 |
|
|---|
| 551 |
You can do this with the following two score file entries: |
|---|
| 552 |
|
|---|
| 553 |
(orphan -500) |
|---|
| 554 |
(mark-and-expunge -100) |
|---|
| 555 |
|
|---|
| 556 |
When you enter the group the first time, you will only see the new |
|---|
| 557 |
threads. You then raise the score of the threads that you find |
|---|
| 558 |
interesting (with `I T' or `I S'), and ignore (`C y') the rest. |
|---|
| 559 |
Next time you enter the group, you will see new articles in the |
|---|
| 560 |
interesting threads, plus any new threads. |
|---|
| 561 |
|
|---|
| 562 |
I.e.---the orphan score atom is for high-volume groups where there |
|---|
| 563 |
exist a few interesting threads which can't be found automatically |
|---|
| 564 |
by ordinary scoring rules.") |
|---|
| 565 |
|
|---|
| 566 |
(adapt (choice :tag "Adapt" |
|---|
| 567 |
(const t) |
|---|
| 568 |
(const ignore) |
|---|
| 569 |
(sexp :format "%v" |
|---|
| 570 |
:hide-front-space t)) "\ |
|---|
| 571 |
This entry controls the adaptive scoring. |
|---|
| 572 |
If it is t, the default adaptive scoring rules will be used. If it |
|---|
| 573 |
is `ignore', no adaptive scoring will be performed on this group. If |
|---|
| 574 |
it is a list, this list will be used as the adaptive scoring rules. |
|---|
| 575 |
If it isn't present, or is something other than t or `ignore', the |
|---|
| 576 |
default adaptive scoring rules will be used. If you want to use |
|---|
| 577 |
adaptive scoring on most groups, you'd set `gnus-use-adaptive-scoring' |
|---|
| 578 |
to t, and insert an `(adapt ignore)' in the groups where you do not |
|---|
| 579 |
want adaptive scoring. If you only want adaptive scoring in a few |
|---|
| 580 |
groups, you'd set `gnus-use-adaptive-scoring' to nil, and insert |
|---|
| 581 |
`(adapt t)' in the score files of the groups where you want it.") |
|---|
| 582 |
|
|---|
| 583 |
(adapt-file (file :tag "Adapt-file") "\ |
|---|
| 584 |
All adaptive score entries will go to the file named by this entry. |
|---|
| 585 |
It will also be applied when entering the group. This atom might |
|---|
| 586 |
be handy if you want to adapt on several groups at once, using the |
|---|
| 587 |
same adaptive file for a number of groups.") |
|---|
| 588 |
|
|---|
| 589 |
(local (repeat :tag "Local" |
|---|
| 590 |
(group :value (nil nil) |
|---|
| 591 |
(symbol :tag "Variable") |
|---|
| 592 |
(sexp :tag "Value"))) "\ |
|---|
| 593 |
The value of this entry should be a list of `(VAR VALUE)' pairs. |
|---|
| 594 |
Each VAR will be made buffer-local to the current summary buffer, |
|---|
| 595 |
and set to the value specified. This is a convenient, if somewhat |
|---|
| 596 |
strange, way of setting variables in some groups if you don't like |
|---|
| 597 |
hooks much.") |
|---|
| 598 |
(touched (sexp :format "Touched\n") "Internal variable.")) |
|---|
| 599 |
"Alist of valid symbolic score parameters. |
|---|
| 600 |
|
|---|
| 601 |
Each entry has the form (NAME TYPE DOC), where NAME is the parameter |
|---|
| 602 |
itself (a symbol), TYPE is the parameters type (a sexp widget), and DOC is a |
|---|
| 603 |
documentation string for the parameter.") |
|---|
| 604 |
|
|---|
| 605 |
(define-widget 'gnus-score-string 'group |
|---|
| 606 |
"Edit score entries for string-valued headers." |
|---|
| 607 |
:convert-widget 'gnus-score-string-convert) |
|---|
| 608 |
|
|---|
| 609 |
(defun gnus-score-string-convert (widget) |
|---|
| 610 |
|
|---|
| 611 |
(let* ((tag (widget-get widget :tag)) |
|---|
| 612 |
(item `(const :format "" :value ,(downcase tag))) |
|---|
| 613 |
(match '(string :tag "Match")) |
|---|
| 614 |
(score '(choice :tag "Score" |
|---|
| 615 |
(const :tag "default" nil) |
|---|
| 616 |
(integer :format "%v" |
|---|
| 617 |
:hide-front-space t))) |
|---|
| 618 |
(expire '(choice :tag "Expire" |
|---|
| 619 |
(const :tag "off" nil) |
|---|
| 620 |
(integer :format "%v" |
|---|
| 621 |
:hide-front-space t))) |
|---|
| 622 |
(type '(choice :tag "Type" |
|---|
| 623 |
:value s |
|---|
| 624 |
|
|---|
| 625 |
|
|---|
| 626 |
|
|---|
| 627 |
(const :tag "Regexp" r) |
|---|
| 628 |
(const :tag "Regexp (fixed case)" R) |
|---|
| 629 |
(const :tag "Substring" s) |
|---|
| 630 |
(const :tag "Substring (fixed case)" S) |
|---|
| 631 |
(const :tag "Exact" e) |
|---|
| 632 |
(const :tag "Exact (fixed case)" E) |
|---|
| 633 |
(const :tag "Word" w) |
|---|
| 634 |
(const :tag "Word (fixed case)" W) |
|---|
| 635 |
(const :tag "default" nil))) |
|---|
| 636 |
(group `(group ,match ,score ,expire ,type)) |
|---|
| 637 |
(doc (concat (or (widget-get widget :doc) |
|---|
| 638 |
(concat "Change score based on the " tag |
|---|
| 639 |
" header.\n")) |
|---|
| 640 |
" |
|---|
| 641 |
You can have an arbitrary number of score entries for this header, |
|---|
| 642 |
each score entry has four elements: |
|---|
| 643 |
|
|---|
| 644 |
1. The \"match element\". This should be the string to look for in the |
|---|
| 645 |
header. |
|---|
| 646 |
|
|---|
| 647 |
2. The \"score element\". This number should be an integer in the |
|---|
| 648 |
neginf to posinf interval. This number is added to the score |
|---|
| 649 |
of the article if the match is successful. If this element is |
|---|
| 650 |
not present, the `gnus-score-interactive-default-score' number |
|---|
| 651 |
will be used instead. This is 1000 by default. |
|---|
| 652 |
|
|---|
| 653 |
3. The \"date element\". This date says when the last time this score |
|---|
| 654 |
entry matched, which provides a mechanism for expiring the |
|---|
| 655 |
score entries. It this element is not present, the score |
|---|
| 656 |
entry is permanent. The date is represented by the number of |
|---|
| 657 |
days since December 31, 1 ce. |
|---|
| 658 |
|
|---|
| 659 |
4. The \"type element\". This element specifies what function should |
|---|
| 660 |
be used to see whether this score entry matches the article. |
|---|
| 661 |
|
|---|
| 662 |
There are the regexp, as well as substring types, and exact match, |
|---|
| 663 |
and word match types. If this element is not present, Gnus will |
|---|
| 664 |
assume that substring matching should be used. There is case |
|---|
| 665 |
sensitive variants of all match types."))) |
|---|
| 666 |
(widget-put widget :args `(,item |
|---|
| 667 |
(repeat :inline t |
|---|
| 668 |
:indent 0 |
|---|
| 669 |
:tag ,tag |
|---|
| 670 |
:doc ,doc |
|---|
| 671 |
:format "%t:\n%h%v%i\n\n" |
|---|
| 672 |
(choice :format "%v" |
|---|
| 673 |
:value ("" nil nil s) |
|---|
| 674 |
,group |
|---|
| 675 |
sexp))))) |
|---|
| 676 |
widget) |
|---|
| 677 |
|
|---|
| 678 |
(define-widget 'gnus-score-integer 'group |
|---|
| 679 |
"Edit score entries for integer-valued headers." |
|---|
| 680 |
:convert-widget 'gnus-score-integer-convert) |
|---|
| 681 |
|
|---|
| 682 |
(defun gnus-score-integer-convert (widget) |
|---|
| 683 |
|
|---|
| 684 |
(let* ((tag (widget-get widget :tag)) |
|---|
| 685 |
(item `(const :format "" :value ,(downcase tag))) |
|---|
| 686 |
(match '(integer :tag "Match")) |
|---|
| 687 |
(score '(choice :tag "Score" |
|---|
| 688 |
(const :tag "default" nil) |
|---|
| 689 |
(integer :format "%v" |
|---|
| 690 |
:hide-front-space t))) |
|---|
| 691 |
(expire '(choice :tag "Expire" |
|---|
| 692 |
(const :tag "off" nil) |
|---|
| 693 |
(integer :format "%v" |
|---|
| 694 |
:hide-front-space t))) |
|---|
| 695 |
(type '(choice :tag "Type" |
|---|
| 696 |
:value < |
|---|
| 697 |
(const <) |
|---|
| 698 |
(const >) |
|---|
| 699 |
(const =) |
|---|
| 700 |
(const >=) |
|---|
| 701 |
(const <=))) |
|---|
| 702 |
(group `(group ,match ,score ,expire ,type)) |
|---|
| 703 |
(doc (concat (or (widget-get widget :doc) |
|---|
| 704 |
(concat "Change score based on the " tag |
|---|
| 705 |
" header."))))) |
|---|
| 706 |
(widget-put widget :args `(,item |
|---|
| 707 |
(repeat :inline t |
|---|
| 708 |
:indent 0 |
|---|
| 709 |
:tag ,tag |
|---|
| 710 |
:doc ,doc |
|---|
| 711 |
:format "%t:\n%h%v%i\n\n" |
|---|
| 712 |
,group)))) |
|---|
| 713 |
widget) |
|---|
| 714 |
|
|---|
| 715 |
(define-widget 'gnus-score-date 'group |
|---|
| 716 |
"Edit score entries for date-valued headers." |
|---|
| 717 |
:convert-widget 'gnus-score-date-convert) |
|---|
| 718 |
|
|---|
| 719 |
(defun gnus-score-date-convert (widget) |
|---|
| 720 |
|
|---|
| 721 |
(let* ((tag (widget-get widget :tag)) |
|---|
| 722 |
(item `(const :format "" :value ,(downcase tag))) |
|---|
| 723 |
(match '(string :tag "Match")) |
|---|
| 724 |
(score '(choice |
|---|