0
|
1 ;;; gnus-edit.el --- Gnus SCORE file editing
|
|
2 ;; Copyright (C) 1995,96 Free Software Foundation, Inc.
|
|
3 ;;
|
|
4 ;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
|
|
5 ;; Keywords: news, help
|
|
6 ;; Version: 0.2
|
|
7
|
|
8 ;;; Commentary:
|
|
9 ;;
|
|
10 ;; Type `M-x gnus-score-customize RET' to invoke.
|
|
11
|
|
12 ;;; Code:
|
|
13
|
|
14 (require 'custom)
|
|
15 (require 'gnus-score)
|
|
16 (eval-when-compile (require 'cl))
|
|
17
|
|
18 (defconst gnus-score-custom-data
|
|
19 '((tag . "Score")
|
|
20 (doc . "Customization of Gnus SCORE files.
|
|
21
|
|
22 SCORE files allow you to assign a score to each article when you enter
|
|
23 a group, and automatically mark the articles as read or delete them
|
|
24 based on the score. In the summary buffer you can use the score to
|
|
25 sort the articles by score (`C-c C-s C-s') or to jump to the unread
|
|
26 article with the highest score (`,').")
|
|
27 (type . group)
|
|
28 (data "\n"
|
|
29 ((header . nil)
|
|
30 (doc . "Name of SCORE file to customize.
|
|
31
|
|
32 Enter the name in the `File' field, then push the [Load] button to
|
|
33 load it. When done editing, push the [Save] button to save the file.
|
|
34
|
|
35 Several score files may apply to each group, and several groups may
|
|
36 use the same score file. This is controlled implicitly by the name of
|
|
37 the score file and the value of the global variable
|
2
|
38 `gnus-score-find-score-files-function', and explicitly by the
|
0
|
39 `Files' and `Exclude Files' entries.")
|
|
40 (compact . t)
|
|
41 (type . group)
|
|
42 (data ((tag . "Load")
|
|
43 (type . button)
|
|
44 (query . gnus-score-custom-load))
|
|
45 ((tag . "Save")
|
|
46 (type . button)
|
|
47 (query . gnus-score-custom-save))
|
|
48 ((name . file)
|
|
49 (tag . "File")
|
|
50 (directory . gnus-kill-files-directory)
|
|
51 (default-file . "SCORE")
|
|
52 (type . file))))
|
|
53 ((name . files)
|
|
54 (tag . "Files")
|
|
55 (doc . "\
|
2
|
56 List of score files to load when the current score file is loaded.
|
0
|
57 You can use this to share score entries between multiple score files.
|
|
58
|
|
59 Push the `[INS]' button add a score file to the list, or `[DEL]' to
|
|
60 delete a score file from the list.")
|
|
61 (type . list)
|
|
62 (data ((type . repeat)
|
|
63 (header . nil)
|
|
64 (data (type . file)
|
|
65 (directory . gnus-kill-files-directory)))))
|
|
66 ((name . exclude-files)
|
|
67 (tag . "Exclude Files")
|
|
68 (doc . "\
|
2
|
69 List of score files to exclude when the current score file is loaded.
|
0
|
70 You can use this if you have a score file you want to share between a
|
|
71 number of newsgroups, except for the newsgroup this score file
|
|
72 matches. [ Did anyone get that? ]
|
|
73
|
|
74 Push the `[INS]' button add a score file to the list, or `[DEL]' to
|
|
75 delete a score file from the list.")
|
|
76 (type . list)
|
|
77 (data ((type . repeat)
|
|
78 (header . nil)
|
|
79 (data (type . file)
|
|
80 (directory . gnus-kill-files-directory)))))
|
|
81 ((name . mark)
|
|
82 (tag . "Mark")
|
|
83 (doc . "\
|
|
84 Articles below this score will be automatically marked as read.
|
|
85
|
|
86 This means that when you enter the summary buffer, the articles will
|
|
87 be shown but will already be marked as read. You can then press `x'
|
|
88 to get rid of them entirely.
|
|
89
|
|
90 By default articles with a negative score will be marked as read. To
|
|
91 change this, push the `Mark' button, and choose `Integer'. You can
|
|
92 then enter a value in the `Mark' field.")
|
|
93 (type . gnus-score-custom-maybe-type))
|
|
94 ((name . expunge)
|
|
95 (tag . "Expunge")
|
|
96 (doc . "\
|
|
97 Articles below this score will not be shown in the summary buffer.")
|
|
98 (type . gnus-score-custom-maybe-type))
|
|
99 ((name . mark-and-expunge)
|
|
100 (tag . "Mark and Expunge")
|
|
101 (doc . "\
|
|
102 Articles below this score will be marked as read, but not shown.
|
|
103
|
|
104 Someone should explain me the difference between this and `expunge'
|
|
105 alone or combined with `mark'.")
|
|
106 (type . gnus-score-custom-maybe-type))
|
|
107 ((name . eval)
|
|
108 (tag . "Eval")
|
|
109 (doc . "\
|
|
110 Evaluate this lisp expression when the entering summary buffer.")
|
|
111 (type . sexp))
|
|
112 ((name . read-only)
|
|
113 (tag . "Read Only")
|
|
114 (doc . "Read-only score files will not be updated or saved.
|
|
115 Except from this buffer, of course!")
|
|
116 (type . toggle))
|
|
117 ((type . doc)
|
|
118 (doc . "\
|
|
119 Each news header has an associated list of score entries.
|
|
120 You can use the [INS] buttons to add new score entries anywhere in the
|
|
121 list, or the [DEL] buttons to delete specific score entries.
|
|
122
|
|
123 Each score entry should specify a string that should be matched with
|
|
124 the content actual header in order to determine whether the entry
|
|
125 applies to that header. Enter that string in the `Match' field.
|
|
126
|
|
127 If the score entry matches, the articles score will be adjusted with
|
|
128 some amount. Enter that amount in the in the `Score' field. You
|
|
129 should specify a positive amount for score entries that matches
|
|
130 articles you find interesting, and a negative amount for score entries
|
|
131 matching articles you would rather avoid. The final score for the
|
|
132 article will be the sum of the score of all score entries that match
|
|
133 the article.
|
|
134
|
|
135 The score entry can be either permanent or expirable. To make the
|
|
136 entry permanent, push the `Date' button and choose the `Permanent'
|
|
137 entry. To make the entry expirable, choose instead the `Integer'
|
|
138 entry. After choosing the you can enter the date the score entry was
|
|
139 last matched in the `Date' field. The date will be automatically
|
|
140 updated each time the score entry matches an article. When the date
|
2
|
141 become too old, the score entry will be removed.
|
0
|
142
|
|
143 For your convenience, the date is specified as the number of days
|
|
144 elapsed since the (imaginary) Gregorian date Sunday, December 31, 1
|
|
145 BC.
|
|
146
|
|
147 Finally, you can choose what kind of match you want to perform by
|
|
148 pushing the `Type' button. For most entries you can choose between
|
|
149 `Exact' which mean the header content must be exactly identical to the
|
|
150 match string, or `Substring' meaning the match string should be
|
|
151 somewhere in the header content, or even `Regexp' to use Emacs regular
|
|
152 expression matching. The last choice is `Fuzzy' which is like `Exact'
|
|
153 except that whitespace derivations, a beginning `Re:' or a terminating
|
|
154 parenthetical remark are all ignored. Each of the four types have a
|
|
155 variant which will ignore case in the comparison. That variant is
|
|
156 indicated with a `(fold)' after its name."))
|
|
157 ((name . from)
|
|
158 (tag . "From")
|
|
159 (doc . "Scoring based on the authors email address.")
|
|
160 (type . gnus-score-custom-string-type))
|
|
161 ((name . subject)
|
|
162 (tag . "Subject")
|
|
163 (doc . "Scoring based on the articles subject.")
|
|
164 (type . gnus-score-custom-string-type))
|
|
165 ((name . followup)
|
|
166 (tag . "Followup")
|
|
167 (doc . "Scoring based on who the article is a followup to.
|
|
168
|
|
169 If you want to see all followups to your own articles, add an entry
|
|
170 with a positive score matching your email address here. You can also
|
|
171 put an entry with a negative score matching someone who is so annoying
|
|
172 that you don't even want to see him quoted in followups.")
|
|
173 (type . gnus-score-custom-string-type))
|
|
174 ((name . xref)
|
|
175 (tag . "Xref")
|
|
176 (doc . "Scoring based on article crossposting.
|
|
177
|
|
178 If you want to score based on which newsgroups an article is posted
|
|
179 to, this is the header to use. The syntax is a little different from
|
|
180 the `Newsgroups' header, but scoring in `Xref' is much faster. As an
|
|
181 example, to match all crossposted articles match on `:.*:' using the
|
|
182 `Regexp' type.")
|
|
183 (type . gnus-score-custom-string-type))
|
|
184 ((name . references)
|
|
185 (tag . "References")
|
|
186 (doc . "Scoring based on article references.
|
|
187
|
|
188 The `References' header gives you an alternative way to score on
|
|
189 followups. If you for example want to see follow all discussions
|
|
190 where people from `iesd.auc.dk' school participate, you can add a
|
|
191 substring match on `iesd.auc.dk>' on this header.")
|
|
192 (type . gnus-score-custom-string-type))
|
|
193 ((name . message-id)
|
|
194 (tag . "Message-ID")
|
|
195 (doc . "Scoring based on the articles message-id.
|
|
196
|
|
197 This isn't very useful, but Lars like completeness. You can use it to
|
|
198 match all messaged generated by recent Gnus version with a `Substring'
|
|
199 match on `.fsf@'.")
|
|
200 (type . gnus-score-custom-string-type))
|
|
201 ((type . doc)
|
|
202 (doc . "\
|
|
203 WARNING: Scoring on the following three pseudo headers is very slow!
|
|
204 Scoring on any of the real headers use a technique that avoids
|
|
205 scanning the entire article, only the actual headers you score on are
|
|
206 scanned, and this scanning has been heavily optimized. Using just a
|
|
207 single entry for one the three pseudo-headers `Head', `Body', and
|
|
208 `All' will require GNUS to retrieve and scan the entire article, which
|
|
209 can be very slow on large groups. However, if you add one entry for
|
|
210 any of these headers, you can just as well add several. Each
|
|
211 subsequent entry cost relatively little extra time."))
|
|
212 ((name . head)
|
|
213 (tag . "Head")
|
|
214 (doc . "Scoring based on the article header.
|
|
215
|
|
216 Instead of matching the content of a single header, the entire header
|
|
217 section of the article is matched. You can use this to match on
|
|
218 arbitrary headers, foe example to single out TIN lusers, use a substring
|
|
219 match on `Newsreader: TIN'. That should get 'em!")
|
|
220 (type . gnus-score-custom-string-type))
|
|
221 ((name . body)
|
|
222 (tag . "Body")
|
|
223 (doc . "Scoring based on the article body.
|
|
224
|
|
225 If you think any article that mentions `Kibo' is inherently
|
|
226 interesting, do a substring match on His name. You Are Allowed.")
|
|
227 (type . gnus-score-custom-string-type))
|
|
228 ((name . all)
|
|
229 (tag . "All")
|
|
230 (doc . "Scoring based on the whole article.")
|
|
231 (type . gnus-score-custom-string-type))
|
|
232 ((name . date)
|
|
233 (tag . "Date")
|
|
234 (doc . "Scoring based on article date.
|
|
235
|
|
236 You can change the score of articles that have been posted before,
|
|
237 after, or at a specific date. You should add the date in the `Match'
|
|
238 field, and then select `before', `after', or `at' by pushing the
|
|
239 `Type' button. Imagine you want to lower the score of very old
|
|
240 articles, or want to raise the score of articles from the future (such
|
|
241 things happen!). Then you can't use date scoring for that. In fact,
|
|
242 I can't imagine anything you would want to use this for.
|
|
243
|
|
244 For your convenience, the date is specified in Usenet date format.")
|
|
245 (type . gnus-score-custom-date-type))
|
|
246 ((type . doc)
|
|
247 (doc . "\
|
|
248 The Lines and Chars headers use integer based scoring.
|
|
249
|
|
250 This means that you should write an integer in the `Match' field, and
|
|
251 the push the `Type' field to if the `Chars' or `Lines' header should
|
|
252 be larger, equal, or smaller than the number you wrote in the match
|
|
253 field."))
|
|
254 ((name . chars)
|
|
255 (tag . "Characters")
|
|
256 (doc . "Scoring based on the number of characters in the article.")
|
|
257 (type . gnus-score-custom-integer-type))
|
|
258 ((name . lines)
|
|
259 (tag . "Lines")
|
|
260 (doc . "Scoring based on the number of lines in the article.")
|
|
261 (type . gnus-score-custom-integer-type))
|
|
262 ((name . orphan)
|
|
263 (tag . "Orphan")
|
|
264 (doc . "Score to add to articles with no parents.")
|
|
265 (type . gnus-score-custom-maybe-type))
|
|
266 ((name . adapt)
|
|
267 (tag . "Adapt")
|
|
268 (doc . "Adapting the score files to your newsreading habits.
|
|
269
|
|
270 When you have finished reading a group GNUS can automatically create
|
|
271 new score entries based on which articles you read and which you
|
|
272 skipped. This is normally controlled by the two global variables
|
|
273 `gnus-use-adaptive-scoring' and `gnus-default-adaptive-score-alist',
|
|
274 The first determines whether adaptive scoring should be enabled or
|
|
275 not, while the second determines what score entries should be created.
|
|
276
|
|
277 You can overwrite the setting of `gnus-use-adaptive-scoring' by
|
|
278 selecting `Enable' or `Disable' by pressing the `Adapt' button.
|
|
279 Selecting `Custom' will allow you to specify the exact adaptation
|
|
280 rules (overwriting `gnus-default-adaptive-score-alist').")
|
|
281 (type . choice)
|
|
282 (data ((tag . "Default")
|
|
283 (default . nil)
|
|
284 (type . const))
|
|
285 ((tag . "Enable")
|
|
286 (default . t)
|
|
287 (type . const))
|
|
288 ((tag . "Disable")
|
|
289 (default . ignore)
|
|
290 (type . const))
|
|
291 ((tag . "Custom")
|
|
292 (doc . "Customization of adaptive scoring.
|
|
293
|
|
294 Each time you read an article it will be marked as read. Likewise, if
|
2
|
295 you delete it, it will be marked as deleted, and if you tick it, it will
|
0
|
296 be marked as ticked. When you leave a group, GNUS can automatically
|
|
297 create score file entries based on these marks, so next time you enter
|
|
298 the group articles with subjects that you read last time have higher
|
|
299 score and articles with subjects that deleted will have lower score.
|
|
300
|
|
301 Below is a list of such marks. You can insert new marks to the list
|
|
302 by pushing on one of the `[INS]' buttons in the left margin to create
|
|
303 a new entry and then pushing the `Mark' button to select the mark.
|
|
304 For each mark there is another list, this time of article headers,
|
|
305 which determine how the mark should affect that header. The `[INS]'
|
|
306 buttons of this list are indented to indicate that the belong to the
|
|
307 mark above. Push the `Header' button to choose a header, and then
|
|
308 enter a score value in the `Score' field.
|
|
309
|
|
310 For each article that are marked with `Mark' when you leave the
|
|
311 group, a temporary score entry for the articles `Header' with the
|
|
312 value of `Score' will be added the adapt file. If the score entry
|
|
313 already exists, `Score' will be added to its value. If you understood
|
|
314 that, you are smart.
|
|
315
|
|
316 You can select the special value `Other' when pressing the `Mark' or
|
|
317 `Header' buttons. This is because Lars might add more useful values
|
|
318 there. If he does, it is up to you to figure out what they are named.")
|
|
319 (type . list)
|
|
320 (default . ((__uninitialized__)))
|
|
321 (data ((type . repeat)
|
|
322 (header . nil)
|
|
323 (data . ((type . list)
|
|
324 (header . nil)
|
|
325 (compact . t)
|
|
326 (data ((type . choice)
|
|
327 (tag . "Mark")
|
|
328 (data ((tag . "Unread")
|
|
329 (default . gnus-unread-mark)
|
|
330 (type . const))
|
|
331 ((tag . "Ticked")
|
|
332 (default . gnus-ticked-mark)
|
|
333 (type . const))
|
|
334 ((tag . "Dormant")
|
|
335 (default . gnus-dormant-mark)
|
|
336 (type . const))
|
|
337 ((tag . "Deleted")
|
|
338 (default . gnus-del-mark)
|
|
339 (type . const))
|
|
340 ((tag . "Read")
|
|
341 (default . gnus-read-mark)
|
|
342 (type . const))
|
|
343 ((tag . "Expirable")
|
|
344 (default . gnus-expirable-mark)
|
|
345 (type . const))
|
|
346 ((tag . "Killed")
|
|
347 (default . gnus-killed-mark)
|
|
348 (type . const))
|
|
349 ((tag . "Kill-file")
|
|
350 (default . gnus-kill-file-mark)
|
|
351 (type . const))
|
|
352 ((tag . "Low-score")
|
|
353 (default . gnus-low-score-mark)
|
|
354 (type . const))
|
|
355 ((tag . "Catchup")
|
|
356 (default . gnus-catchup-mark)
|
|
357 (type . const))
|
|
358 ((tag . "Ancient")
|
|
359 (default . gnus-ancient-mark)
|
|
360 (type . const))
|
|
361 ((tag . "Canceled")
|
|
362 (default . gnus-canceled-mark)
|
|
363 (type . const))
|
|
364 ((prompt . "Other")
|
|
365 (default . ??)
|
|
366 (type . sexp))))
|
|
367 ((type . repeat)
|
|
368 (prefix . " ")
|
|
369 (data . ((type . list)
|
|
370 (compact . t)
|
|
371 (data ((tag . "Header")
|
|
372 (type . choice)
|
|
373 (data ((tag . "Subject")
|
|
374 (default . subject)
|
|
375 (type . const))
|
|
376 ((prompt . "From")
|
|
377 (tag . "From ")
|
|
378 (default . from)
|
|
379 (type . const))
|
|
380 ((prompt . "Other")
|
|
381 (width . 7)
|
|
382 (default . nil)
|
|
383 (type . symbol))))
|
|
384 ((tag . "Score")
|
|
385 (type . integer))))))))))))))
|
|
386 ((name . local)
|
|
387 (tag . "Local")
|
|
388 (doc . "\
|
|
389 List of local variables to set when this score file is loaded.
|
|
390
|
|
391 Using this entry can provide a convenient way to set variables that
|
|
392 will affect the summary mode for only some specific groups, i.e. those
|
|
393 groups matched by the current score file.")
|
|
394 (type . list)
|
|
395 (data ((type . repeat)
|
|
396 (header . nil)
|
|
397 (data . ((type . list)
|
|
398 (compact . t)
|
|
399 (data ((tag . "Name")
|
|
400 (width . 26)
|
|
401 (type . symbol))
|
|
402 ((tag . "Value")
|
|
403 (width . 26)
|
|
404 (type . sexp)))))))))))
|
|
405
|
|
406 (defconst gnus-score-custom-type-properties
|
|
407 '((gnus-score-custom-maybe-type
|
|
408 (type . choice)
|
|
409 (data ((type . integer)
|
|
410 (default . 0))
|
|
411 ((tag . "Default")
|
|
412 (type . const)
|
|
413 (default . nil))))
|
|
414 (gnus-score-custom-string-type
|
|
415 (type . list)
|
|
416 (data ((type . repeat)
|
|
417 (header . nil)
|
|
418 (data . ((type . list)
|
|
419 (compact . t)
|
|
420 (data ((tag . "Match")
|
|
421 (width . 59)
|
|
422 (type . string))
|
|
423 "\n "
|
|
424 ((tag . "Score")
|
|
425 (type . integer))
|
|
426 ((tag . "Date")
|
|
427 (type . choice)
|
|
428 (data ((type . integer)
|
|
429 (default . 0)
|
|
430 (width . 9))
|
|
431 ((tag . "Permanent")
|
|
432 (type . const)
|
|
433 (default . nil))))
|
|
434 ((tag . "Type")
|
|
435 (type . choice)
|
|
436 (data ((tag . "Exact")
|
|
437 (default . E)
|
|
438 (type . const))
|
|
439 ((tag . "Substring")
|
|
440 (default . S)
|
|
441 (type . const))
|
|
442 ((tag . "Regexp")
|
|
443 (default . R)
|
|
444 (type . const))
|
|
445 ((tag . "Fuzzy")
|
|
446 (default . F)
|
|
447 (type . const))
|
|
448 ((tag . "Exact (fold)")
|
|
449 (default . e)
|
|
450 (type . const))
|
|
451 ((tag . "Substring (fold)")
|
|
452 (default . s)
|
|
453 (type . const))
|
|
454 ((tag . "Regexp (fold)")
|
|
455 (default . r)
|
|
456 (type . const))
|
|
457 ((tag . "Fuzzy (fold)")
|
|
458 (default . f)
|
|
459 (type . const))))))))))
|
|
460 (gnus-score-custom-integer-type
|
|
461 (type . list)
|
|
462 (data ((type . repeat)
|
|
463 (header . nil)
|
|
464 (data . ((type . list)
|
|
465 (compact . t)
|
|
466 (data ((tag . "Match")
|
|
467 (type . integer))
|
|
468 ((tag . "Score")
|
|
469 (type . integer))
|
|
470 ((tag . "Date")
|
|
471 (type . choice)
|
|
472 (data ((type . integer)
|
|
473 (default . 0)
|
|
474 (width . 9))
|
|
475 ((tag . "Permanent")
|
|
476 (type . const)
|
|
477 (default . nil))))
|
|
478 ((tag . "Type")
|
|
479 (type . choice)
|
|
480 (data ((tag . "<")
|
|
481 (default . <)
|
|
482 (type . const))
|
|
483 ((tag . ">")
|
|
484 (default . >)
|
|
485 (type . const))
|
|
486 ((tag . "=")
|
|
487 (default . =)
|
|
488 (type . const))
|
|
489 ((tag . ">=")
|
|
490 (default . >=)
|
|
491 (type . const))
|
|
492 ((tag . "<=")
|
|
493 (default . <=)
|
|
494 (type . const))))))))))
|
|
495 (gnus-score-custom-date-type
|
|
496 (type . list)
|
|
497 (data ((type . repeat)
|
|
498 (header . nil)
|
|
499 (data . ((type . list)
|
|
500 (compact . t)
|
|
501 (data ((tag . "Match")
|
|
502 (width . 59)
|
|
503 (type . string))
|
|
504 "\n "
|
|
505 ((tag . "Score")
|
|
506 (type . integer))
|
|
507 ((tag . "Date")
|
|
508 (type . choice)
|
|
509 (data ((type . integer)
|
|
510 (default . 0)
|
|
511 (width . 9))
|
|
512 ((tag . "Permanent")
|
|
513 (type . const)
|
|
514 (default . nil))))
|
|
515 ((tag . "Type")
|
|
516 (type . choice)
|
|
517 (data ((tag . "Before")
|
|
518 (default . before)
|
|
519 (type . const))
|
|
520 ((tag . "After")
|
|
521 (default . after)
|
|
522 (type . const))
|
|
523 ((tag . "At")
|
|
524 (default . at)
|
|
525 (type . const))))))))))))
|
|
526
|
|
527 (defvar gnus-score-custom-file nil
|
|
528 "Name of SCORE file being customized.")
|
|
529
|
|
530 (defun gnus-score-customize ()
|
|
531 "Create a buffer for editing gnus SCORE files."
|
|
532 (interactive)
|
|
533 (let (gnus-score-alist)
|
|
534 (custom-buffer-create "*Score Edit*" gnus-score-custom-data
|
|
535 gnus-score-custom-type-properties
|
|
536 'gnus-score-custom-set
|
|
537 'gnus-score-custom-get
|
|
538 'gnus-score-custom-save))
|
|
539 (make-local-variable 'gnus-score-custom-file)
|
|
540 (setq gnus-score-custom-file
|
|
541 (expand-file-name "SCORE" gnus-kill-files-directory))
|
|
542 (make-local-variable 'gnus-score-alist)
|
|
543 (setq gnus-score-alist nil)
|
|
544 (custom-reset-all))
|
|
545
|
|
546 (defun gnus-score-custom-get (name)
|
|
547 (if (eq name 'file)
|
|
548 gnus-score-custom-file
|
|
549 (let ((entry (assoc (symbol-name name) gnus-score-alist)))
|
|
550 (if entry
|
|
551 (mapcar 'gnus-score-custom-sanify (cdr entry))
|
|
552 (setq entry (assoc name gnus-score-alist))
|
|
553 (if (or (memq name '(files exclude-files local))
|
|
554 (and (eq name 'adapt)
|
|
555 (not (symbolp (car (cdr entry))))))
|
|
556 (cdr entry)
|
|
557 (car (cdr entry)))))))
|
|
558
|
|
559 (defun gnus-score-custom-set (name value)
|
|
560 (cond ((eq name 'file)
|
|
561 (setq gnus-score-custom-file value))
|
|
562 ((assoc (symbol-name name) gnus-score-alist)
|
|
563 (if value
|
|
564 (setcdr (assoc (symbol-name name) gnus-score-alist) value)
|
|
565 (setq gnus-score-alist (delq (assoc (symbol-name name)
|
|
566 gnus-score-alist)
|
|
567 gnus-score-alist))))
|
|
568 ((assoc (symbol-name name) gnus-header-index)
|
|
569 (if value
|
|
570 (setq gnus-score-alist
|
|
571 (cons (cons (symbol-name name) value) gnus-score-alist))))
|
|
572 ((assoc name gnus-score-alist)
|
|
573 (cond ((null value)
|
|
574 (setq gnus-score-alist (delq (assoc name gnus-score-alist)
|
|
575 gnus-score-alist)))
|
|
576 ((and (listp value) (not (eq name 'eval)))
|
|
577 (setcdr (assoc name gnus-score-alist) value))
|
|
578 (t
|
|
579 (setcdr (assoc name gnus-score-alist) (list value)))))
|
|
580 ((null value))
|
|
581 ((and (listp value) (not (eq name 'eval)))
|
|
582 (setq gnus-score-alist (cons (cons name value) gnus-score-alist)))
|
|
583 (t
|
|
584 (setq gnus-score-alist
|
|
585 (cons (cons name (list value)) gnus-score-alist)))))
|
|
586
|
|
587 (defun gnus-score-custom-sanify (entry)
|
|
588 (list (nth 0 entry)
|
|
589 (or (nth 1 entry) gnus-score-interactive-default-score)
|
|
590 (nth 2 entry)
|
|
591 (cond ((null (nth 3 entry))
|
|
592 's)
|
|
593 ((memq (nth 3 entry) '(before after at >= <=))
|
|
594 (nth 3 entry))
|
|
595 (t
|
|
596 (intern (substring (symbol-name (nth 3 entry)) 0 1))))))
|
|
597
|
|
598 (defvar gnus-score-cache nil)
|
|
599
|
|
600 (defun gnus-score-custom-load ()
|
|
601 (interactive)
|
|
602 (let ((file (custom-name-value 'file)))
|
|
603 (if (eq file custom-nil)
|
|
604 (error "You must specify a file name"))
|
|
605 (setq file (expand-file-name file gnus-kill-files-directory))
|
|
606 (gnus-score-load file)
|
|
607 (setq gnus-score-custom-file file)
|
|
608 (custom-reset-all)
|
|
609 (gnus-message 4 "Loaded")))
|
|
610
|
|
611 (defun gnus-score-custom-save ()
|
|
612 (interactive)
|
|
613 (custom-apply-all)
|
|
614 (gnus-score-remove-from-cache gnus-score-custom-file)
|
|
615 (let ((file gnus-score-custom-file)
|
|
616 (score gnus-score-alist)
|
|
617 emacs-lisp-mode-hook)
|
|
618 (save-excursion
|
|
619 (set-buffer (get-buffer-create "*Score*"))
|
|
620 (buffer-disable-undo (current-buffer))
|
|
621 (erase-buffer)
|
|
622 (pp score (current-buffer))
|
|
623 (gnus-make-directory (file-name-directory file))
|
|
624 (write-region (point-min) (point-max) file nil 'silent)
|
|
625 (kill-buffer (current-buffer))))
|
|
626 (gnus-message 4 "Saved"))
|
|
627
|
|
628 (provide 'gnus-edit)
|
|
629
|
|
630 ;;; gnus-edit.el end here
|