From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alan Schmitt Subject: Re: org-review-schedule Date: Thu, 24 Apr 2014 13:51:02 +0200 Message-ID: References: <877g6leltk.fsf@bzg.ath.cx> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54521) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WdUrH-0000hZ-RD for emacs-orgmode@gnu.org; Thu, 24 Apr 2014 21:24:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WdIBE-0001SY-LE for emacs-orgmode@gnu.org; Thu, 24 Apr 2014 07:51:14 -0400 In-Reply-To: <877g6leltk.fsf@bzg.ath.cx> (Bastien's message of "Sat, 19 Apr 2014 10:14:35 +0200") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Bastien Cc: emacs-orgmode --=-=-= Content-Type: text/plain Hi Bastien, On 2014-04-19 10:14, Bastien writes: > Hi Alan, > > thanks for sharing -- some comments: > > - you need to update the copyright of the file; I changed the date. As I signed the FSF paper, do I need to change the name as well and put mine? > - example code in section 3 of the header is mangled; I removed that example; it should not be in the file. > - there are some dangling parentheses; Are those parentheses on a line by themselves? I could not find them. > - use (get-text-property (point-min) ...) instead of > (get-text-property 1 ...) Changed. > - I'd use org-review instead of org-review-schedule as prefix; Changed. > - maybe you can use "naked" timestamps like 2014-04-19 sam. > instead of inactive ones, this way using "[" in the agenda > will not create false positives by inserting entries with > a REVIEW property. This is now the case by default, with an option to have inactive or active time stamps. > - I infer from a quick read that this works for the agenda but > I guess this could work for both the agenda and Org buffers; It depends what "this" means ;-) My goal was to use it in an agenda view, but most of the functionality does not depend on it. > Since you took inspirationg from org-expiry, I guess some of > the comments above would apply there too... feel free to hack > into this directions for both org-expiry.el and org-review.el! > Actually, maybe both should be merged somehow, since expiring > is just reviewing entries to interactively delete them. I'm still not sure where to take this ... I agree both are cases of adding dates to entries and doing things according to those dates, but I still need to think more about how to generalize it to cover both cases. I attach the new version. I would like to propose to add this to the contrib directory, but I don't know the procedure to submit this code. Thanks, Alan --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=org-review.el Content-Transfer-Encoding: quoted-printable ;;; org-review.el --- schedule reviews for Org entries ;; ;; Copyright 2014 Free Software Foundation, Inc. ;; ;; Author: Alan Schmitt ;; Version: 0.1 ;; Keywords: org review ;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; ;; This allows to schedule reviews of org entries. ;; ;; Entries will be scheduled for review only if their LAST_REVIEW ;; property is set. The next review date is computed from the ;; LAST_REVIEW property and the REVIEW_DELAY period, such as "+1m". If ;; REVIEW_DELAY is absent, a default period is used. Note that the ;; LAST_REVIEW property is not considered as inherited, but REVIEW_DELAY ;; is, allowing to set it for whole subtrees. ;; ;; Checking of review dates is done through an agenda view, using the ;; `org-review-skip' skipping function. This function is based ;; on `org-review-toreview-p', that returns `nil' if no review ;; is necessary (no review planned or it happened recently), otherwise ;; it returns the date the review was first necessary (LAST_REVIEW + ;; REVIEW_DELAY if it is in the past). ;; ;; When the entry is marked as reviewed, the LAST_REVIEW date is set to ;; the current date. The function ;; `org-review-insert-last-review' may be used for this. ;; ;; Example use. ;;=20 ;; 1 - To display the things to review in the agenda. ;;=20 ;; (setq org-agenda-custom-commands (quote ( ... ("R" "Review ;; projects" tags-todo "-CANCELLED/" ;; ((org-agenda-overriding-header "Reviews Scheduled") ;; (org-agenda-skip-function 'org-review-skip) ;; (org-agenda-cmp-user-defined 'org-review-compare) ;; (org-agenda-sorting-strategy '(user-defined-down)))) ... ))) ;; ;; 2 - To set a key binding to review from the agenda ;; ;; (add-hook 'org-agenda-mode-hook (lambda () (local-set-key (kbd "C-c ;; C-r") 'org-review-insert-last-review))) ;;; Code: ;;; User variables: (defgroup org-review nil "Org review scheduling." :tag "Org Review Schedule" :group 'org) (defcustom org-review-timestamp-format 'naked "Timestamp format for last review properties." :type '(radio (const naked) (const inactive) (const active)) :group 'org-review) (defcustom org-review-last-property-name "LAST_REVIEW" "The name of the property for the date of the last review." :type 'string :group 'org-review) (defcustom org-review-delay-property-name "REVIEW_DELAY" "The name of the property for setting the delay before the next review." :type 'string :group 'org-review) (defcustom org-review-delay "+1m" "Time span between the date of last review and the next one. The default value for this variable (\"+1m\") means that entries will be marked for review one month after their last review. If the review delay cannot be retrieved from the entry or the subtree above, this delay is used." :type 'string :group 'org-review) ;;; Functions: (defun org-review-last-planned (last delay) "Computes the next planned review, given the LAST review date (in string format) and the review DELAY (in string format)." (let* ((lt (org-read-date nil t last)) (ct (current-time))) (time-add lt (time-subtract (org-read-date nil t delay) ct)))) (defun org-review-last-review-prop () "Return the value of the last review property of the current headline." (let ((lr-prop org-review-last-property-name)) (org-entry-get (point) lr-prop))) (defun org-review-toreview-p () "Check if the entry at point should be marked for review. Return nil if the entry does not need to be reviewed. Otherwise return the number of days between the past planned review date and today. If there is no last review date, return nil. If there is no review delay period, use `org-review-delay'." (let* ((lr-prop org-review-last-property-name) (lp (org-entry-get (point) lr-prop))) (when lp=20 (let* ((dr-prop org-review-delay-property-name) (dr (or (org-entry-get (point) dr-prop t)=20 org-review-delay)) (nt (org-review-last-planned lp dr)) ) (if (time-less-p nt (current-time)) nt))))) (defun org-review-insert-last-review (&optional prompt) "Insert the current date as last review. If prefix argument: prompt the user for the date." (interactive "P") (let* ((ts (if prompt (concat "<" (org-read-date) ">") (format-time-string (car org-time-stamp-formats))))) (save-excursion (org-entry-put (if (equal (buffer-name) org-agenda-buffer-name) (or (org-get-at-bol 'org-marker) (org-agenda-error)) (point)) org-review-last-property-name (cond=20 ((equal org-review-timestamp-format 'inactive) (concat "[" (substring ts 1 -1) "]")) ((equal org-review-timestamp-format 'active) ts) (t (substring ts 1 -1))))))) (defun org-review-skip () "Skip entries that are not scheduled to be reviewed." (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond ((org-review-toreview-p) nil) (t next-headline))))) (defun org-review-compare (a b) "Compares the date of scheduled review for the two agenda entries, to be used with `org-agenda-cmp-user-defined'. Returns +1 if A has been scheduled for longer and -1 otherwise." (let* ((ma (or (get-text-property (point-min) 'org-marker a) (get-text-property (point-min) 'org-hd-marker a))) (mb (or (get-text-property (point-min) 'org-marker b) (get-text-property (point-min) 'org-hd-marker b))) (pal (org-entry-get ma org-review-last-property-name)) (pad (or (org-entry-get ma org-review-delay-property-name t) org-review-delay)) (pbl (org-entry-get mb org-review-last-property-name)) (pbd (or (org-entry-get mb org-review-delay-property-name t) org-review-delay)) (sa (org-review-last-planned pal pad)) (sb (org-review-last-planned pbl pbd))) (if (time-less-p sa sb) 1 -1))) (provide 'org-review) ;;; org-review.el ends here --=-=-=--