; This file contains some functions for Gnus, to be used with ; egowatch.pl. The main function it adds is add-watch, which is bound ; to (f5) in the gnus-summary-mode-map. It allows the user to save ; match-data to be used by egowatch.pl, so that later followups will ; prompt an email to the user. ; ; See egowatch.pl for instructions and explanations. ; ; Credits and blame: ; ; This program was written by Jesse Hughes, jesseh@cs.kun.nl. It may ; be freely modified, distributed, whatever, as long as the source ; file continues to acknowledge the contribution of the original ; author. ; Please email for any fixes, questions, complaints, suggestions, etc. ; I'm not much of a Perl hacker, so criticisms are welcome. ; Format of the watch file: ; newsgroup name:header:contents:expiration ; ; comment character "#" (require 'string) (define-key gnus-summary-mode-map [(f5)] 'add-watch) ;;Maybe some day I'll write this. It would allow one to mark the ;;articles in the summary buffer that match something in the ;;watch-file. (defun read-watch-file()) ;;Maybe some day I'll write this, too, so that one can delete entries ;;in the watch-file from the summary buffer. I'm not sure how useful ;;this is. In any case, at present, one can do this by hand. (defun del-watch()) ;;; ; ; See the perl function quotemeta. ; ;;; (defun quote-meta (str) (let ((ret (string-replace-match "[^a-zA-Z0-9]" str "\\\\\\&" nil t))) (if ret ret str))) (defun read-exp-date-str () (let ((entered nil)) (while (progn (setq entered (read-string "Expiration date: " (format-time-string "%D %R" (cons (+ (car (current-time)) (/ (* 30 24 60 60) (lsh 2 15))) (+ (car (cdr (current-time))) (% (* 30 24 60 60) (lsh 2 15))))))) (let* ((date (car (string-split "[ ]+" entered))) (time (cadr (string-split "[ ]+"entered))) (month (string-to-int (car (string-split "/" date)))) (day (string-to-int (cadr (string-split "/" date)))) (year (+ 2000 (string-to-int (caddr (string-split "/" date))))) (hour (string-to-int (car (string-split ":" time)))) (min (string-to-int (cadr (string-split ":" time))))) ;seconds minutes hour day month year (not (encode-time 0 min hour day month year))))) entered)) ;;; ; ; add-watch ; ;;; (defun add-watch (header grp type val expiration-date-str) "Adds a record to the egowatch file.\nSee egowatch.pl for explanation of this file.\n\nThe inputs are:\n header : A newsgroup header.\n grp : Newsgroup.\n type : Substring or regexp match type.\n val : Match value.\n expiration-date : Date at which this record expires." (interactive (let* ((header (progn (gnus-summary-scroll-up 0) ;; Select current article (let ((sel (completing-read "Header [subject]: " '(("Subject" 0) ("subject" 0) ("References" 1) ("references" 1) ("From" 2) ("from" 2) )))) (if (not (string= sel "")) (capitalize sel) "Subject")))) (grp (read-string "Newsgroup: " (if gnus-newsgroup-name gnus-newsgroup-name ""))) ;; Question: What is the second element of the alist for ;; completing-read *used* for? (type (let ((sel (completing-read "Match type [substring]: " '(("regexp" 0) ("substring" 1)) nil t))) (if (not (string= sel "")) sel "substring"))) (field (condition-case nil (progn (set-buffer gnus-original-article-buffer) (if (string= "References" header) (mail-fetch-field "Message-ID") (mail-fetch-field header))) (error ""))) (val (read-string (concat (capitalize type) " match data: ") (if (string= type "regexp") (quote-meta field) field))) (expiration-date-str (read-exp-date-str))) (list header grp type val expiration-date-str))) (save-excursion (if (string= type "substring") (setq val (quote-meta val))) (set-buffer (find-file-noselect "/home/jesse/.newswatch/newswatch.in" t)) (goto-char (point-max)) (if (not (= 0 (current-column))) (newline)) (insert "\"" grp "\",\"" header "\",\"" val "\",\"") (call-process "date" "/dev/null" t nil (concat "-d " expiration-date-str) "+%s") (delete-char -1) ;;Remove newline. (insert "\"") (save-buffer) )) (provide 'ego-watch)