mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-27 10:54:40 +00:00
631 lines
21 KiB
EmacsLisp
631 lines
21 KiB
EmacsLisp
;;; gnus-edit.el --- Gnus SCORE file editing
|
|
;; Copyright (C) 1995,96 Free Software Foundation, Inc.
|
|
;;
|
|
;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
|
|
;; Keywords: news, help
|
|
;; Version: 0.2
|
|
|
|
;;; Commentary:
|
|
;;
|
|
;; Type `M-x gnus-score-customize RET' to invoke.
|
|
|
|
;;; Code:
|
|
|
|
(require 'custom)
|
|
(require 'gnus-score)
|
|
(eval-when-compile (require 'cl))
|
|
|
|
(defconst gnus-score-custom-data
|
|
'((tag . "Score")
|
|
(doc . "Customization of Gnus SCORE files.
|
|
|
|
SCORE files allow you to assign a score to each article when you enter
|
|
a group, and automatically mark the articles as read or delete them
|
|
based on the score. In the summary buffer you can use the score to
|
|
sort the articles by score (`C-c C-s C-s') or to jump to the unread
|
|
article with the highest score (`,').")
|
|
(type . group)
|
|
(data "\n"
|
|
((header . nil)
|
|
(doc . "Name of SCORE file to customize.
|
|
|
|
Enter the name in the `File' field, then push the [Load] button to
|
|
load it. When done editing, push the [Save] button to save the file.
|
|
|
|
Several score files may apply to each group, and several groups may
|
|
use the same score file. This is controlled implicitly by the name of
|
|
the score file and the value of the global variable
|
|
`gnus-score-find-score-files-function', and explicitly by the the
|
|
`Files' and `Exclude Files' entries.")
|
|
(compact . t)
|
|
(type . group)
|
|
(data ((tag . "Load")
|
|
(type . button)
|
|
(query . gnus-score-custom-load))
|
|
((tag . "Save")
|
|
(type . button)
|
|
(query . gnus-score-custom-save))
|
|
((name . file)
|
|
(tag . "File")
|
|
(directory . gnus-kill-files-directory)
|
|
(default-file . "SCORE")
|
|
(type . file))))
|
|
((name . files)
|
|
(tag . "Files")
|
|
(doc . "\
|
|
List of score files to load when the the current score file is loaded.
|
|
You can use this to share score entries between multiple score files.
|
|
|
|
Push the `[INS]' button add a score file to the list, or `[DEL]' to
|
|
delete a score file from the list.")
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data (type . file)
|
|
(directory . gnus-kill-files-directory)))))
|
|
((name . exclude-files)
|
|
(tag . "Exclude Files")
|
|
(doc . "\
|
|
List of score files to exclude when the the current score file is loaded.
|
|
You can use this if you have a score file you want to share between a
|
|
number of newsgroups, except for the newsgroup this score file
|
|
matches. [ Did anyone get that? ]
|
|
|
|
Push the `[INS]' button add a score file to the list, or `[DEL]' to
|
|
delete a score file from the list.")
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data (type . file)
|
|
(directory . gnus-kill-files-directory)))))
|
|
((name . mark)
|
|
(tag . "Mark")
|
|
(doc . "\
|
|
Articles below this score will be automatically marked as read.
|
|
|
|
This means that when you enter the summary buffer, the articles will
|
|
be shown but will already be marked as read. You can then press `x'
|
|
to get rid of them entirely.
|
|
|
|
By default articles with a negative score will be marked as read. To
|
|
change this, push the `Mark' button, and choose `Integer'. You can
|
|
then enter a value in the `Mark' field.")
|
|
(type . gnus-score-custom-maybe-type))
|
|
((name . expunge)
|
|
(tag . "Expunge")
|
|
(doc . "\
|
|
Articles below this score will not be shown in the summary buffer.")
|
|
(type . gnus-score-custom-maybe-type))
|
|
((name . mark-and-expunge)
|
|
(tag . "Mark and Expunge")
|
|
(doc . "\
|
|
Articles below this score will be marked as read, but not shown.
|
|
|
|
Someone should explain me the difference between this and `expunge'
|
|
alone or combined with `mark'.")
|
|
(type . gnus-score-custom-maybe-type))
|
|
((name . eval)
|
|
(tag . "Eval")
|
|
(doc . "\
|
|
Evaluate this lisp expression when the entering summary buffer.")
|
|
(type . sexp))
|
|
((name . read-only)
|
|
(tag . "Read Only")
|
|
(doc . "Read-only score files will not be updated or saved.
|
|
Except from this buffer, of course!")
|
|
(type . toggle))
|
|
((type . doc)
|
|
(doc . "\
|
|
Each news header has an associated list of score entries.
|
|
You can use the [INS] buttons to add new score entries anywhere in the
|
|
list, or the [DEL] buttons to delete specific score entries.
|
|
|
|
Each score entry should specify a string that should be matched with
|
|
the content actual header in order to determine whether the entry
|
|
applies to that header. Enter that string in the `Match' field.
|
|
|
|
If the score entry matches, the articles score will be adjusted with
|
|
some amount. Enter that amount in the in the `Score' field. You
|
|
should specify a positive amount for score entries that matches
|
|
articles you find interesting, and a negative amount for score entries
|
|
matching articles you would rather avoid. The final score for the
|
|
article will be the sum of the score of all score entries that match
|
|
the article.
|
|
|
|
The score entry can be either permanent or expirable. To make the
|
|
entry permanent, push the `Date' button and choose the `Permanent'
|
|
entry. To make the entry expirable, choose instead the `Integer'
|
|
entry. After choosing the you can enter the date the score entry was
|
|
last matched in the `Date' field. The date will be automatically
|
|
updated each time the score entry matches an article. When the date
|
|
become too old, the the score entry will be removed.
|
|
|
|
For your convenience, the date is specified as the number of days
|
|
elapsed since the (imaginary) Gregorian date Sunday, December 31, 1
|
|
BC.
|
|
|
|
Finally, you can choose what kind of match you want to perform by
|
|
pushing the `Type' button. For most entries you can choose between
|
|
`Exact' which mean the header content must be exactly identical to the
|
|
match string, or `Substring' meaning the match string should be
|
|
somewhere in the header content, or even `Regexp' to use Emacs regular
|
|
expression matching. The last choice is `Fuzzy' which is like `Exact'
|
|
except that whitespace derivations, a beginning `Re:' or a terminating
|
|
parenthetical remark are all ignored. Each of the four types have a
|
|
variant which will ignore case in the comparison. That variant is
|
|
indicated with a `(fold)' after its name."))
|
|
((name . from)
|
|
(tag . "From")
|
|
(doc . "Scoring based on the authors email address.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . subject)
|
|
(tag . "Subject")
|
|
(doc . "Scoring based on the articles subject.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . followup)
|
|
(tag . "Followup")
|
|
(doc . "Scoring based on who the article is a followup to.
|
|
|
|
If you want to see all followups to your own articles, add an entry
|
|
with a positive score matching your email address here. You can also
|
|
put an entry with a negative score matching someone who is so annoying
|
|
that you don't even want to see him quoted in followups.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . xref)
|
|
(tag . "Xref")
|
|
(doc . "Scoring based on article crossposting.
|
|
|
|
If you want to score based on which newsgroups an article is posted
|
|
to, this is the header to use. The syntax is a little different from
|
|
the `Newsgroups' header, but scoring in `Xref' is much faster. As an
|
|
example, to match all crossposted articles match on `:.*:' using the
|
|
`Regexp' type.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . references)
|
|
(tag . "References")
|
|
(doc . "Scoring based on article references.
|
|
|
|
The `References' header gives you an alternative way to score on
|
|
followups. If you for example want to see follow all discussions
|
|
where people from `iesd.auc.dk' school participate, you can add a
|
|
substring match on `iesd.auc.dk>' on this header.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . message-id)
|
|
(tag . "Message-ID")
|
|
(doc . "Scoring based on the articles message-id.
|
|
|
|
This isn't very useful, but Lars like completeness. You can use it to
|
|
match all messaged generated by recent Gnus version with a `Substring'
|
|
match on `.fsf@'.")
|
|
(type . gnus-score-custom-string-type))
|
|
((type . doc)
|
|
(doc . "\
|
|
WARNING: Scoring on the following three pseudo headers is very slow!
|
|
Scoring on any of the real headers use a technique that avoids
|
|
scanning the entire article, only the actual headers you score on are
|
|
scanned, and this scanning has been heavily optimized. Using just a
|
|
single entry for one the three pseudo-headers `Head', `Body', and
|
|
`All' will require GNUS to retrieve and scan the entire article, which
|
|
can be very slow on large groups. However, if you add one entry for
|
|
any of these headers, you can just as well add several. Each
|
|
subsequent entry cost relatively little extra time."))
|
|
((name . head)
|
|
(tag . "Head")
|
|
(doc . "Scoring based on the article header.
|
|
|
|
Instead of matching the content of a single header, the entire header
|
|
section of the article is matched. You can use this to match on
|
|
arbitrary headers, foe example to single out TIN lusers, use a substring
|
|
match on `Newsreader: TIN'. That should get 'em!")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . body)
|
|
(tag . "Body")
|
|
(doc . "Scoring based on the article body.
|
|
|
|
If you think any article that mentions `Kibo' is inherently
|
|
interesting, do a substring match on His name. You Are Allowed.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . all)
|
|
(tag . "All")
|
|
(doc . "Scoring based on the whole article.")
|
|
(type . gnus-score-custom-string-type))
|
|
((name . date)
|
|
(tag . "Date")
|
|
(doc . "Scoring based on article date.
|
|
|
|
You can change the score of articles that have been posted before,
|
|
after, or at a specific date. You should add the date in the `Match'
|
|
field, and then select `before', `after', or `at' by pushing the
|
|
`Type' button. Imagine you want to lower the score of very old
|
|
articles, or want to raise the score of articles from the future (such
|
|
things happen!). Then you can't use date scoring for that. In fact,
|
|
I can't imagine anything you would want to use this for.
|
|
|
|
For your convenience, the date is specified in Usenet date format.")
|
|
(type . gnus-score-custom-date-type))
|
|
((type . doc)
|
|
(doc . "\
|
|
The Lines and Chars headers use integer based scoring.
|
|
|
|
This means that you should write an integer in the `Match' field, and
|
|
the push the `Type' field to if the `Chars' or `Lines' header should
|
|
be larger, equal, or smaller than the number you wrote in the match
|
|
field."))
|
|
((name . chars)
|
|
(tag . "Characters")
|
|
(doc . "Scoring based on the number of characters in the article.")
|
|
(type . gnus-score-custom-integer-type))
|
|
((name . lines)
|
|
(tag . "Lines")
|
|
(doc . "Scoring based on the number of lines in the article.")
|
|
(type . gnus-score-custom-integer-type))
|
|
((name . orphan)
|
|
(tag . "Orphan")
|
|
(doc . "Score to add to articles with no parents.")
|
|
(type . gnus-score-custom-maybe-type))
|
|
((name . adapt)
|
|
(tag . "Adapt")
|
|
(doc . "Adapting the score files to your newsreading habits.
|
|
|
|
When you have finished reading a group GNUS can automatically create
|
|
new score entries based on which articles you read and which you
|
|
skipped. This is normally controlled by the two global variables
|
|
`gnus-use-adaptive-scoring' and `gnus-default-adaptive-score-alist',
|
|
The first determines whether adaptive scoring should be enabled or
|
|
not, while the second determines what score entries should be created.
|
|
|
|
You can overwrite the setting of `gnus-use-adaptive-scoring' by
|
|
selecting `Enable' or `Disable' by pressing the `Adapt' button.
|
|
Selecting `Custom' will allow you to specify the exact adaptation
|
|
rules (overwriting `gnus-default-adaptive-score-alist').")
|
|
(type . choice)
|
|
(data ((tag . "Default")
|
|
(default . nil)
|
|
(type . const))
|
|
((tag . "Enable")
|
|
(default . t)
|
|
(type . const))
|
|
((tag . "Disable")
|
|
(default . ignore)
|
|
(type . const))
|
|
((tag . "Custom")
|
|
(doc . "Customization of adaptive scoring.
|
|
|
|
Each time you read an article it will be marked as read. Likewise, if
|
|
you delete it it will be marked as deleted, and if you tick it it will
|
|
be marked as ticked. When you leave a group, GNUS can automatically
|
|
create score file entries based on these marks, so next time you enter
|
|
the group articles with subjects that you read last time have higher
|
|
score and articles with subjects that deleted will have lower score.
|
|
|
|
Below is a list of such marks. You can insert new marks to the list
|
|
by pushing on one of the `[INS]' buttons in the left margin to create
|
|
a new entry and then pushing the `Mark' button to select the mark.
|
|
For each mark there is another list, this time of article headers,
|
|
which determine how the mark should affect that header. The `[INS]'
|
|
buttons of this list are indented to indicate that the belong to the
|
|
mark above. Push the `Header' button to choose a header, and then
|
|
enter a score value in the `Score' field.
|
|
|
|
For each article that are marked with `Mark' when you leave the
|
|
group, a temporary score entry for the articles `Header' with the
|
|
value of `Score' will be added the adapt file. If the score entry
|
|
already exists, `Score' will be added to its value. If you understood
|
|
that, you are smart.
|
|
|
|
You can select the special value `Other' when pressing the `Mark' or
|
|
`Header' buttons. This is because Lars might add more useful values
|
|
there. If he does, it is up to you to figure out what they are named.")
|
|
(type . list)
|
|
(default . ((__uninitialized__)))
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data . ((type . list)
|
|
(header . nil)
|
|
(compact . t)
|
|
(data ((type . choice)
|
|
(tag . "Mark")
|
|
(data ((tag . "Unread")
|
|
(default . gnus-unread-mark)
|
|
(type . const))
|
|
((tag . "Ticked")
|
|
(default . gnus-ticked-mark)
|
|
(type . const))
|
|
((tag . "Dormant")
|
|
(default . gnus-dormant-mark)
|
|
(type . const))
|
|
((tag . "Deleted")
|
|
(default . gnus-del-mark)
|
|
(type . const))
|
|
((tag . "Read")
|
|
(default . gnus-read-mark)
|
|
(type . const))
|
|
((tag . "Expirable")
|
|
(default . gnus-expirable-mark)
|
|
(type . const))
|
|
((tag . "Killed")
|
|
(default . gnus-killed-mark)
|
|
(type . const))
|
|
((tag . "Kill-file")
|
|
(default . gnus-kill-file-mark)
|
|
(type . const))
|
|
((tag . "Low-score")
|
|
(default . gnus-low-score-mark)
|
|
(type . const))
|
|
((tag . "Catchup")
|
|
(default . gnus-catchup-mark)
|
|
(type . const))
|
|
((tag . "Ancient")
|
|
(default . gnus-ancient-mark)
|
|
(type . const))
|
|
((tag . "Canceled")
|
|
(default . gnus-canceled-mark)
|
|
(type . const))
|
|
((prompt . "Other")
|
|
(default . ??)
|
|
(type . sexp))))
|
|
((type . repeat)
|
|
(prefix . " ")
|
|
(data . ((type . list)
|
|
(compact . t)
|
|
(data ((tag . "Header")
|
|
(type . choice)
|
|
(data ((tag . "Subject")
|
|
(default . subject)
|
|
(type . const))
|
|
((prompt . "From")
|
|
(tag . "From ")
|
|
(default . from)
|
|
(type . const))
|
|
((prompt . "Other")
|
|
(width . 7)
|
|
(default . nil)
|
|
(type . symbol))))
|
|
((tag . "Score")
|
|
(type . integer))))))))))))))
|
|
((name . local)
|
|
(tag . "Local")
|
|
(doc . "\
|
|
List of local variables to set when this score file is loaded.
|
|
|
|
Using this entry can provide a convenient way to set variables that
|
|
will affect the summary mode for only some specific groups, i.e. those
|
|
groups matched by the current score file.")
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data . ((type . list)
|
|
(compact . t)
|
|
(data ((tag . "Name")
|
|
(width . 26)
|
|
(type . symbol))
|
|
((tag . "Value")
|
|
(width . 26)
|
|
(type . sexp)))))))))))
|
|
|
|
(defconst gnus-score-custom-type-properties
|
|
'((gnus-score-custom-maybe-type
|
|
(type . choice)
|
|
(data ((type . integer)
|
|
(default . 0))
|
|
((tag . "Default")
|
|
(type . const)
|
|
(default . nil))))
|
|
(gnus-score-custom-string-type
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data . ((type . list)
|
|
(compact . t)
|
|
(data ((tag . "Match")
|
|
(width . 59)
|
|
(type . string))
|
|
"\n "
|
|
((tag . "Score")
|
|
(type . integer))
|
|
((tag . "Date")
|
|
(type . choice)
|
|
(data ((type . integer)
|
|
(default . 0)
|
|
(width . 9))
|
|
((tag . "Permanent")
|
|
(type . const)
|
|
(default . nil))))
|
|
((tag . "Type")
|
|
(type . choice)
|
|
(data ((tag . "Exact")
|
|
(default . E)
|
|
(type . const))
|
|
((tag . "Substring")
|
|
(default . S)
|
|
(type . const))
|
|
((tag . "Regexp")
|
|
(default . R)
|
|
(type . const))
|
|
((tag . "Fuzzy")
|
|
(default . F)
|
|
(type . const))
|
|
((tag . "Exact (fold)")
|
|
(default . e)
|
|
(type . const))
|
|
((tag . "Substring (fold)")
|
|
(default . s)
|
|
(type . const))
|
|
((tag . "Regexp (fold)")
|
|
(default . r)
|
|
(type . const))
|
|
((tag . "Fuzzy (fold)")
|
|
(default . f)
|
|
(type . const))))))))))
|
|
(gnus-score-custom-integer-type
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data . ((type . list)
|
|
(compact . t)
|
|
(data ((tag . "Match")
|
|
(type . integer))
|
|
((tag . "Score")
|
|
(type . integer))
|
|
((tag . "Date")
|
|
(type . choice)
|
|
(data ((type . integer)
|
|
(default . 0)
|
|
(width . 9))
|
|
((tag . "Permanent")
|
|
(type . const)
|
|
(default . nil))))
|
|
((tag . "Type")
|
|
(type . choice)
|
|
(data ((tag . "<")
|
|
(default . <)
|
|
(type . const))
|
|
((tag . ">")
|
|
(default . >)
|
|
(type . const))
|
|
((tag . "=")
|
|
(default . =)
|
|
(type . const))
|
|
((tag . ">=")
|
|
(default . >=)
|
|
(type . const))
|
|
((tag . "<=")
|
|
(default . <=)
|
|
(type . const))))))))))
|
|
(gnus-score-custom-date-type
|
|
(type . list)
|
|
(data ((type . repeat)
|
|
(header . nil)
|
|
(data . ((type . list)
|
|
(compact . t)
|
|
(data ((tag . "Match")
|
|
(width . 59)
|
|
(type . string))
|
|
"\n "
|
|
((tag . "Score")
|
|
(type . integer))
|
|
((tag . "Date")
|
|
(type . choice)
|
|
(data ((type . integer)
|
|
(default . 0)
|
|
(width . 9))
|
|
((tag . "Permanent")
|
|
(type . const)
|
|
(default . nil))))
|
|
((tag . "Type")
|
|
(type . choice)
|
|
(data ((tag . "Before")
|
|
(default . before)
|
|
(type . const))
|
|
((tag . "After")
|
|
(default . after)
|
|
(type . const))
|
|
((tag . "At")
|
|
(default . at)
|
|
(type . const))))))))))))
|
|
|
|
(defvar gnus-score-custom-file nil
|
|
"Name of SCORE file being customized.")
|
|
|
|
(defun gnus-score-customize ()
|
|
"Create a buffer for editing gnus SCORE files."
|
|
(interactive)
|
|
(let (gnus-score-alist)
|
|
(custom-buffer-create "*Score Edit*" gnus-score-custom-data
|
|
gnus-score-custom-type-properties
|
|
'gnus-score-custom-set
|
|
'gnus-score-custom-get
|
|
'gnus-score-custom-save))
|
|
(make-local-variable 'gnus-score-custom-file)
|
|
(setq gnus-score-custom-file
|
|
(expand-file-name "SCORE" gnus-kill-files-directory))
|
|
(make-local-variable 'gnus-score-alist)
|
|
(setq gnus-score-alist nil)
|
|
(custom-reset-all))
|
|
|
|
(defun gnus-score-custom-get (name)
|
|
(if (eq name 'file)
|
|
gnus-score-custom-file
|
|
(let ((entry (assoc (symbol-name name) gnus-score-alist)))
|
|
(if entry
|
|
(mapcar 'gnus-score-custom-sanify (cdr entry))
|
|
(setq entry (assoc name gnus-score-alist))
|
|
(if (or (memq name '(files exclude-files local))
|
|
(and (eq name 'adapt)
|
|
(not (symbolp (car (cdr entry))))))
|
|
(cdr entry)
|
|
(car (cdr entry)))))))
|
|
|
|
(defun gnus-score-custom-set (name value)
|
|
(cond ((eq name 'file)
|
|
(setq gnus-score-custom-file value))
|
|
((assoc (symbol-name name) gnus-score-alist)
|
|
(if value
|
|
(setcdr (assoc (symbol-name name) gnus-score-alist) value)
|
|
(setq gnus-score-alist (delq (assoc (symbol-name name)
|
|
gnus-score-alist)
|
|
gnus-score-alist))))
|
|
((assoc (symbol-name name) gnus-header-index)
|
|
(if value
|
|
(setq gnus-score-alist
|
|
(cons (cons (symbol-name name) value) gnus-score-alist))))
|
|
((assoc name gnus-score-alist)
|
|
(cond ((null value)
|
|
(setq gnus-score-alist (delq (assoc name gnus-score-alist)
|
|
gnus-score-alist)))
|
|
((and (listp value) (not (eq name 'eval)))
|
|
(setcdr (assoc name gnus-score-alist) value))
|
|
(t
|
|
(setcdr (assoc name gnus-score-alist) (list value)))))
|
|
((null value))
|
|
((and (listp value) (not (eq name 'eval)))
|
|
(setq gnus-score-alist (cons (cons name value) gnus-score-alist)))
|
|
(t
|
|
(setq gnus-score-alist
|
|
(cons (cons name (list value)) gnus-score-alist)))))
|
|
|
|
(defun gnus-score-custom-sanify (entry)
|
|
(list (nth 0 entry)
|
|
(or (nth 1 entry) gnus-score-interactive-default-score)
|
|
(nth 2 entry)
|
|
(cond ((null (nth 3 entry))
|
|
's)
|
|
((memq (nth 3 entry) '(before after at >= <=))
|
|
(nth 3 entry))
|
|
(t
|
|
(intern (substring (symbol-name (nth 3 entry)) 0 1))))))
|
|
|
|
(defvar gnus-score-cache nil)
|
|
|
|
(defun gnus-score-custom-load ()
|
|
(interactive)
|
|
(let ((file (custom-name-value 'file)))
|
|
(if (eq file custom-nil)
|
|
(error "You must specify a file name"))
|
|
(setq file (expand-file-name file gnus-kill-files-directory))
|
|
(gnus-score-load file)
|
|
(setq gnus-score-custom-file file)
|
|
(custom-reset-all)
|
|
(gnus-message 4 "Loaded")))
|
|
|
|
(defun gnus-score-custom-save ()
|
|
(interactive)
|
|
(custom-apply-all)
|
|
(gnus-score-remove-from-cache gnus-score-custom-file)
|
|
(let ((file gnus-score-custom-file)
|
|
(score gnus-score-alist)
|
|
emacs-lisp-mode-hook)
|
|
(save-excursion
|
|
(set-buffer (get-buffer-create "*Score*"))
|
|
(buffer-disable-undo (current-buffer))
|
|
(erase-buffer)
|
|
(pp score (current-buffer))
|
|
(gnus-make-directory (file-name-directory file))
|
|
(write-region (point-min) (point-max) file nil 'silent)
|
|
(kill-buffer (current-buffer))))
|
|
(gnus-message 4 "Saved"))
|
|
|
|
(provide 'gnus-edit)
|
|
|
|
;;; gnus-edit.el end here
|