From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christopher League Subject: Re: wish list: sort tasks by age Date: Wed, 1 Jul 2009 09:26:14 -0400 Message-ID: <1B91C2B7-A9A5-4370-AF63-5549DB74746D@contrapunctus.net> References: <9FE27D7D-3CB3-4B17-9061-0AFF0FCD0AFF@contrapunctus.net> <87tz1wzy1o.wl%maus.david@gmail.com> <873a9gem4v.wl%maus.david@gmail.com> <87d48kipim.fsf@bzg.ath.cx> Mime-Version: 1.0 (Apple Message framework v935.3) Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MLzpS-0007g6-W1 for emacs-orgmode@gnu.org; Wed, 01 Jul 2009 09:26:27 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MLzpO-0007d0-23 for Emacs-orgmode@gnu.org; Wed, 01 Jul 2009 09:26:26 -0400 Received: from [199.232.76.173] (port=59732 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MLzpN-0007cp-PE for Emacs-orgmode@gnu.org; Wed, 01 Jul 2009 09:26:21 -0400 Received: from contrapunctus.net ([207.210.219.173]:51530) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MLzpN-0002Iv-7b for Emacs-orgmode@gnu.org; Wed, 01 Jul 2009 09:26:21 -0400 In-Reply-To: <87d48kipim.fsf@bzg.ath.cx> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: David Maus Cc: Bastien , org-mode mailing list Thanks everyone. I think I managed to get something like David's suggestion working... I spent the most time trying to initialize the creation times from git though, with vc-annotate.. I don't think that was meant to be used non-interactively, but I beat it into shape. :) The other end of it is the agenda view, so I made a comparison function that puts them in order oldest to youngest. I made a gist for the snippet here: http://gist.github.com/138770 and I'll also paste below. org-expiry is interesting.. I didn't know about that. Certainly there's a similarity, although the point of view is different: "tasks that are old and should be archived" vs. "tasks that are old and should be FINISHED!!!" :) I haven't thought too much yet about how to unify the two ideas... Chris On Jul 1, 2009, at 7:58 AM, Bastien wrote: > David Maus writes: >> And what a fun it is to train my elisp skills. A first hack that >> seems to work: >> >> (defun dmj/org-assure-creation-property () >> "Process all orgmode entries of current buffer that do not >> match a defined search string" >> (interactive) >> (org-map-entries 'dmj/org-insert-creation-property "+Creation_Time= >> \"\"") >> ) >> >> (defun dmj/org-insert-creation-property () >> "Insert Creation-Property in Orgmode entry at point" >> (let ((stamp (format-time-string (cdr org-time-stamp-formats) >> (current-time)))) >> (setq stamp (concat "[" (substring stamp 1 -1) "]")) >> (org-entry-put (point-marker) "Creation_Time" stamp)) >> ) >> > Thanks for this David -- you might also have a look at the code in > org-expiry.el. If there is anything there that you want to improve, > please do so! ;;; sorting org-mode tasks by age (defconst org-age-property "CREATED") (defun org-age-set-to-today-if-missing () (interactive) (or (org-entry-get (point) org-age-property) (let ((d (format-time-string "%Y-%m-%d" (current-time)))) (org-entry-put (point) org-age-property d) d))) (defconst org-date-regexp "\\b[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\ \b") (defun org-age-set-from-vc-if-missing () (interactive) (or (org-entry-get (point) org-age-property) (let ((current-line (count-lines (point-min) (point))) date-string) (save-window-excursion (vc-annotate buffer-file-name (vc-workfile-version buffer- file-name)) (if (search-forward-regexp org-date-regexp (point-at-eol) t) (setq date-string (match-string 0))) (kill-buffer nil)) ;; otherwise next annotation may be wrong (when date-string (org-entry-put (point) org-age-property date-string) (basic-save-buffer)) ;; otherwise next annotation may be wrong date-string))) (defvar org-age-todo-match "/TODO|PROJECT|MAYBE|WAIT") (defun org-age-set-all (setf) (let ((rs (org-map-entries setf org-age-todo-match 'agenda))) rs)) (defun org-age-set-all-to-today () (interactive) (org-age-set-all 'org-age-set-to-today-if-missing)) (org-age-set-all-to-today) (defun org-age-set-all-from-vc () (interactive) (org-age-set-all 'org-age-set-from-vc-if-missing)) (defun org-age-compare (a b) (let* ((ma (get-text-property 1 'org-marker a)) (mb (get-text-property 1 'org-marker b)) (da (with-current-buffer (marker-buffer ma) (goto-char (marker-position ma)) (org-age-set-to-today-if-missing))) (db (with-current-buffer (marker-buffer mb) (goto-char (marker-position mb)) (org-age-set-to-today-if-missing)))) (cond ((string< da db) -1) ((string= da db) nil) (t +1)))) (setq org-agenda-cmp-user-defined 'org-age-compare) (setq org-agenda-custom-commands '(("z" "description" todo "TODO" ((org-agenda-sorting-strategy '(user-defined-up)) (org-agenda-archives-mode nil)))))