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