From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.emacs.gnus.general/38722 Path: main.gmane.org!not-for-mail From: Didier Verna Newsgroups: gmane.emacs.gnus.general Subject: [PATCH] new version of nndiary Date: Wed, 12 Sep 2001 16:26:31 +0200 Message-ID: NNTP-Posting-Host: coloc-standby.netfonds.no Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: main.gmane.org 1035174538 23930 80.91.224.250 (21 Oct 2002 04:28:58 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Mon, 21 Oct 2002 04:28:58 +0000 (UTC) Return-Path: Return-Path: Original-Received: (qmail 7835 invoked from network); 12 Sep 2001 14:18:26 -0000 Original-Received: from hermes.epita.fr (163.5.255.10) by gnus.org with SMTP; 12 Sep 2001 14:18:26 -0000 Original-Received: from goa.lrde.epita.fr (mail@goa.lrde.epita.fr [10.223.13.2]) by hermes.epita.fr id f8CGGSI11148 for EPITA Paris France Wed, 12 Sep 2001 16:16:28 GMT Original-Received: from uzeb.lrde.epita.fr ([10.223.13.53] ident=mail) by goa.lrde.epita.fr with esmtp (Exim 3.32 #1 (Debian)) id 15hB07-00039p-00 for ; Wed, 12 Sep 2001 16:28:27 +0200 Original-Received: from didier by uzeb.lrde.epita.fr with local (Exim 3.32 #1 (Debian)) id 15hAyH-0003PK-00 for ; Wed, 12 Sep 2001 16:26:33 +0200 Original-To: Gnus Beta Testers X-Attribution: drv X-Url: http://www.lrde.epita.fr/~didier X-Web: http://www.lrde.epita.fr/~didier X-Home-Page: http://www.lrde.epita.fr/~didier X-Face: |j}\)O|k##MrRz#VK$Jy=0r=3Qc,,a/Tr6*JQbE73dy17]2YcmW$9Z&H21e}#~#pgc>dn(is5Bv1l!{1re+Q9suKIOUmOqZs2>QMxHlR;;}kaGYA@HR3D C6 X-Face: 6o|eiKqaHN.ANh8HXDzntcWUOCg\]RsOd.ctvm~*y}Y^R&*a+Co,\s#=HWsw3x$b_n2kJ#g (7u?J^@^xP)f,jUF|0Z'J:|G/bMA5O12*b,7`-Q`=pKsCRIpso07.Y>YB2H{7`?u&yh;C_ZtLHfj * nndiary.el: new version (0.2-b13). * nndiary.el (nndiary-mail-sources): doc update. * nndiary.el (nndiary-split-methods): ditto. * nndiary.el (nndiary-request-accept-article-hooks): New. * nndiary.el (nndiary-request-accept-article): use it, check message validity. * nndiary.el (nndiary-get-new-mail): changed default to nil. * nndiary.el (nndiary-schedule): fix bug (misplaced condition-case): it didn't return nil on error. * gnus-diary.el: new version. * gnus-diary.el (gnus-diary-summary-line-format): removed %I. * gnus-diary.el (gnus-diary-header-value-history): New. * gnus-diary.el (gnus-diary-narrow-to-headers): New. * gnus-diary.el (gnus-diary-add-header): New. * gnus-diary.el (gnus-diary-check-message): New. * gnus-diary.el (message-mode-map): bind the above to `C-c D c'. * gnus-diary.el (gnus-article-edit-mode-map): ditto. Gnus Patch (runsocks cvs -q diff -u -t -b -B -w lisp/nndiary.el lisp/gnus-d= iary.el): Index: lisp/nndiary.el =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/cvsroot/gnus/lisp/nndiary.el,v retrieving revision 1.1 diff -u -u -t -b -B -w -r1.1 nndiary.el --- lisp/nndiary.el 2001/09/10 14:21:06 1.1 +++ lisp/nndiary.el 2001/09/12 13:59:14 @@ -2,7 +2,7 @@ =20 ;; Copyright (C) 1999-2001 Didier Verna. =20 -;; PRCS: $Id: nndiary.el 1.22 Tue, 04 Sep 2001 11:32:13 +0200 didier $ +;; PRCS: $Id: nndiary.el 1.26 Wed, 12 Sep 2001 15:23:27 +0200 didier $ =20 ;; Author: Didier Verna ;; Maintainer: Didier Verna @@ -69,35 +69,39 @@ ;; Usage: ;; =3D=3D=3D=3D=3D =20 -;; 1/ Diary messages contain several `X-Diary-*' special headers. You *m= ust* -;; arrange that these messages be split in a private folder *before* G= nus -;; treat them. You need this because Gnus is not able yet to manage -;; multiple backends for mail retrieval. Getting them from a separate -;; source will compensate this misfeature to some extent, as we will s= ee. -;; As an example, here's my procmailrc entry to store diary files in -;; ~/.nndiary (the default nndiary mail source file): +;; 1/ NNDiary has two modes of operation: traditional (the default) and +;; autonomous. +;; a/ In traditional mode, NNDiary does not get new mail by itself. Y= ou +;; have to move mails from your primary mail backend to nndiary +;; groups. +;; b/ In autonomous mode, NNDiary retrieves its own mail and handles it +;; independantly of your primary mail backend. To use NNDiary in +;; autonomous mode, you have several things to do: +;; i/ Put (setq nndiary-get-new-mail t) in your gnusrc file. +;; ii/ Diary messages contain several `X-Diary-*' special headers. +;; You *must* arrange that these messages be split in a priva= te +;; folder *before* Gnus treat them. You need this because Gn= us +;; is not able yet to manage multiple backends for mail +;; retrieval. Getting them from a separate source will +;; compensate this misfeature to some extent, as we will see. +;; As an example, here's my procmailrc entry to store diary f= iles +;; in ~/.nndiary (the default nndiary mail source file): ;; ;; :0 HD : ;; * ^X-Diary ;; .nndiary -;; +;; iii/ Customize the variables `nndiary-mail-sources' and +;; `nndiary-split-methods'. These are replacements for the u= sual +;; mail sources and split methods which, and will be used in +;; autonomous mode. `nndiary-mail-sources' defaults to +;; '(file :path "~/.nndiary"). ;; 2/ Install nndiary somewhere Emacs / Gnus can find it. Normally, you ;; *don't* have to '(require 'nndiary) anywhere. Gnus will do so when ;; appropriate as long as nndiary is somewhere in the load path. -;; 3/ Now, customize nndiary: type `M-x customize-group', and then `nndia= ry' -;; at the prompt (note that if you have not restarted Emacs yet, you'll -;; have to the load the library by hand before being able to customize= it). -;; In particular, you should customize the following options: -;; - `nndiary-mail-sources', which overrides the normal `mail-sources' -;; value for diary messages retrieving. It defaults to -;; '(file :path "~/.nndiary"). -;; - `nndiary-split-methods', which overrides the normal -;; `nnmail-split-methods' value for diary messages splitting. You c= an -;; have all the diary groups you want (for example, I have a birthda= ys -;; group, and stuff like that). -;; - `nndiary-reminders', the list of times when you want to be remind= ed -;; of your appointements (e.g. 3 weeks before, then 2 days before, t= hen -;; 1 hour before and that's it). +;; 3/ Now, customize the rest of nndiary. In particular, you should +;; customize `nndiary-reminders', the list of times when you want to be +;; reminded of your appointements (e.g. 3 weeks before, then 2 days +;; before, then 1 hour before and that's it). ;; 4/ You *must* use the group timestamp feature of Gnus. This adds a ;; timestamp to each groups' parameters (please refer to the Gnus ;; documentation ("Group Timestamp" info node) to see how it's done. @@ -159,14 +163,16 @@ ;; * Respooling doesn't work because contrary to the request-scan function, ;; Gnus won't allow me to override the split methods when calling the ;; respooling backend functions. -;; * The time zone mechanism is subject to change. +;; * There's a bug in the time zone mechanism with variable TZ locations. ;; * We could allow a keyword like `ask' in X-Diary-* headers, that would = mean -;; "ask for value upon reception of the message". Suggested by Jody Klym= ak. +;; "ask for value upon reception of the message". ;; * We could add an optional header X-Diary-Reminders to specify a special ;; reminders value for this message. Suggested by Jody Klymak. -;; * Modify the request-accept-article function to make it prompt for diary -;; headers if they're missing. +;; * We should check messages validity in other circumstances than just +;; moving an article from sonwhere else (request-accept). For instance, = when +;; editing / saving and so on. =20 + ;; Remarks: ;; =3D=3D=3D=3D=3D=3D=3D =20 @@ -224,7 +230,8 @@ `((file :path ,(expand-file-name "~/.nndiary"))) "*NNDiary specific mail sources. This variable is used by nndiary in place of the standard `mail-sources' -variable. These sources must contain diary messages ONLY." +variable when `nndiary-get-new-mail' is set to non-nil. These sources +must contain diary messages ONLY." :group 'nndiary :group 'mail-source :type 'sexp) @@ -232,7 +239,8 @@ (defcustom nndiary-split-methods '(("diary" "")) "*NNDiary specific split methods. This variable is used by nndiary in place of the standard -`nnmail-split-methods' variable." +`nnmail-split-methods' variable when `nndiary-get-new-mail' is set to +non-nil." :group 'nndiary :group 'nnmail-split :type '(choice (repeat :tag "Alist" (group (string :tag "Name") regexp)) @@ -304,6 +312,13 @@ :group 'nndiary :type 'hook) =20 +(defcustom nndiary-request-accept-article-hooks nil + "*Hooks to run before accepting an article. +Executed near the beginning of `nndiary-request-accept-article'. +The hooks will be called with the article in the current buffer." + :group 'nndiary + :type 'hook) + (defcustom nndiary-check-directory-twice t "*If t, check directories twice to avoid NFS failures." :group 'nndiary @@ -327,10 +342,11 @@ (expand-file-name "newsgroups" nndiary-directory) "Newsgroups description file for the nndiary backend.") =20 -(defvoo nndiary-get-new-mail t +(defvoo nndiary-get-new-mail nil "Whether nndiary gets new mail and split it. -Contrary to traditional mail backends, this variable should always be -non-nil because nndiary uses its own mail-sources and split-methods.") +Contrary to traditional mail backends, this variable can be set to t +even if your primary mail backend also retreives mail. In such a case, +NDiary uses its own mail-sources and split-methods.") =20 (defvoo nndiary-nov-is-evil nil "If non-nil, Gnus will never use nov databases for nndiary groups. @@ -352,7 +368,7 @@ ;; $Format: "(defconst nndiary-prcs-major-version \"$ProjectMajorVersion$\= ")"$ (defconst nndiary-prcs-major-version "branch-0-2") ;; $Format: "(defconst nndiary-prcs-minor-version \"$ProjectMinorVersion$\= ")"$ -(defconst nndiary-prcs-minor-version "1") +(defconst nndiary-prcs-minor-version "13") (defconst nndiary-version (let ((level nndiary-prcs-minor-version) major minor status) @@ -745,6 +761,8 @@ (deffoo nndiary-request-accept-article (group &optional server last) (nndiary-possibly-change-directory group server) (nnmail-check-syntax) + (run-hooks 'nndiary-request-accept-article-hooks) + (when (nndiary-schedule) (let (result) (when nnmail-cache-accepted-message-ids (nnmail-cache-insert (nnmail-fetch-field "message-id"))) @@ -770,6 +788,7 @@ (nnmail-cache-close)) (nndiary-save-nov)))) result)) + ) =20 (deffoo nndiary-request-post (&optional server) (nnmail-do-request-post 'nndiary-request-accept-article server)) @@ -1285,7 +1304,7 @@ val))) =20 (defun nndiary-parse-schedule-value (str min-or-values max) - ;; Parse the schedule string STR. + ;; Parse the schedule string STR, or signal an error. ;; Signals are caught by `nndary-schedule'. (if (string-match "[ \t]*\\*[ \t]*" str) ;; unspecifyed @@ -1339,15 +1358,18 @@ )) =20 (defsubst nndiary-schedule () + (let (head) + (condition-case arg (mapcar (lambda (elt) - (condition-case arg - (nndiary-parse-schedule (nth 0 elt) (nth 1 elt) (nth 2 elt)) + (setq head (nth 0 elt)) + (nndiary-parse-schedule (nth 0 elt) (nth 1 elt) (nth 2 elt))) + nndiary-headers) (t (nnheader-report 'nndiary "X-Diary-%s header parse error: %s." - (car elt) (cdr arg)) - nil))) - nndiary-headers)) + head (cdr arg)) + nil)) + )) =20 (defun nndiary-max (spec) ;; Returns the max of specification SPEC, or nil for permanent schedules. Index: lisp/gnus-diary.el =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/cvsroot/gnus/lisp/gnus-diary.el,v retrieving revision 1.1 diff -u -u -t -b -B -w -r1.1 gnus-diary.el --- lisp/gnus-diary.el 2001/09/10 14:21:06 1.1 +++ lisp/gnus-diary.el 2001/09/12 13:59:14 @@ -1,13 +1,13 @@ ;;; gnus-diary.el --- Wrapper around the NNDiary Gnus backend =20 -;; Copyright (C) 1999 Didier Verna. +;; Copyright (C) 1999-2001 Didier Verna. =20 -;; PRCS: $Id: gnus-diary.el 1.8 Tue, 04 Sep 2001 11:32:13 +0200 didier $ +;; PRCS: $Id: gnus-diary.el 1.17 Wed, 12 Sep 2001 15:54:36 +0200 didier $ =20 ;; Author: Didier Verna ;; Maintainer: Didier Verna ;; Created: Tue Jul 20 10:42:55 1999 under XEmacs 21.2 (beta 18) -;; Last Revision: Wed Aug 8 14:38:14 2001 +;; Last Revision: Wed Sep 12 12:31:09 2001 ;; Keywords: calendar mail news =20 ;; This file is part of NNDiary. @@ -35,17 +35,17 @@ ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 ;; Gnus-Diary is a wrapper around the NNDiary Gnus backend. It is here to -;; make your nndiary-user life easier in differnet ways. So, you don't ha= ve +;; make your nndiary-user life easier in different ways. So, you don't ha= ve ;; to use it if you don't want to. But, really, you should. =20 -;; Gnus-Diary offers the following improvements on top of the NNDiary back= end: +;; Gnus-Diary offers the following features on top of the NNDiary backend: =20 ;; - A nice summary line format: ;; Displaying diary messages in standard summary line format (usually ;; something like ": ") is pretty useless. Most of t= he ;; time, you're the one who wrote the message, and you mostly want to see -;; the event's date. Gnus-Diary offers you a nice summary line format w= hich -;; will do this. By default, a summary line will appear like this: +;; the event's date. Gnus-Diary offers you a nice summary line format +;; which will do this. By default, a summary line will appear like thi= s: ;; ;; : ;; @@ -70,7 +70,19 @@ ;; headers will be inserted automatically (but not filled with proper ;; values yet). =20 +;; - An interactive mail-to-diary convertion function: +;; The function `gnus-diary-check-message' ensures that the current mes= sage +;; contains all the required diary headers, and prompts you for values / +;; correction if needed. This function is hooked in the nndiary backen= d so +;; that moving an article to an nndiary group will trigger it +;; automatically. It is also bound to `C-c D c' in message-mode and +;; article-edit-mode in order to ease the process of converting a usual +;; mail to a diary one. This function takes a prefix argument which wi= ll +;; force prompting of all diary headers, regardless of their +;; presence/validity. That way, you can very easily reschedule a diary +;; message for instance. =20 + ;; Usage: ;; =3D=3D=3D=3D=3D =20 @@ -84,22 +96,17 @@ ;; Bugs / Todo: ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 -;; * Provide `gnus-group-diary-mail' and `gnus-group-post-diary-news' (or -;; something like that), that would do just like `gnus-group-mail' and -;; `gnus-group-post-news', but also prompt for diary header values with -;; completion etc. -;; * Maybe not actually: we could just have a function that converts *any* -;; message to a diary one, by prompting the schedule. You could then for= ward -;; a message and make it a diary one etc. =20 ;;; Code: =20 (require 'nndiary) +(require 'message) +(require 'gnus-art) =20 (defgroup gnus-diary nil "Utilities on top of the nndiary backend for Gnus.") =20 -(defcustom gnus-diary-summary-line-format "%U%R%z%I %uD: %(%s%) (%ud)\n" +(defcustom gnus-diary-summary-line-format "%U%R%z %uD: %(%s%) (%ud)\n" "*Summary line format for nndiary groups." :type 'string :group 'gnus-diary @@ -325,10 +334,127 @@ (add-hook 'gnus-subscribe-newsgroup-hooks 'gnus-diary-maybe-update-group-parameters) =20 + +;; Diary Message Checking =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +(if (fboundp 'kill-entire-line) + (defun gnus-diary-kill-entire-line () + (kill-entire-line)) + (defun gnus-diary-kill-entire-line () + (beginning-of-line) + (let ((kill-whole-line t)) + (kill-line))) + ) + +(defvar gnus-diary-header-value-history nil + ;; History variable for header value prompting + ) + +(defun gnus-diary-narrow-to-headers () + "Narrow the current buffer to the header part. +Point is left at the beginning of the region. +The buffer is assumed to contain a message, but the format is unknown." + (cond ((eq major-mode 'message-mode) + (message-narrow-to-headers)) + (t + (goto-char (point-min)) + (when (search-forward "\n\n" nil t) + (narrow-to-region (point-min) (- (point) 1)) + (goto-char (point-min)))) + )) + +(defun gnus-diary-add-header (str) + "Add a header to the current buffer. +The buffer is assumed to contain a message, but the format is unknown." + (cond ((eq major-mode 'message-mode) + (message-add-header str)) + (t + (save-restriction + (gnus-diary-narrow-to-headers) + (goto-char (point-max)) + (if (string-match "\n$" str) + (insert str) + (insert str ?\n)))) + )) + +(defun gnus-diary-check-message (arg) + "Ensure that the current message is a valid for NNDiary. +This function checks that all NNDiary required headers are present and +valid, and prompts for values / correction otherwise. + +If ARG (or prefix) is non-nil, force prompting for all fields." + (interactive "P") + (save-excursion + (mapcar + (lambda (head) + (let ((header (concat "X-Diary-" (car head))) + (ask arg) + value invalid) + ;; First, try to find the header, and checks for validity: + (save-restriction + (gnus-diary-narrow-to-headers) + (when (re-search-forward (concat "^" header ":") nil t) + (unless (eq (char-after) ? ) + (insert " ")) + (setq value (buffer-substring (point) (point-at-eol))) + (and (string-match "[ \t]*\\([^ \t]+\\)[ \t]*" value) + (setq value (match-string 1 value))) + (condition-case () + (nndiary-parse-schedule-value value + (nth 1 head) (nth 2 head)) + (t + (setq invalid t))) + ;; #### NOTE: this (along with the `gnus-diary-add-header' + ;; function) could be rewritten in a better way, in particular + ;; not to blindly remove an already present header and reinse= rt + ;; it somewhere else afterwards. + (when (or ask invalid) + (gnus-diary-kill-entire-line)) + )) + ;; Now, loop until a valid value is provided: + (while (or ask (not value) invalid) + (let ((prompt (concat (and invalid + (prog1 "(current value invalid) " + (beep))) + header + (and (not value) " (defaults to `*')") + ": "))) + (setq value + (if (listp (nth 1 head)) + (completing-read prompt (cons '("*" nil) (nth 1 hea= d)) + nil t value + gnus-diary-header-value-history "*= ") + (read-string prompt value + gnus-diary-header-value-history "*")))) + (setq ask nil) + (setq invalid nil) + (condition-case () + (nndiary-parse-schedule-value value + (nth 1 head) (nth 2 head)) + (t + (setq invalid t)))) + (gnus-diary-add-header (concat header ": " value)) + )) + nndiary-headers) + )) + +(add-hook 'nndiary-request-accept-article-hooks + (lambda () (gnus-diary-check-message nil))) + +(define-key message-mode-map "\C-cDc" 'gnus-diary-check-message) +(define-key gnus-article-edit-mode-map "\C-cDc" 'gnus-diary-check-message) + + +;; The end =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + (defun gnus-diary-version () "Current Diary backend version." (interactive) (message "NNDiary version %s" nndiary-version)) + +(define-key message-mode-map "\C-cDv" 'gnus-diary-version) +(define-key gnus-article-edit-mode-map "\C-cDv" 'gnus-diary-version) + =20 (provide 'gnus-diary) =20 --=20 Didier Verna, didier@lrde.epita.fr, http://www.lrde.epita.fr/~didier EPITA / LRDE, 14-16 rue Voltaire Tel.+33 (1) 53 14 59 47 94276 Le Kremlin-Bic=EAtre, France Fax.+33 (1) 44 08 01 99 didier@xemac= s.org