comparison lisp/gnus/gnus-score.el @ 30:ec9a17fef872 r19-15b98

Import from CVS: tag r19-15b98
author cvs
date Mon, 13 Aug 2007 08:52:29 +0200
parents 4103f0995bd7
children e04119814345
comparison
equal deleted inserted replaced
29:7976500f47f9 30:ec9a17fef872
178 allowed so that one may use gnus-score-file-single-match-alist to 178 allowed so that one may use gnus-score-file-single-match-alist to
179 set this variable.) 179 set this variable.)
180 180
181 * A function. 181 * A function.
182 If the function returns non-nil, the result will be used 182 If the function returns non-nil, the result will be used
183 as the home score file. The function will be passed the 183 as the home score file. The function will be passed the
184 name of the group as its parameter. 184 name of the group as its parameter.
185 185
186 * A string. Use the string as the home score file. 186 * A string. Use the string as the home score file.
187 187
188 The list will be traversed from the beginning towards the end looking 188 The list will be traversed from the beginning towards the end looking
203 (repeat (choice string 203 (repeat (choice string
204 (cons regexp (repeat file)) 204 (cons regexp (repeat file))
205 function)) 205 function))
206 function)) 206 function))
207 207
208 (defcustom gnus-default-adaptive-score-alist 208 (defcustom gnus-default-adaptive-score-alist
209 '((gnus-kill-file-mark) 209 '((gnus-kill-file-mark)
210 (gnus-unread-mark) 210 (gnus-unread-mark)
211 (gnus-read-mark (from 3) (subject 30)) 211 (gnus-read-mark (from 3) (subject 30))
212 (gnus-catchup-mark (subject -10)) 212 (gnus-catchup-mark (subject -10))
213 (gnus-killed-mark (from -1) (subject -20)) 213 (gnus-killed-mark (from -1) (subject -20))
243 "try" "re") 243 "try" "re")
244 "Default list of words to be ignored when doing adaptive word scoring." 244 "Default list of words to be ignored when doing adaptive word scoring."
245 :group 'gnus-score-adapt 245 :group 'gnus-score-adapt
246 :type '(repeat string)) 246 :type '(repeat string))
247 247
248 (defcustom gnus-default-adaptive-word-score-alist 248 (defcustom gnus-default-adaptive-word-score-alist
249 `((,gnus-read-mark . 30) 249 `((,gnus-read-mark . 30)
250 (,gnus-catchup-mark . -10) 250 (,gnus-catchup-mark . -10)
251 (,gnus-killed-mark . -20) 251 (,gnus-killed-mark . -20)
252 (,gnus-del-mark . -15)) 252 (,gnus-del-mark . -15))
253 "Alist of marks and scores." 253 "Alist of marks and scores."
385 (defvar gnus-score-trace nil) 385 (defvar gnus-score-trace nil)
386 (defvar gnus-score-edit-buffer nil) 386 (defvar gnus-score-edit-buffer nil)
387 387
388 (defvar gnus-score-alist nil 388 (defvar gnus-score-alist nil
389 "Alist containing score information. 389 "Alist containing score information.
390 The keys can be symbols or strings. The following symbols are defined. 390 The keys can be symbols or strings. The following symbols are defined.
391 391
392 touched: If this alist has been modified. 392 touched: If this alist has been modified.
393 mark: Automatically mark articles below this. 393 mark: Automatically mark articles below this.
394 expunge: Automatically expunge articles below this. 394 expunge: Automatically expunge articles below this.
395 files: List of other score files to load when loading this one. 395 files: List of other score files to load when loading this one.
467 (interactive "P") 467 (interactive "P")
468 (gnus-set-global-variables) 468 (gnus-set-global-variables)
469 (let* ((nscore (gnus-score-default score)) 469 (let* ((nscore (gnus-score-default score))
470 (prefix (if (< nscore 0) ?L ?I)) 470 (prefix (if (< nscore 0) ?L ?I))
471 (increase (> nscore 0)) 471 (increase (> nscore 0))
472 (char-to-header 472 (char-to-header
473 '((?a "from" nil nil string) 473 '((?a "from" nil nil string)
474 (?s "subject" nil nil string) 474 (?s "subject" nil nil string)
475 (?b "body" "" nil body-string) 475 (?b "body" "" nil body-string)
476 (?h "head" "" nil body-string) 476 (?h "head" "" nil body-string)
477 (?i "message-id" nil t string) 477 (?i "message-id" nil t string)
496 (?= = "equal to number" number))) 496 (?= = "equal to number" number)))
497 (char-to-perm 497 (char-to-perm
498 (list (list ?t (current-time-string) "temporary") 498 (list (list ?t (current-time-string) "temporary")
499 '(?p perm "permanent") '(?i now "immediate"))) 499 '(?p perm "permanent") '(?i now "immediate")))
500 (mimic gnus-score-mimic-keymap) 500 (mimic gnus-score-mimic-keymap)
501 (hchar (and gnus-score-default-header 501 (hchar (and gnus-score-default-header
502 (aref (symbol-name gnus-score-default-header) 0))) 502 (aref (symbol-name gnus-score-default-header) 0)))
503 (tchar (and gnus-score-default-type 503 (tchar (and gnus-score-default-type
504 (aref (symbol-name gnus-score-default-type) 0))) 504 (aref (symbol-name gnus-score-default-type) 0)))
505 (pchar (and gnus-score-default-duration 505 (pchar (and gnus-score-default-duration
506 (aref (symbol-name gnus-score-default-duration) 0))) 506 (aref (symbol-name gnus-score-default-duration) 0)))
507 entry temporary type match) 507 entry temporary type match)
508 508
509 (unwind-protect 509 (unwind-protect
510 (progn 510 (progn
511 511
512 ;; First we read the header to score. 512 ;; First we read the header to score.
513 (while (not hchar) 513 (while (not hchar)
514 (if mimic 514 (if mimic
515 (progn 515 (progn
516 (sit-for 1) 516 (sit-for 1)
517 (message "%c-" prefix)) 517 (message "%c-" prefix))
518 (message "%s header (%s?): " (if increase "Increase" "Lower") 518 (message "%s header (%s?): " (if increase "Increase" "Lower")
519 (mapconcat (lambda (s) (char-to-string (car s))) 519 (mapconcat (lambda (s) (char-to-string (car s)))
520 char-to-header ""))) 520 char-to-header "")))
530 (when (/= (downcase hchar) hchar) 530 (when (/= (downcase hchar) hchar)
531 ;; This was a majuscule, so we end reading and set the defaults. 531 ;; This was a majuscule, so we end reading and set the defaults.
532 (if mimic (message "%c %c" prefix hchar) (message "")) 532 (if mimic (message "%c %c" prefix hchar) (message ""))
533 (setq tchar (or tchar ?s) 533 (setq tchar (or tchar ?s)
534 pchar (or pchar ?t))) 534 pchar (or pchar ?t)))
535 535
536 ;; We continue reading - the type. 536 ;; We continue reading - the type.
537 (while (not tchar) 537 (while (not tchar)
538 (if mimic 538 (if mimic
539 (progn 539 (progn
540 (sit-for 1) (message "%c %c-" prefix hchar)) 540 (sit-for 1) (message "%c %c-" prefix hchar))
591 (when (and (eq (1+ prefix) 77) 591 (when (and (eq (1+ prefix) 77)
592 (eq (+ hchar 12) 109) 592 (eq (+ hchar 12) 109)
593 (eq tchar 114) 593 (eq tchar 114)
594 (eq (- pchar 4) 111)) 594 (eq (- pchar 4) 111))
595 (error "You rang?")) 595 (error "You rang?"))
596 (if mimic 596 (if mimic
597 (error "%c %c %c %c" prefix hchar tchar pchar) 597 (error "%c %c %c %c" prefix hchar tchar pchar)
598 (error "")))) 598 (error ""))))
599 ;; Always kill the score help buffer. 599 ;; Always kill the score help buffer.
600 (gnus-score-kill-help-buffer)) 600 (gnus-score-kill-help-buffer))
601 601
602 ;; We have all the data, so we enter this score. 602 ;; We have all the data, so we enter this score.
603 (setq match (if (string= (nth 2 entry) "") "" 603 (setq match (if (string= (nth 2 entry) "") ""
604 (gnus-summary-header (or (nth 2 entry) (nth 1 entry))))) 604 (gnus-summary-header (or (nth 2 entry) (nth 1 entry)))))
605 605
606 ;; Modify the match, perhaps. 606 ;; Modify the match, perhaps.
607 (cond 607 (cond
608 ((equal (nth 1 entry) "xref") 608 ((equal (nth 1 entry) "xref")
609 (when (string-match "^Xref: *" match) 609 (when (string-match "^Xref: *" match)
610 (setq match (substring match (match-end 0)))) 610 (setq match (substring match (match-end 0))))
611 (when (string-match "^[^:]* +" match) 611 (when (string-match "^[^:]* +" match)
612 (setq match (substring match (match-end 0)))))) 612 (setq match (substring match (match-end 0))))))
613 613
614 (when (memq type '(r R regexp Regexp)) 614 (when (memq type '(r R regexp Regexp))
615 (setq match (regexp-quote match))) 615 (setq match (regexp-quote match)))
616 616
617 (gnus-summary-score-entry 617 (gnus-summary-score-entry
618 (nth 1 entry) ; Header 618 (nth 1 entry) ; Header
622 (if (eq temporary 'perm) ; Temp 622 (if (eq temporary 'perm) ; Temp
623 nil 623 nil
624 temporary) 624 temporary)
625 (not (nth 3 entry))) ; Prompt 625 (not (nth 3 entry))) ; Prompt
626 )) 626 ))
627 627
628 (defun gnus-score-insert-help (string alist idx) 628 (defun gnus-score-insert-help (string alist idx)
629 (setq gnus-score-help-winconf (current-window-configuration)) 629 (setq gnus-score-help-winconf (current-window-configuration))
630 (save-excursion 630 (save-excursion
631 (set-buffer (get-buffer-create "*Score Help*")) 631 (set-buffer (get-buffer-create "*Score Help*"))
632 (buffer-disable-undo (current-buffer)) 632 (buffer-disable-undo (current-buffer))
644 (setq max n)) 644 (setq max n))
645 (setq list (cdr list))) 645 (setq list (cdr list)))
646 (setq max (+ max 4)) ; %c, `:', SPACE, a SPACE at end 646 (setq max (+ max 4)) ; %c, `:', SPACE, a SPACE at end
647 (setq n (/ (1- (window-width)) max)) ; items per line 647 (setq n (/ (1- (window-width)) max)) ; items per line
648 (setq width (/ (1- (window-width)) n)) ; width of each item 648 (setq width (/ (1- (window-width)) n)) ; width of each item
649 ;; insert `n' items, each in a field of width `width' 649 ;; insert `n' items, each in a field of width `width'
650 (while alist 650 (while alist
651 (if (< i n) 651 (if (< i n)
652 () 652 ()
653 (setq i 0) 653 (setq i 0)
654 (delete-char -1) ; the `\n' takes a char 654 (delete-char -1) ; the `\n' takes a char
663 (split-window) 663 (split-window)
664 (pop-to-buffer "*Score Help*") 664 (pop-to-buffer "*Score Help*")
665 (let ((window-min-height 1)) 665 (let ((window-min-height 1))
666 (shrink-window-if-larger-than-buffer)) 666 (shrink-window-if-larger-than-buffer))
667 (select-window (get-buffer-window gnus-summary-buffer)))) 667 (select-window (get-buffer-window gnus-summary-buffer))))
668 668
669 (defun gnus-summary-header (header &optional no-err) 669 (defun gnus-summary-header (header &optional no-err)
670 ;; Return HEADER for current articles, or error. 670 ;; Return HEADER for current articles, or error.
671 (let ((article (gnus-summary-article-number)) 671 (let ((article (gnus-summary-article-number))
672 headers) 672 headers)
673 (if article 673 (if article
681 (error "No article on current line") 681 (error "No article on current line")
682 nil)))) 682 nil))))
683 683
684 (defun gnus-newsgroup-score-alist () 684 (defun gnus-newsgroup-score-alist ()
685 (or 685 (or
686 (let ((param-file (gnus-group-find-parameter 686 (let ((param-file (gnus-group-find-parameter
687 gnus-newsgroup-name 'score-file))) 687 gnus-newsgroup-name 'score-file)))
688 (when param-file 688 (when param-file
689 (gnus-score-load param-file))) 689 (gnus-score-load param-file)))
690 (gnus-score-load 690 (gnus-score-load
691 (gnus-score-file-name gnus-newsgroup-name))) 691 (gnus-score-file-name gnus-newsgroup-name)))
692 gnus-score-alist) 692 gnus-score-alist)
693 693
694 (defsubst gnus-score-get (symbol &optional alist) 694 (defsubst gnus-score-get (symbol &optional alist)
695 ;; Get SYMBOL's definition in ALIST. 695 ;; Get SYMBOL's definition in ALIST.
696 (cdr (assoc symbol 696 (cdr (assoc symbol
697 (or alist 697 (or alist
698 gnus-score-alist 698 gnus-score-alist
699 (gnus-newsgroup-score-alist))))) 699 (gnus-newsgroup-score-alist)))))
700 700
701 (defun gnus-summary-score-entry (header match type score date 701 (defun gnus-summary-score-entry (header match type score date
702 &optional prompt silent) 702 &optional prompt silent)
732 (setq match (gnus-simplify-subject-fuzzy match)))) 732 (setq match (gnus-simplify-subject-fuzzy match))))
733 (let ((score (gnus-score-default score)) 733 (let ((score (gnus-score-default score))
734 (header (format "%s" (downcase header))) 734 (header (format "%s" (downcase header)))
735 new) 735 new)
736 (when prompt 736 (when prompt
737 (setq match (read-string 737 (setq match (read-string
738 (format "Match %s on %s, %s: " 738 (format "Match %s on %s, %s: "
739 (cond ((eq date 'now) 739 (cond ((eq date 'now)
740 "now") 740 "now")
741 ((stringp date) 741 ((stringp date)
742 "temp") 742 "temp")
743 (t "permanent")) 743 (t "permanent"))
748 match)))) 748 match))))
749 749
750 ;; Get rid of string props. 750 ;; Get rid of string props.
751 (setq match (format "%s" match)) 751 (setq match (format "%s" match))
752 752
753 ;; If this is an integer comparison, we transform from string to int. 753 ;; If this is an integer comparison, we transform from string to int.
754 (when (eq (nth 2 (assoc header gnus-header-index)) 'gnus-score-integer) 754 (when (eq (nth 2 (assoc header gnus-header-index)) 'gnus-score-integer)
755 (setq match (string-to-int match))) 755 (setq match (string-to-int match)))
756 756
757 (unless (eq date 'now) 757 (unless (eq date 'now)
758 ;; Add the score entry to the score file. 758 ;; Add the score entry to the score file.
759 (when (= score gnus-score-interactive-default-score) 759 (when (= score gnus-score-interactive-default-score)
760 (setq score nil)) 760 (setq score nil))
761 (let ((old (gnus-score-get header)) 761 (let ((old (gnus-score-get header))
762 elem) 762 elem)
763 (setq new 763 (setq new
764 (cond 764 (cond
765 (type 765 (type
766 (list match score 766 (list match score
767 (and date (if (numberp date) date 767 (and date (if (numberp date) date
768 (gnus-day-number date))) 768 (gnus-day-number date)))
769 type)) 769 type))
819 (gnus-simplify-subject-fuzzy match)) 819 (gnus-simplify-subject-fuzzy match))
820 ((eq type 'r) 820 ((eq type 'r)
821 match) 821 match)
822 ((eq type 'e) 822 ((eq type 'e)
823 (concat "\\`" (regexp-quote match) "\\'")) 823 (concat "\\`" (regexp-quote match) "\\'"))
824 (t 824 (t
825 (regexp-quote match))))) 825 (regexp-quote match)))))
826 (while (not (eobp)) 826 (while (not (eobp))
827 (let ((content (gnus-summary-header header 'noerr)) 827 (let ((content (gnus-summary-header header 'noerr))
828 (case-fold-search t)) 828 (case-fold-search t))
829 (and content 829 (and content
844 group) 844 group)
845 (unless xref 845 (unless xref
846 (error "This article is not crossposted")) 846 (error "This article is not crossposted"))
847 (while (string-match " \\([^ \t]+\\):" xref start) 847 (while (string-match " \\([^ \t]+\\):" xref start)
848 (setq start (match-end 0)) 848 (setq start (match-end 0))
849 (when (not (string= 849 (when (not (string=
850 (setq group 850 (setq group
851 (substring xref (match-beginning 1) (match-end 1))) 851 (substring xref (match-beginning 1) (match-end 1)))
852 gnus-newsgroup-name)) 852 gnus-newsgroup-name))
853 (gnus-summary-score-entry 853 (gnus-summary-score-entry
854 "xref" (concat " " group ":") nil score date t))))) 854 "xref" (concat " " group ":") nil score date t)))))
855 855
861 ;; All score code written by Per Abrahamsen <abraham@iesd.auc.dk>. 861 ;; All score code written by Per Abrahamsen <abraham@iesd.auc.dk>.
862 862
863 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>. 863 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
864 (defun gnus-score-set-mark-below (score) 864 (defun gnus-score-set-mark-below (score)
865 "Automatically mark articles with score below SCORE as read." 865 "Automatically mark articles with score below SCORE as read."
866 (interactive 866 (interactive
867 (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg)) 867 (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
868 (string-to-int (read-string "Mark below: "))))) 868 (string-to-int (read-string "Mark below: ")))))
869 (setq score (or score gnus-summary-default-score 0)) 869 (setq score (or score gnus-summary-default-score 0))
870 (gnus-score-set 'mark (list score)) 870 (gnus-score-set 'mark (list score))
871 (gnus-score-set 'touched '(t)) 871 (gnus-score-set 'touched '(t))
895 (goto-char (pop hidden)) 895 (goto-char (pop hidden))
896 (gnus-summary-hide-thread))))) 896 (gnus-summary-hide-thread)))))
897 897
898 (defun gnus-score-set-expunge-below (score) 898 (defun gnus-score-set-expunge-below (score)
899 "Automatically expunge articles with score below SCORE." 899 "Automatically expunge articles with score below SCORE."
900 (interactive 900 (interactive
901 (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg)) 901 (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
902 (string-to-int (read-string "Set expunge below: "))))) 902 (string-to-int (read-string "Set expunge below: ")))))
903 (setq score (or score gnus-summary-default-score 0)) 903 (setq score (or score gnus-summary-default-score 0))
904 (gnus-score-set 'expunge (list score)) 904 (gnus-score-set 'expunge (list score))
905 (gnus-score-set 'touched '(t))) 905 (gnus-score-set 'touched '(t)))
934 "references" id 's 934 "references" id 's
935 score (current-time-string)))))))) 935 score (current-time-string))))))))
936 936
937 (defun gnus-score-set (symbol value &optional alist) 937 (defun gnus-score-set (symbol value &optional alist)
938 ;; Set SYMBOL to VALUE in ALIST. 938 ;; Set SYMBOL to VALUE in ALIST.
939 (let* ((alist 939 (let* ((alist
940 (or alist 940 (or alist
941 gnus-score-alist 941 gnus-score-alist
942 (gnus-newsgroup-score-alist))) 942 (gnus-newsgroup-score-alist)))
943 (entry (assoc symbol alist))) 943 (entry (assoc symbol alist)))
944 (cond ((gnus-score-get 'read-only alist) 944 (cond ((gnus-score-get 'read-only alist)
945 ;; This is a read-only score file, so we do nothing. 945 ;; This is a read-only score file, so we do nothing.
984 (gnus-set-global-variables) 984 (gnus-set-global-variables)
985 (gnus-message 1 "%s" (gnus-summary-article-score))) 985 (gnus-message 1 "%s" (gnus-summary-article-score)))
986 986
987 (defun gnus-score-change-score-file (file) 987 (defun gnus-score-change-score-file (file)
988 "Change current score alist." 988 "Change current score alist."
989 (interactive 989 (interactive
990 (list (read-file-name "Change to score file: " gnus-kill-files-directory))) 990 (list (read-file-name "Change to score file: " gnus-kill-files-directory)))
991 (gnus-score-load-file file) 991 (gnus-score-load-file file)
992 (gnus-set-mode-line 'summary)) 992 (gnus-set-mode-line 'summary))
993 993
994 (defvar gnus-score-edit-exit-function) 994 (defvar gnus-score-edit-exit-function)
1004 (gnus-configure-windows 'edit-score) 1004 (gnus-configure-windows 'edit-score)
1005 (gnus-score-mode) 1005 (gnus-score-mode)
1006 (setq gnus-score-edit-exit-function 'gnus-score-edit-done) 1006 (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
1007 (make-local-variable 'gnus-prev-winconf) 1007 (make-local-variable 'gnus-prev-winconf)
1008 (setq gnus-prev-winconf winconf)) 1008 (setq gnus-prev-winconf winconf))
1009 (gnus-message 1009 (gnus-message
1010 4 (substitute-command-keys 1010 4 (substitute-command-keys
1011 "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits"))) 1011 "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
1012 1012
1013 (defun gnus-score-edit-file (file) 1013 (defun gnus-score-edit-file (file)
1014 "Edit a score file." 1014 "Edit a score file."
1015 (interactive 1015 (interactive
1016 (list (read-file-name "Edit score file: " gnus-kill-files-directory))) 1016 (list (read-file-name "Edit score file: " gnus-kill-files-directory)))
1017 (gnus-make-directory (file-name-directory file)) 1017 (gnus-make-directory (file-name-directory file))
1018 (when (buffer-name gnus-summary-buffer) 1018 (when (buffer-name gnus-summary-buffer)
1019 (gnus-score-save)) 1019 (gnus-score-save))
1020 (let ((winconf (current-window-configuration))) 1020 (let ((winconf (current-window-configuration)))
1022 (gnus-configure-windows 'edit-score) 1022 (gnus-configure-windows 'edit-score)
1023 (gnus-score-mode) 1023 (gnus-score-mode)
1024 (setq gnus-score-edit-exit-function 'gnus-score-edit-done) 1024 (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
1025 (make-local-variable 'gnus-prev-winconf) 1025 (make-local-variable 'gnus-prev-winconf)
1026 (setq gnus-prev-winconf winconf)) 1026 (setq gnus-prev-winconf winconf))
1027 (gnus-message 1027 (gnus-message
1028 4 (substitute-command-keys 1028 4 (substitute-command-keys
1029 "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits"))) 1029 "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
1030 1030
1031 (defun gnus-score-load-file (file) 1031 (defun gnus-score-load-file (file)
1032 ;; Load score file FILE. Returns a list a retrieved score-alists. 1032 ;; Load score file FILE. Returns a list a retrieved score-alists.
1033 (let* ((file (expand-file-name 1033 (let* ((file (expand-file-name
1034 (or (and (string-match 1034 (or (and (string-match
1035 (concat "^" (expand-file-name 1035 (concat "^" (expand-file-name
1036 gnus-kill-files-directory)) 1036 gnus-kill-files-directory))
1037 (expand-file-name file)) 1037 (expand-file-name file))
1038 file) 1038 file)
1046 (setq alist (cdr cached)) 1046 (setq alist (cdr cached))
1047 ;; We load the score file. 1047 ;; We load the score file.
1048 (setq gnus-score-alist nil) 1048 (setq gnus-score-alist nil)
1049 (setq alist (gnus-score-load-score-alist file)) 1049 (setq alist (gnus-score-load-score-alist file))
1050 ;; We add '(touched) to the alist to signify that it hasn't been 1050 ;; We add '(touched) to the alist to signify that it hasn't been
1051 ;; touched (yet). 1051 ;; touched (yet).
1052 (unless (assq 'touched alist) 1052 (unless (assq 'touched alist)
1053 (push (list 'touched nil) alist)) 1053 (push (list 'touched nil) alist))
1054 ;; If it is a global score file, we make it read-only. 1054 ;; If it is a global score file, we make it read-only.
1055 (and global 1055 (and global
1056 (not (assq 'read-only alist)) 1056 (not (assq 'read-only alist))
1082 (local (gnus-score-get 'local alist)) 1082 (local (gnus-score-get 'local alist))
1083 (decay (car (gnus-score-get 'decay alist))) 1083 (decay (car (gnus-score-get 'decay alist)))
1084 (eval (car (gnus-score-get 'eval alist)))) 1084 (eval (car (gnus-score-get 'eval alist))))
1085 ;; Perform possible decays. 1085 ;; Perform possible decays.
1086 (when (and gnus-decay-scores 1086 (when (and gnus-decay-scores
1087 (gnus-decay-scores 1087 (gnus-decay-scores
1088 alist (or decay (gnus-time-to-day (current-time))))) 1088 alist (or decay (gnus-time-to-day (current-time)))))
1089 (gnus-score-set 'touched '(t) alist) 1089 (gnus-score-set 'touched '(t) alist)
1090 (gnus-score-set 'decay (list (gnus-time-to-day (current-time))))) 1090 (gnus-score-set 'decay (list (gnus-time-to-day (current-time)))))
1091 ;; We do not respect eval and files atoms from global score 1091 ;; We do not respect eval and files atoms from global score
1092 ;; files. 1092 ;; files.
1093 (and files (not global) 1093 (and files (not global)
1094 (setq lists (apply 'append lists 1094 (setq lists (apply 'append lists
1095 (mapcar (lambda (file) 1095 (mapcar (lambda (file)
1096 (gnus-score-load-file file)) 1096 (gnus-score-load-file file))
1097 (if adapt-file (cons adapt-file files) 1097 (if adapt-file (cons adapt-file files)
1098 files))))) 1098 files)))))
1099 (and eval (not global) (eval eval)) 1099 (and eval (not global) (eval eval))
1100 ;; We then expand any exclude-file directives. 1100 ;; We then expand any exclude-file directives.
1101 (setq gnus-scores-exclude-files 1101 (setq gnus-scores-exclude-files
1102 (nconc 1102 (nconc
1103 (mapcar 1103 (mapcar
1104 (lambda (sfile) 1104 (lambda (sfile)
1105 (expand-file-name sfile (file-name-directory file))) 1105 (expand-file-name sfile (file-name-directory file)))
1106 exclude-files) 1106 exclude-files)
1107 gnus-scores-exclude-files)) 1107 gnus-scores-exclude-files))
1108 (if (not local) 1108 (if (not local)
1128 (setq gnus-newsgroup-adaptive t) 1128 (setq gnus-newsgroup-adaptive t)
1129 adapt) 1129 adapt)
1130 (t 1130 (t
1131 ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring) 1131 ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring)
1132 gnus-default-adaptive-score-alist))) 1132 gnus-default-adaptive-score-alist)))
1133 (setq gnus-thread-expunge-below 1133 (setq gnus-thread-expunge-below
1134 (or thread-mark-and-expunge gnus-thread-expunge-below)) 1134 (or thread-mark-and-expunge gnus-thread-expunge-below))
1135 (setq gnus-summary-mark-below 1135 (setq gnus-summary-mark-below
1136 (or mark mark-and-expunge gnus-summary-mark-below)) 1136 (or mark mark-and-expunge gnus-summary-mark-below))
1137 (setq gnus-summary-expunge-below 1137 (setq gnus-summary-expunge-below
1138 (or expunge mark-and-expunge gnus-summary-expunge-below)) 1138 (or expunge mark-and-expunge gnus-summary-expunge-below))
1139 (setq gnus-newsgroup-adaptive-score-file 1139 (setq gnus-newsgroup-adaptive-score-file
1140 (or adapt-file gnus-newsgroup-adaptive-score-file))) 1140 (or adapt-file gnus-newsgroup-adaptive-score-file)))
1141 (setq gnus-current-score-file file) 1141 (setq gnus-current-score-file file)
1142 (setq gnus-score-alist alist) 1142 (setq gnus-score-alist alist)
1143 lists)) 1143 lists))
1144 1144
1152 (unless gnus-score-alist 1152 (unless gnus-score-alist
1153 (setq gnus-score-alist (copy-alist '((touched nil))))) 1153 (setq gnus-score-alist (copy-alist '((touched nil)))))
1154 (push (cons file gnus-score-alist) gnus-score-cache)))) 1154 (push (cons file gnus-score-alist) gnus-score-cache))))
1155 1155
1156 (defun gnus-score-remove-from-cache (file) 1156 (defun gnus-score-remove-from-cache (file)
1157 (setq gnus-score-cache 1157 (setq gnus-score-cache
1158 (delq (assoc file gnus-score-cache) gnus-score-cache))) 1158 (delq (assoc file gnus-score-cache) gnus-score-cache)))
1159 1159
1160 (defun gnus-score-load-score-alist (file) 1160 (defun gnus-score-load-score-alist (file)
1161 "Read score FILE." 1161 "Read score FILE."
1162 (let (alist) 1162 (let (alist)
1171 ;; Only do the loading if the score file isn't empty. 1171 ;; Only do the loading if the score file isn't empty.
1172 (when (save-excursion (re-search-forward "[()0-9a-zA-Z]" nil t)) 1172 (when (save-excursion (re-search-forward "[()0-9a-zA-Z]" nil t))
1173 (setq alist 1173 (setq alist
1174 (condition-case () 1174 (condition-case ()
1175 (read (current-buffer)) 1175 (read (current-buffer))
1176 (error 1176 (error
1177 (gnus-error 3.2 "Problem with score file %s" file)))))) 1177 (gnus-error 3.2 "Problem with score file %s" file))))))
1178 (if (eq (car alist) 'setq) 1178 (if (eq (car alist) 'setq)
1179 ;; This is an old-style score file. 1179 ;; This is an old-style score file.
1180 (setq gnus-score-alist (gnus-score-transform-old-to-new alist)) 1180 (setq gnus-score-alist (gnus-score-transform-old-to-new alist))
1181 (setq gnus-score-alist alist)) 1181 (setq gnus-score-alist alist))
1183 (setq gnus-score-alist 1183 (setq gnus-score-alist
1184 (gnus-score-check-syntax gnus-score-alist file))))) 1184 (gnus-score-check-syntax gnus-score-alist file)))))
1185 1185
1186 (defun gnus-score-check-syntax (alist file) 1186 (defun gnus-score-check-syntax (alist file)
1187 "Check the syntax of the score ALIST." 1187 "Check the syntax of the score ALIST."
1188 (cond 1188 (cond
1189 ((null alist) 1189 ((null alist)
1190 nil) 1190 nil)
1191 ((not (consp alist)) 1191 ((not (consp alist))
1192 (gnus-message 1 "Score file is not a list: %s" file) 1192 (gnus-message 1 "Score file is not a list: %s" file)
1193 (ding) 1193 (ding)
1200 err 1200 err
1201 (cond 1201 (cond
1202 ((not (listp (car a))) 1202 ((not (listp (car a)))
1203 (format "Illegal score element %s in %s" (car a) file)) 1203 (format "Illegal score element %s in %s" (car a) file))
1204 ((stringp (caar a)) 1204 ((stringp (caar a))
1205 (cond 1205 (cond
1206 ((not (listp (setq sr (cdar a)))) 1206 ((not (listp (setq sr (cdar a))))
1207 (format "Illegal header match %s in %s" (nth 1 (car a)) file)) 1207 (format "Illegal header match %s in %s" (nth 1 (car a)) file))
1208 (t 1208 (t
1209 (setq type (caar a)) 1209 (setq type (caar a))
1210 (while (and sr (not err)) 1210 (while (and sr (not err))
1211 (setq s (pop sr)) 1211 (setq s (pop sr))
1212 (setq 1212 (setq
1213 err 1213 err
1214 (cond 1214 (cond
1215 ((if (member (downcase type) '("lines" "chars")) 1215 ((if (member (downcase type) '("lines" "chars"))
1216 (not (numberp (car s))) 1216 (not (numberp (car s)))
1217 (not (stringp (car s)))) 1217 (not (stringp (car s))))
1253 (list (car entry) (cdr entry)) 1253 (list (car entry) (cdr entry))
1254 entry) 1254 entry)
1255 out)) 1255 out))
1256 (setq alist (cdr alist))) 1256 (setq alist (cdr alist)))
1257 (cons (list 'touched t) (nreverse out)))) 1257 (cons (list 'touched t) (nreverse out))))
1258 1258
1259 (defun gnus-score-save () 1259 (defun gnus-score-save ()
1260 ;; Save all score information. 1260 ;; Save all score information.
1261 (let ((cache gnus-score-cache) 1261 (let ((cache gnus-score-cache)
1262 entry score file) 1262 entry score file)
1263 (save-excursion 1263 (save-excursion
1274 (not (file-writable-p file)))) 1274 (not (file-writable-p file))))
1275 () 1275 ()
1276 (setq score (setcdr entry (delq (assq 'touched score) score))) 1276 (setq score (setcdr entry (delq (assq 'touched score) score)))
1277 (erase-buffer) 1277 (erase-buffer)
1278 (let (emacs-lisp-mode-hook) 1278 (let (emacs-lisp-mode-hook)
1279 (if (string-match 1279 (if (string-match
1280 (concat (regexp-quote gnus-adaptive-file-suffix) 1280 (concat (regexp-quote gnus-adaptive-file-suffix)
1281 "$") 1281 "$")
1282 file) 1282 file)
1283 ;; This is an adaptive score file, so we do not run 1283 ;; This is an adaptive score file, so we do not run
1284 ;; it through `pp'. These files can get huge, and 1284 ;; it through `pp'. These files can get huge, and
1285 ;; are not meant to be edited by human hands. 1285 ;; are not meant to be edited by human hands.
1286 (gnus-prin1 score) 1286 (gnus-prin1 score)
1287 ;; This is a normal score file, so we print it very 1287 ;; This is a normal score file, so we print it very
1288 ;; prettily. 1288 ;; prettily.
1289 (pp score (current-buffer)))) 1289 (pp score (current-buffer))))
1290 (gnus-make-directory (file-name-directory file)) 1290 (gnus-make-directory (file-name-directory file))
1291 ;; If the score file is empty, we delete it. 1291 ;; If the score file is empty, we delete it.
1292 (if (zerop (buffer-size)) 1292 (if (zerop (buffer-size))
1293 (delete-file file) 1293 (delete-file file)
1294 ;; There are scores, so we write the file. 1294 ;; There are scores, so we write the file.
1295 (when (file-writable-p file) 1295 (when (file-writable-p file)
1296 (gnus-write-buffer file) 1296 (gnus-write-buffer file)
1297 (when gnus-score-after-write-file-function 1297 (when gnus-score-after-write-file-function
1298 (funcall gnus-score-after-write-file-function file))))) 1298 (funcall gnus-score-after-write-file-function file)))))
1299 (and gnus-score-uncacheable-files 1299 (and gnus-score-uncacheable-files
1363 (buffer-disable-undo (current-buffer)) 1363 (buffer-disable-undo (current-buffer))
1364 1364
1365 ;; Set the global variant of this variable. 1365 ;; Set the global variant of this variable.
1366 (setq gnus-current-score-file current-score-file) 1366 (setq gnus-current-score-file current-score-file)
1367 ;; score orphans 1367 ;; score orphans
1368 (when gnus-orphan-score 1368 (when gnus-orphan-score
1369 (setq gnus-score-index 1369 (setq gnus-score-index
1370 (nth 1 (assoc "references" gnus-header-index))) 1370 (nth 1 (assoc "references" gnus-header-index)))
1371 (gnus-score-orphans gnus-orphan-score)) 1371 (gnus-score-orphans gnus-orphan-score))
1372 ;; Run each header through the score process. 1372 ;; Run each header through the score process.
1373 (while entries 1373 (while entries
1374 (setq entry (pop entries) 1374 (setq entry (pop entries)
1399 (while (setq score (pop scores)) 1399 (while (setq score (pop scores))
1400 (while score 1400 (while score
1401 (when (listp (caar score)) 1401 (when (listp (caar score))
1402 (gnus-score-advanced (car score) trace)) 1402 (gnus-score-advanced (car score) trace))
1403 (pop score)))) 1403 (pop score))))
1404 1404
1405 (gnus-message 5 "Scoring...done")))))) 1405 (gnus-message 5 "Scoring...done"))))))
1406 1406
1407 1407
1408 (defun gnus-get-new-thread-ids (articles) 1408 (defun gnus-get-new-thread-ids (articles)
1409 (let ((index (nth 1 (assoc "message-id" gnus-header-index))) 1409 (let ((index (nth 1 (assoc "message-id" gnus-header-index)))
1420 1420
1421 ;; Orphan functions written by plm@atcmp.nl (Peter Mutsaers). 1421 ;; Orphan functions written by plm@atcmp.nl (Peter Mutsaers).
1422 (defun gnus-score-orphans (score) 1422 (defun gnus-score-orphans (score)
1423 (let ((new-thread-ids (gnus-get-new-thread-ids gnus-scores-articles)) 1423 (let ((new-thread-ids (gnus-get-new-thread-ids gnus-scores-articles))
1424 alike articles art arts this last this-id) 1424 alike articles art arts this last this-id)
1425 1425
1426 (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<) 1426 (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
1427 articles gnus-scores-articles) 1427 articles gnus-scores-articles)
1428 1428
1429 ;;more or less the same as in gnus-score-string 1429 ;;more or less the same as in gnus-score-string
1430 (erase-buffer) 1430 (erase-buffer)
1469 (while arts 1469 (while arts
1470 (setq art (car arts) 1470 (setq art (car arts)
1471 arts (cdr arts)) 1471 arts (cdr arts))
1472 (setcdr art (+ score (cdr art)))) 1472 (setcdr art (+ score (cdr art))))
1473 (forward-line)))))) 1473 (forward-line))))))
1474 1474
1475 1475
1476 (defun gnus-score-integer (scores header now expire &optional trace) 1476 (defun gnus-score-integer (scores header now expire &optional trace)
1477 (let ((gnus-score-index (nth 1 (assoc header gnus-header-index))) 1477 (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
1478 entries alist) 1478 entries alist)
1479 1479
1499 ;; `gnus-score-string' does to minimize searches and stuff, 1499 ;; `gnus-score-string' does to minimize searches and stuff,
1500 ;; I will assume that people generally will put so few 1500 ;; I will assume that people generally will put so few
1501 ;; matches on numbers that any cleverness will take more 1501 ;; matches on numbers that any cleverness will take more
1502 ;; time than one would gain. 1502 ;; time than one would gain.
1503 (while articles 1503 (while articles
1504 (when (funcall match-func 1504 (when (funcall match-func
1505 (or (aref (caar articles) gnus-score-index) 0) 1505 (or (aref (caar articles) gnus-score-index) 0)
1506 match) 1506 match)
1507 (when trace 1507 (when trace
1508 (push (cons (car-safe (rassq alist gnus-score-cache)) kill) 1508 (push (cons (car-safe (rassq alist gnus-score-cache)) kill)
1509 gnus-score-trace)) 1509 gnus-score-trace))
1510 (setq found t) 1510 (setq found t)
1511 (setcdr (car articles) (+ score (cdar articles)))) 1511 (setcdr (car articles) (+ score (cdar articles))))
1512 (setq articles (cdr articles))) 1512 (setq articles (cdr articles)))
1600 entries alist ofunc article last) 1600 entries alist ofunc article last)
1601 (when articles 1601 (when articles
1602 (setq last (mail-header-number (caar (last articles)))) 1602 (setq last (mail-header-number (caar (last articles))))
1603 ;; Not all backends support partial fetching. In that case, 1603 ;; Not all backends support partial fetching. In that case,
1604 ;; we just fetch the entire article. 1604 ;; we just fetch the entire article.
1605 (unless (gnus-check-backend-function 1605 (unless (gnus-check-backend-function
1606 (and (string-match "^gnus-" (symbol-name request-func)) 1606 (and (string-match "^gnus-" (symbol-name request-func))
1607 (intern (substring (symbol-name request-func) 1607 (intern (substring (symbol-name request-func)
1608 (match-end 0)))) 1608 (match-end 0))))
1609 gnus-newsgroup-name) 1609 gnus-newsgroup-name)
1610 (setq ofunc request-func) 1610 (setq ofunc request-func)
1638 (type (or (nth 3 kill) 's)) 1638 (type (or (nth 3 kill) 's))
1639 (score (or (nth 1 kill) 1639 (score (or (nth 1 kill)
1640 gnus-score-interactive-default-score)) 1640 gnus-score-interactive-default-score))
1641 (date (nth 2 kill)) 1641 (date (nth 2 kill))
1642 (found nil) 1642 (found nil)
1643 (case-fold-search 1643 (case-fold-search
1644 (not (or (eq type 'R) (eq type 'S) 1644 (not (or (eq type 'R) (eq type 'S)
1645 (eq type 'Regexp) (eq type 'String)))) 1645 (eq type 'Regexp) (eq type 'String))))
1646 (search-func 1646 (search-func
1647 (cond ((or (eq type 'r) (eq type 'R) 1647 (cond ((or (eq type 'r) (eq type 'R)
1648 (eq type 'regexp) (eq type 'Regexp)) 1648 (eq type 'regexp) (eq type 'Regexp))
1649 're-search-forward) 1649 're-search-forward)
1650 ((or (eq type 's) (eq type 'S) 1650 ((or (eq type 's) (eq type 'S)
1651 (eq type 'string) (eq type 'String)) 1651 (eq type 'string) (eq type 'String))
1663 gnus-score-trace))) 1663 gnus-score-trace)))
1664 ;; Update expire date 1664 ;; Update expire date
1665 (unless trace 1665 (unless trace
1666 (cond 1666 (cond
1667 ((null date)) ;Permanent entry. 1667 ((null date)) ;Permanent entry.
1668 ((and found gnus-update-score-entry-dates) 1668 ((and found gnus-update-score-entry-dates)
1669 ;; Match, update date. 1669 ;; Match, update date.
1670 (gnus-score-set 'touched '(t) alist) 1670 (gnus-score-set 'touched '(t) alist)
1671 (setcar (nthcdr 2 kill) now)) 1671 (setcar (nthcdr 2 kill) now))
1672 ((and expire (< date expire)) ;Old entry, remove. 1672 ((and expire (< date expire)) ;Old entry, remove.
1673 (gnus-score-set 'touched '(t) alist) 1673 (gnus-score-set 'touched '(t) alist)
1693 ;; this function makes will be put into this file. 1693 ;; this function makes will be put into this file.
1694 (save-excursion 1694 (save-excursion
1695 (set-buffer gnus-summary-buffer) 1695 (set-buffer gnus-summary-buffer)
1696 (gnus-score-load-file 1696 (gnus-score-load-file
1697 (or gnus-newsgroup-adaptive-score-file 1697 (or gnus-newsgroup-adaptive-score-file
1698 (gnus-score-file-name 1698 (gnus-score-file-name
1699 gnus-newsgroup-name gnus-adaptive-file-suffix)))) 1699 gnus-newsgroup-name gnus-adaptive-file-suffix))))
1700 1700
1701 (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<) 1701 (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
1702 articles gnus-scores-articles) 1702 articles gnus-scores-articles)
1703 1703
1714 (setq alike (list art) 1714 (setq alike (list art)
1715 last this))) 1715 last this)))
1716 (when last ; Bwadr, duplicate code. 1716 (when last ; Bwadr, duplicate code.
1717 (insert last ?\n) 1717 (insert last ?\n)
1718 (put-text-property (1- (point)) (point) 'articles alike)) 1718 (put-text-property (1- (point)) (point) 'articles alike))
1719 1719
1720 ;; Find matches. 1720 ;; Find matches.
1721 (while scores 1721 (while scores
1722 (setq alist (car scores) 1722 (setq alist (car scores)
1723 scores (cdr scores) 1723 scores (cdr scores)
1724 entries (assoc header alist)) 1724 entries (assoc header alist))
1729 (type (or (nth 3 kill) 's)) 1729 (type (or (nth 3 kill) 's))
1730 (score (or (nth 1 kill) gnus-score-interactive-default-score)) 1730 (score (or (nth 1 kill) gnus-score-interactive-default-score))
1731 (date (nth 2 kill)) 1731 (date (nth 2 kill))
1732 (found nil) 1732 (found nil)
1733 (mt (aref (symbol-name type) 0)) 1733 (mt (aref (symbol-name type) 0))
1734 (case-fold-search 1734 (case-fold-search
1735 (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F)))) 1735 (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F))))
1736 (dmt (downcase mt)) 1736 (dmt (downcase mt))
1737 (search-func 1737 (search-func
1738 (cond ((= dmt ?r) 're-search-forward) 1738 (cond ((= dmt ?r) 're-search-forward)
1739 ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward) 1739 ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
1740 (t (error "Illegal match type: %s" type)))) 1740 (t (error "Illegal match type: %s" type))))
1741 arts art) 1741 arts art)
1742 (goto-char (point-min)) 1742 (goto-char (point-min))
1745 (and (= (progn (beginning-of-line) (point)) 1745 (and (= (progn (beginning-of-line) (point))
1746 (match-beginning 0)) 1746 (match-beginning 0))
1747 (= (progn (end-of-line) (point)) 1747 (= (progn (end-of-line) (point))
1748 (match-end 0)) 1748 (match-end 0))
1749 (progn 1749 (progn
1750 (setq found (setq arts (get-text-property 1750 (setq found (setq arts (get-text-property
1751 (point) 'articles))) 1751 (point) 'articles)))
1752 ;; Found a match, update scores. 1752 ;; Found a match, update scores.
1753 (while arts 1753 (while arts
1754 (setq art (car arts) 1754 (setq art (car arts)
1755 arts (cdr arts)) 1755 arts (cdr arts))
1756 (gnus-score-add-followups 1756 (gnus-score-add-followups
1757 (car art) score all-scores thread)))) 1757 (car art) score all-scores thread))))
1758 (end-of-line)) 1758 (end-of-line))
1759 (while (funcall search-func match nil t) 1759 (while (funcall search-func match nil t)
1760 (end-of-line) 1760 (end-of-line)
1761 (setq found (setq arts (get-text-property (point) 'articles))) 1761 (setq found (setq arts (get-text-property (point) 'articles)))
1793 (or (null (nth 3 (cadr entry))) 1793 (or (null (nth 3 (cadr entry)))
1794 (eq 's (nth 3 (cadr entry)))) 1794 (eq 's (nth 3 (cadr entry))))
1795 (assoc id entry) 1795 (assoc id entry)
1796 (setq dont t))) 1796 (setq dont t)))
1797 (unless dont 1797 (unless dont
1798 (gnus-summary-score-entry 1798 (gnus-summary-score-entry
1799 (if thread "thread" "references") 1799 (if thread "thread" "references")
1800 id 's score (current-time-string) nil t))))) 1800 id 's score (current-time-string) nil t)))))
1801 1801
1802 (defun gnus-score-string (score-list header now expire &optional trace) 1802 (defun gnus-score-string (score-list header now expire &optional trace)
1803 ;; Score ARTICLES according to HEADER in SCORE-LIST. 1803 ;; Score ARTICLES according to HEADER in SCORE-LIST.
1804 ;; Update matching entries to NOW and remove unmatched entries older 1804 ;; Update matching entries to NOW and remove unmatched entries older
1805 ;; than EXPIRE. 1805 ;; than EXPIRE.
1806 1806
1807 ;; Insert the unique article headers in the buffer. 1807 ;; Insert the unique article headers in the buffer.
1808 (let ((gnus-score-index (nth 1 (assoc header gnus-header-index))) 1808 (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
1809 ;; gnus-score-index is used as a free variable. 1809 ;; gnus-score-index is used as a free variable.
1810 alike last this art entries alist articles 1810 alike last this art entries alist articles
1811 fuzzies arts words kill) 1811 fuzzies arts words kill)
1812 1812
1813 ;; Sorting the articles costs os O(N*log N) but will allow us to 1813 ;; Sorting the articles costs os O(N*log N) but will allow us to
1814 ;; only match with each unique header. Thus the actual matching 1814 ;; only match with each unique header. Thus the actual matching
1815 ;; will be O(M*U) where M is the number of strings to match with, 1815 ;; will be O(M*U) where M is the number of strings to match with,
1853 (date (nth 2 kill)) 1853 (date (nth 2 kill))
1854 (found nil) 1854 (found nil)
1855 (mt (aref (symbol-name type) 0)) 1855 (mt (aref (symbol-name type) 0))
1856 (case-fold-search (not (memq mt '(?R ?S ?E ?F)))) 1856 (case-fold-search (not (memq mt '(?R ?S ?E ?F))))
1857 (dmt (downcase mt)) 1857 (dmt (downcase mt))
1858 (search-func 1858 (search-func
1859 (cond ((= dmt ?r) 're-search-forward) 1859 (cond ((= dmt ?r) 're-search-forward)
1860 ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward) 1860 ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
1861 ((= dmt ?w) nil) 1861 ((= dmt ?w) nil)
1862 (t (error "Illegal match type: %s" type))))) 1862 (t (error "Illegal match type: %s" type)))))
1863 (cond 1863 (cond
1876 ;; Is it really exact? 1876 ;; Is it really exact?
1877 (and (eolp) 1877 (and (eolp)
1878 (= (gnus-point-at-bol) (match-beginning 0)) 1878 (= (gnus-point-at-bol) (match-beginning 0))
1879 ;; Yup. 1879 ;; Yup.
1880 (progn 1880 (progn
1881 (setq found (setq arts (get-text-property 1881 (setq found (setq arts (get-text-property
1882 (point) 'articles))) 1882 (point) 'articles)))
1883 ;; Found a match, update scores. 1883 ;; Found a match, update scores.
1884 (if trace 1884 (if trace
1885 (while (setq art (pop arts)) 1885 (while (setq art (pop arts))
1886 (setcdr art (+ score (cdr art))) 1886 (setcdr art (+ score (cdr art)))
1887 (push 1887 (push
1888 (cons 1888 (cons
1889 (car-safe (rassq alist gnus-score-cache)) 1889 (car-safe (rassq alist gnus-score-cache))
1890 kill) 1890 kill)
1891 gnus-score-trace)) 1891 gnus-score-trace))
1892 (while (setq art (pop arts)) 1892 (while (setq art (pop arts))
1893 (setcdr art (+ score (cdr art))))))) 1893 (setcdr art (+ score (cdr art)))))))
1912 (setcdr art (+ score (cdr art))))) 1912 (setcdr art (+ score (cdr art)))))
1913 (forward-line 1)))) 1913 (forward-line 1))))
1914 ;; Update expiry date 1914 ;; Update expiry date
1915 (if trace 1915 (if trace
1916 (setq entries (cdr entries)) 1916 (setq entries (cdr entries))
1917 (cond 1917 (cond
1918 ;; Permanent entry. 1918 ;; Permanent entry.
1919 ((null date) 1919 ((null date)
1920 (setq entries (cdr entries))) 1920 (setq entries (cdr entries)))
1921 ;; We have a match, so we update the date. 1921 ;; We have a match, so we update the date.
1922 ((and found gnus-update-score-entry-dates) 1922 ((and found gnus-update-score-entry-dates)
1951 (setq found (setq arts (get-text-property (point) 'articles))) 1951 (setq found (setq arts (get-text-property (point) 'articles)))
1952 (if trace 1952 (if trace
1953 (while (setq art (pop arts)) 1953 (while (setq art (pop arts))
1954 (setcdr art (+ score (cdr art))) 1954 (setcdr art (+ score (cdr art)))
1955 (push (cons 1955 (push (cons
1956 (car-safe (rassq (cdar fuzzies) gnus-score-cache)) 1956 (car-safe (rassq (cdar fuzzies) gnus-score-cache))
1957 kill) 1957 kill)
1958 gnus-score-trace)) 1958 gnus-score-trace))
1959 ;; Found a match, update scores. 1959 ;; Found a match, update scores.
1960 (while (setq art (pop arts)) 1960 (while (setq art (pop arts))
1961 (setcdr art (+ score (cdr art)))))) 1961 (setcdr art (+ score (cdr art))))))
2022 (unwind-protect 2022 (unwind-protect
2023 (progn 2023 (progn
2024 (set-syntax-table gnus-adaptive-word-syntax-table) 2024 (set-syntax-table gnus-adaptive-word-syntax-table)
2025 (while (re-search-forward "\\b\\w+\\b" nil t) 2025 (while (re-search-forward "\\b\\w+\\b" nil t)
2026 (setq val 2026 (setq val
2027 (gnus-gethash 2027 (gnus-gethash
2028 (setq word (downcase (buffer-substring 2028 (setq word (downcase (buffer-substring
2029 (match-beginning 0) (match-end 0)))) 2029 (match-beginning 0) (match-end 0))))
2030 hashtb)) 2030 hashtb))
2031 (gnus-sethash 2031 (gnus-sethash
2032 word 2032 word
2045 (string-lessp (aref (car a1) gnus-score-index) 2045 (string-lessp (aref (car a1) gnus-score-index)
2046 (aref (car a2) gnus-score-index))) 2046 (aref (car a2) gnus-score-index)))
2047 2047
2048 (defun gnus-current-score-file-nondirectory (&optional score-file) 2048 (defun gnus-current-score-file-nondirectory (&optional score-file)
2049 (let ((score-file (or score-file gnus-current-score-file))) 2049 (let ((score-file (or score-file gnus-current-score-file)))
2050 (if score-file 2050 (if score-file
2051 (gnus-short-group-name (file-name-nondirectory score-file)) 2051 (gnus-short-group-name (file-name-nondirectory score-file))
2052 "none"))) 2052 "none")))
2053 2053
2054 (defun gnus-score-adaptive () 2054 (defun gnus-score-adaptive ()
2055 "Create adaptive score rules for this newsgroup." 2055 "Create adaptive score rules for this newsgroup."
2056 (when gnus-newsgroup-adaptive 2056 (when gnus-newsgroup-adaptive
2057 ;; We change the score file to the adaptive score file. 2057 ;; We change the score file to the adaptive score file.
2058 (save-excursion 2058 (save-excursion
2059 (set-buffer gnus-summary-buffer) 2059 (set-buffer gnus-summary-buffer)
2060 (gnus-score-load-file 2060 (gnus-score-load-file
2061 (or gnus-newsgroup-adaptive-score-file 2061 (or gnus-newsgroup-adaptive-score-file
2062 (gnus-score-file-name 2062 (gnus-score-file-name
2063 gnus-newsgroup-name gnus-adaptive-file-suffix)))) 2063 gnus-newsgroup-name gnus-adaptive-file-suffix))))
2064 ;; Perform ordinary line scoring. 2064 ;; Perform ordinary line scoring.
2065 (when (or (not (listp gnus-newsgroup-adaptive)) 2065 (when (or (not (listp gnus-newsgroup-adaptive))
2066 (memq 'line gnus-newsgroup-adaptive)) 2066 (memq 'line gnus-newsgroup-adaptive))
2067 (save-excursion 2067 (save-excursion
2083 "references" 2083 "references"
2084 (symbol-name (caar elem))) 2084 (symbol-name (caar elem)))
2085 (cdar elem))) 2085 (cdar elem)))
2086 (setcar (car elem) 2086 (setcar (car elem)
2087 `(lambda (h) 2087 `(lambda (h)
2088 (,(intern 2088 (,(intern
2089 (concat "mail-header-" 2089 (concat "mail-header-"
2090 (if (eq (caar elem) 'followup) 2090 (if (eq (caar elem) 'followup)
2091 "message-id" 2091 "message-id"
2092 (downcase (symbol-name (caar elem)))))) 2092 (downcase (symbol-name (caar elem))))))
2093 h))) 2093 h)))
2094 (setq elem (cdr elem))) 2094 (setq elem (cdr elem)))
2098 (setq elem (cdr (assq (gnus-data-mark (car data)) alist))) 2098 (setq elem (cdr (assq (gnus-data-mark (car data)) alist)))
2099 (if (or (not elem) 2099 (if (or (not elem)
2100 (gnus-data-pseudo-p (car data))) 2100 (gnus-data-pseudo-p (car data)))
2101 () 2101 ()
2102 (when (setq headers (gnus-data-header (car data))) 2102 (when (setq headers (gnus-data-header (car data)))
2103 (while elem 2103 (while elem
2104 (setq match (funcall (caar elem) headers)) 2104 (setq match (funcall (caar elem) headers))
2105 (gnus-summary-score-entry 2105 (gnus-summary-score-entry
2106 (nth 1 (car elem)) match 2106 (nth 1 (car elem)) match
2107 (cond 2107 (cond
2108 ((numberp match) 2108 ((numberp match)
2109 '=) 2109 '=)
2110 ((equal (nth 1 (car elem)) "date") 2110 ((equal (nth 1 (car elem)) "date")
2111 'a) 2111 'a)
2112 (t 2112 (t
2113 ;; Whether we use substring or exact matches is 2113 ;; Whether we use substring or exact matches is
2114 ;; controlled here. 2114 ;; controlled here.
2115 (if (or (not gnus-score-exact-adapt-limit) 2115 (if (or (not gnus-score-exact-adapt-limit)
2116 (< (length match) gnus-score-exact-adapt-limit)) 2116 (< (length match) gnus-score-exact-adapt-limit))
2117 'e 2117 'e
2118 (if (equal (nth 1 (car elem)) "subject") 2118 (if (equal (nth 1 (car elem)) "subject")
2119 'f 's)))) 2119 'f 's))))
2120 (nth 2 (car elem)) date nil t) 2120 (nth 2 (car elem)) date nil t)
2121 (setq elem (cdr elem))))) 2121 (setq elem (cdr elem)))))
2122 (setq data (cdr data)))))) 2122 (setq data (cdr data))))))
2136 ;; Go through all articles. 2136 ;; Go through all articles.
2137 (while (setq d (pop data)) 2137 (while (setq d (pop data))
2138 (when (and 2138 (when (and
2139 (not (gnus-data-pseudo-p d)) 2139 (not (gnus-data-pseudo-p d))
2140 (setq score 2140 (setq score
2141 (cdr (assq 2141 (cdr (assq
2142 (gnus-data-mark d) 2142 (gnus-data-mark d)
2143 gnus-adaptive-word-score-alist)))) 2143 gnus-adaptive-word-score-alist))))
2144 ;; This article has a mark that should lead to 2144 ;; This article has a mark that should lead to
2145 ;; adaptive word rules, so we insert the subject 2145 ;; adaptive word rules, so we insert the subject
2146 ;; and find all words in that string. 2146 ;; and find all words in that string.
2244 (gnus-score-save) 2244 (gnus-score-save)
2245 (setq gnus-score-cache nil) 2245 (setq gnus-score-cache nil)
2246 (setq gnus-newsgroup-scored nil) 2246 (setq gnus-newsgroup-scored nil)
2247 (gnus-possibly-score-headers) 2247 (gnus-possibly-score-headers)
2248 (gnus-score-update-all-lines)) 2248 (gnus-score-update-all-lines))
2249 2249
2250 (defun gnus-score-flush-cache () 2250 (defun gnus-score-flush-cache ()
2251 "Flush the cache of score files." 2251 "Flush the cache of score files."
2252 (interactive) 2252 (interactive)
2253 (gnus-score-save) 2253 (gnus-score-save)
2254 (setq gnus-score-cache nil 2254 (setq gnus-score-cache nil
2323 (defun gnus-summary-lower-thread (&optional score) 2323 (defun gnus-summary-lower-thread (&optional score)
2324 "Lower score of articles in the current thread with SCORE." 2324 "Lower score of articles in the current thread with SCORE."
2325 (interactive "P") 2325 (interactive "P")
2326 (gnus-summary-raise-thread (- (1- (gnus-score-default score))))) 2326 (gnus-summary-raise-thread (- (1- (gnus-score-default score)))))
2327 2327
2328 ;;; Finding score files. 2328 ;;; Finding score files.
2329 2329
2330 (defun gnus-score-score-files (group) 2330 (defun gnus-score-score-files (group)
2331 "Return a list of all possible score files." 2331 "Return a list of all possible score files."
2332 ;; Search and set any global score files. 2332 ;; Search and set any global score files.
2333 (when gnus-global-score-files 2333 (when gnus-global-score-files
2334 (unless gnus-internal-global-score-files 2334 (unless gnus-internal-global-score-files
2335 (gnus-score-search-global-directories gnus-global-score-files))) 2335 (gnus-score-search-global-directories gnus-global-score-files)))
2336 ;; Fix the kill-file dir variable. 2336 ;; Fix the kill-file dir variable.
2337 (setq gnus-kill-files-directory 2337 (setq gnus-kill-files-directory
2338 (file-name-as-directory gnus-kill-files-directory)) 2338 (file-name-as-directory gnus-kill-files-directory))
2339 ;; If we can't read it, there are no score files. 2339 ;; If we can't read it, there are no score files.
2340 (if (not (file-exists-p (expand-file-name gnus-kill-files-directory))) 2340 (if (not (file-exists-p (expand-file-name gnus-kill-files-directory)))
2341 (setq gnus-score-file-list nil) 2341 (setq gnus-score-file-list nil)
2342 (if (not (gnus-use-long-file-name 'not-score)) 2342 (if (not (gnus-use-long-file-name 'not-score))
2343 ;; We do not use long file names, so we have to do some 2343 ;; We do not use long file names, so we have to do some
2344 ;; directory traversing. 2344 ;; directory traversing.
2345 (setq gnus-score-file-list 2345 (setq gnus-score-file-list
2346 (cons nil 2346 (cons nil
2347 (or gnus-short-name-score-file-cache 2347 (or gnus-short-name-score-file-cache
2348 (prog2 2348 (prog2
2349 (gnus-message 6 "Finding all score files...") 2349 (gnus-message 6 "Finding all score files...")
2350 (setq gnus-short-name-score-file-cache 2350 (setq gnus-short-name-score-file-cache
2351 (gnus-score-score-files-1 2351 (gnus-score-score-files-1
2354 ;; We want long file names. 2354 ;; We want long file names.
2355 (when (or (not gnus-score-file-list) 2355 (when (or (not gnus-score-file-list)
2356 (not (car gnus-score-file-list)) 2356 (not (car gnus-score-file-list))
2357 (gnus-file-newer-than gnus-kill-files-directory 2357 (gnus-file-newer-than gnus-kill-files-directory
2358 (car gnus-score-file-list))) 2358 (car gnus-score-file-list)))
2359 (setq gnus-score-file-list 2359 (setq gnus-score-file-list
2360 (cons (nth 5 (file-attributes gnus-kill-files-directory)) 2360 (cons (nth 5 (file-attributes gnus-kill-files-directory))
2361 (nreverse 2361 (nreverse
2362 (directory-files 2362 (directory-files
2363 gnus-kill-files-directory t 2363 gnus-kill-files-directory t
2364 (gnus-score-file-regexp))))))) 2364 (gnus-score-file-regexp)))))))
2365 (cdr gnus-score-file-list))) 2365 (cdr gnus-score-file-list)))
2366 2366
2367 (defun gnus-score-score-files-1 (dir) 2367 (defun gnus-score-score-files-1 (dir)
2368 "Return all possible score files under DIR." 2368 "Return all possible score files under DIR."
2369 (let ((files (list (expand-file-name dir))) 2369 (let ((files (list (expand-file-name dir)))
2370 (regexp (gnus-score-file-regexp)) 2370 (regexp (gnus-score-file-regexp))
2371 (case-fold-search nil) 2371 (case-fold-search nil)
2372 seen out file) 2372 seen out file)
2373 (while (setq file (pop files)) 2373 (while (setq file (pop files))
2374 (cond 2374 (cond
2375 ;; Ignore "." and "..". 2375 ;; Ignore "." and "..".
2376 ((member (file-name-nondirectory file) '("." "..")) 2376 ((member (file-name-nondirectory file) '("." ".."))
2377 nil) 2377 nil)
2378 ;; Add subtrees of directory to also be searched. 2378 ;; Add subtrees of directory to also be searched.
2379 ((and (file-directory-p file) 2379 ((and (file-directory-p file)
2384 ((string-match regexp file) 2384 ((string-match regexp file)
2385 (push file out)))) 2385 (push file out))))
2386 (or out 2386 (or out
2387 ;; Return a dummy value. 2387 ;; Return a dummy value.
2388 (list "~/News/this.file.does.not.exist.SCORE")))) 2388 (list "~/News/this.file.does.not.exist.SCORE"))))
2389 2389
2390 (defun gnus-score-file-regexp () 2390 (defun gnus-score-file-regexp ()
2391 "Return a regexp that match all score files." 2391 "Return a regexp that match all score files."
2392 (concat "\\(" (regexp-quote gnus-score-file-suffix ) 2392 (concat "\\(" (regexp-quote gnus-score-file-suffix )
2393 "\\|" (regexp-quote gnus-adaptive-file-suffix) "\\)\\'")) 2393 "\\|" (regexp-quote gnus-adaptive-file-suffix) "\\)\\'"))
2394 2394
2395 (defun gnus-score-find-bnews (group) 2395 (defun gnus-score-find-bnews (group)
2396 "Return a list of score files for GROUP. 2396 "Return a list of score files for GROUP.
2397 The score files are those files in the ~/News/ directory which matches 2397 The score files are those files in the ~/News/ directory which matches
2398 GROUP using BNews sys file syntax." 2398 GROUP using BNews sys file syntax."
2399 (let* ((sfiles (append (gnus-score-score-files group) 2399 (let* ((sfiles (append (gnus-score-score-files group)
2400 gnus-internal-global-score-files)) 2400 gnus-internal-global-score-files))
2401 (kill-dir (file-name-as-directory 2401 (kill-dir (file-name-as-directory
2402 (expand-file-name gnus-kill-files-directory))) 2402 (expand-file-name gnus-kill-files-directory)))
2403 (klen (length kill-dir)) 2403 (klen (length kill-dir))
2404 (score-regexp (gnus-score-file-regexp)) 2404 (score-regexp (gnus-score-file-regexp))
2405 (trans (cdr (assq ?: nnheader-file-name-translation-alist))) 2405 (trans (cdr (assq ?: nnheader-file-name-translation-alist)))
2406 ofiles not-match regexp) 2406 ofiles not-match regexp)
2407 (save-excursion 2407 (save-excursion
2408 (set-buffer (get-buffer-create "*gnus score files*")) 2408 (set-buffer (get-buffer-create "*gnus score files*"))
2409 (buffer-disable-undo (current-buffer)) 2409 (buffer-disable-undo (current-buffer))
2410 ;; Go through all score file names and create regexp with them 2410 ;; Go through all score file names and create regexp with them
2411 ;; as the source. 2411 ;; as the source.
2412 (while sfiles 2412 (while sfiles
2413 (erase-buffer) 2413 (erase-buffer)
2414 (insert (car sfiles)) 2414 (insert (car sfiles))
2415 (goto-char (point-min)) 2415 (goto-char (point-min))
2416 ;; First remove the suffix itself. 2416 ;; First remove the suffix itself.
2493 (gnus-score-file-name group gnus-adaptive-file-suffix)) 2493 (gnus-score-file-name group gnus-adaptive-file-suffix))
2494 (setq all (nreverse all))) 2494 (setq all (nreverse all)))
2495 (mapcar 'gnus-score-file-name all))) 2495 (mapcar 'gnus-score-file-name all)))
2496 (if (equal prefix "") 2496 (if (equal prefix "")
2497 all 2497 all
2498 (mapcar 2498 (mapcar
2499 (lambda (file) 2499 (lambda (file)
2500 (concat (file-name-directory file) prefix 2500 (concat (file-name-directory file) prefix
2501 (file-name-nondirectory file))) 2501 (file-name-nondirectory file)))
2502 all)))) 2502 all))))
2503 2503
2520 (push (buffer-substring beg (1- (point))) 2520 (push (buffer-substring beg (1- (point)))
2521 elems)) 2521 elems))
2522 (erase-buffer) 2522 (erase-buffer)
2523 (setq elems (delete "all" elems)) 2523 (setq elems (delete "all" elems))
2524 (length elems)))) 2524 (length elems))))
2525 2525
2526 (defun gnus-sort-score-files (files) 2526 (defun gnus-sort-score-files (files)
2527 "Sort FILES so that the most general files come first." 2527 "Sort FILES so that the most general files come first."
2528 (nnheader-temp-write nil 2528 (nnheader-temp-write nil
2529 (let ((alist 2529 (let ((alist
2530 (mapcar 2530 (mapcar
2554 (while alist 2554 (while alist
2555 (when (string-match (caar alist) group) 2555 (when (string-match (caar alist) group)
2556 ;; progn used just in case ("regexp") has no files 2556 ;; progn used just in case ("regexp") has no files
2557 ;; and score-files is still nil. -sj 2557 ;; and score-files is still nil. -sj
2558 ;; this can be construed as a "stop searching here" feature :> 2558 ;; this can be construed as a "stop searching here" feature :>
2559 ;; and used to simplify regexps in the single-alist 2559 ;; and used to simplify regexps in the single-alist
2560 (setq score-files 2560 (setq score-files
2561 (nconc score-files (copy-sequence (cdar alist)))) 2561 (nconc score-files (copy-sequence (cdar alist))))
2562 (setq alist nil)) 2562 (setq alist nil))
2563 (setq alist (cdr alist))) 2563 (setq alist (cdr alist)))
2564 ;; cache the score files 2564 ;; cache the score files
2573 ;; Make sure funcs is a list. 2573 ;; Make sure funcs is a list.
2574 (and funcs 2574 (and funcs
2575 (not (listp funcs)) 2575 (not (listp funcs))
2576 (setq funcs (list funcs))) 2576 (setq funcs (list funcs)))
2577 ;; Get the initial score files for this group. 2577 ;; Get the initial score files for this group.
2578 (when funcs 2578 (when funcs
2579 (setq score-files (nreverse (gnus-score-find-alist group)))) 2579 (setq score-files (nreverse (gnus-score-find-alist group))))
2580 ;; Add any home adapt files. 2580 ;; Add any home adapt files.
2581 (let ((home (gnus-home-score-file group t))) 2581 (let ((home (gnus-home-score-file group t)))
2582 (when home 2582 (when home
2583 (push home score-files) 2583 (push home score-files)
2589 (setq gnus-newsgroup-adaptive-score-file param-file))) 2589 (setq gnus-newsgroup-adaptive-score-file param-file)))
2590 ;; Go through all the functions for finding score files (or actual 2590 ;; Go through all the functions for finding score files (or actual
2591 ;; scores) and add them to a list. 2591 ;; scores) and add them to a list.
2592 (while funcs 2592 (while funcs
2593 (when (gnus-functionp (car funcs)) 2593 (when (gnus-functionp (car funcs))
2594 (setq score-files 2594 (setq score-files
2595 (nconc score-files (nreverse (funcall (car funcs) group))))) 2595 (nconc score-files (nreverse (funcall (car funcs) group)))))
2596 (setq funcs (cdr funcs))) 2596 (setq funcs (cdr funcs)))
2597 ;; Add any home score files. 2597 ;; Add any home score files.
2598 (let ((home (gnus-home-score-file group))) 2598 (let ((home (gnus-home-score-file group)))
2599 (when home 2599 (when home
2619 (when (member (cadr files) (cddr files)) 2619 (when (member (cadr files) (cddr files))
2620 (setcdr files (cddr files))) 2620 (setcdr files (cddr files)))
2621 (pop files))) 2621 (pop files)))
2622 ;; Do the scoring if there are any score files for this group. 2622 ;; Do the scoring if there are any score files for this group.
2623 score-files)) 2623 score-files))
2624 2624
2625 (defun gnus-possibly-score-headers (&optional trace) 2625 (defun gnus-possibly-score-headers (&optional trace)
2626 "Do scoring if scoring is required." 2626 "Do scoring if scoring is required."
2627 (let ((score-files (gnus-all-score-files))) 2627 (let ((score-files (gnus-all-score-files)))
2628 (when score-files 2628 (when score-files
2629 (gnus-score-headers score-files trace)))) 2629 (gnus-score-headers score-files trace))))
2634 (nnheader-translate-file-chars 2634 (nnheader-translate-file-chars
2635 (cond 2635 (cond
2636 ((or (null newsgroup) 2636 ((or (null newsgroup)
2637 (string-equal newsgroup "")) 2637 (string-equal newsgroup ""))
2638 ;; The global score file is placed at top of the directory. 2638 ;; The global score file is placed at top of the directory.
2639 (expand-file-name 2639 (expand-file-name
2640 suffix gnus-kill-files-directory)) 2640 suffix gnus-kill-files-directory))
2641 ((gnus-use-long-file-name 'not-score) 2641 ((gnus-use-long-file-name 'not-score)
2642 ;; Append ".SCORE" to newsgroup name. 2642 ;; Append ".SCORE" to newsgroup name.
2643 (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup) 2643 (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
2644 "." suffix) 2644 "." suffix)
2655 ;; available global score files. 2655 ;; available global score files.
2656 (interactive (list gnus-global-score-files)) 2656 (interactive (list gnus-global-score-files))
2657 (let (out) 2657 (let (out)
2658 (while files 2658 (while files
2659 (if (string-match "/$" (car files)) 2659 (if (string-match "/$" (car files))
2660 (setq out (nconc (directory-files 2660 (setq out (nconc (directory-files
2661 (car files) t 2661 (car files) t
2662 (concat (gnus-score-file-regexp) "$")))) 2662 (concat (gnus-score-file-regexp) "$"))))
2663 (push (car files) out)) 2663 (push (car files) out))
2664 (setq files (cdr files))) 2664 (setq files (cdr files)))
2665 (setq gnus-internal-global-score-files out))) 2665 (setq gnus-internal-global-score-files out)))
2705 (if (string-match "^[^.]+\\." group) 2705 (if (string-match "^[^.]+\\." group)
2706 (concat (match-string 0 group) gnus-score-file-suffix) 2706 (concat (match-string 0 group) gnus-score-file-suffix)
2707 ;; Group name without any dots. 2707 ;; Group name without any dots.
2708 (concat group (if (gnus-use-long-file-name 'not-score) "." "/") 2708 (concat group (if (gnus-use-long-file-name 'not-score) "." "/")
2709 gnus-score-file-suffix))) 2709 gnus-score-file-suffix)))
2710 2710
2711 (defun gnus-hierarchial-home-adapt-file (group) 2711 (defun gnus-hierarchial-home-adapt-file (group)
2712 "Return the adapt file of the top-level hierarchy of GROUP." 2712 "Return the adapt file of the top-level hierarchy of GROUP."
2713 (if (string-match "^[^.]+\\." group) 2713 (if (string-match "^[^.]+\\." group)
2714 (concat (match-string 0 group) gnus-adaptive-file-suffix) 2714 (concat (match-string 0 group) gnus-adaptive-file-suffix)
2715 ;; Group name without any dots. 2715 ;; Group name without any dots.