emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* wish list: sort tasks by age
@ 2009-06-30 20:04 Christopher League
       [not found] ` <87tz1wzy1o.wl%maus.david@gmail.com>
  2009-07-01 11:57 ` Bastien
  0 siblings, 2 replies; 7+ messages in thread
From: Christopher League @ 2009-06-30 20:04 UTC (permalink / raw)
  To: Emacs-orgmode

I would love to be able to sort TODOs by their age, so it becomes  
painfully obvious what I have been ignoring.  Since org relies on free- 
form text (a strength), it's tricky to ensure that every item gets a  
'creation-time' property.  But it doesn't need to be accurate to the  
second; even a script that added that property once every day or so  
might do the trick.

Since I commit my agenda files to git every day or so, I can actually  
get an approximation to this with git-blame... grep the TODO  
headlines, then sort by commit date.  It's pretty hackish, and I'm not  
sure I want to go to the trouble of integrating that raw data with the  
agenda view, if there's a better way within org.

Ideas? Thanks!
Chris

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
       [not found] ` <87tz1wzy1o.wl%maus.david@gmail.com>
@ 2009-07-01  8:10   ` Manish
  2009-07-01 10:24     ` David Maus
  0 siblings, 1 reply; 7+ messages in thread
From: Manish @ 2009-07-01  8:10 UTC (permalink / raw)
  To: David Maus; +Cc: Emacs-orgmode

  On Wed, Jul 1, 2009 at 12:31 PM, David Maus<maus.david@gmail.com> wrote:
  > At Tue, 30 Jun 2009 16:04:39 -0400,
  > Christopher League wrote:
  >>
  >> I would love to be able to sort TODOs by their age, so it becomes
  >> painfully obvious what I have been ignoring. Since org relies on free-
  >> form text (a strength), it's tricky to ensure that every item gets a
  >> 'creation-time' property. But it doesn't need to be accurate to the
  >> second; even a script that added that property once every day or so
  >> might do the trick.
  >
  > Well, I'm not a elisp hacker but what comes into my mind is a custom
  > function that does:
  >
  > for all headlines with a TODO keyword
  >
  > * check if property "creation-time" exists
  >
  > * add propertie creation time with current date & time if such an
  > propertie does not exist
  >
  > and then hook this function into before-save-hook.
  >
  > So the question is (a) if there are functions to process all items,
  > check for existence of a property and create properties (I'm quite
  > certain there are) and (b) how to use them.

There are property and mapping APIs documented in the manual under
section on hacking.

-- 
Manish

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
  2009-07-01  8:10   ` Manish
@ 2009-07-01 10:24     ` David Maus
  2009-07-01 11:58       ` Bastien
  0 siblings, 1 reply; 7+ messages in thread
From: David Maus @ 2009-07-01 10:24 UTC (permalink / raw)
  To: Emacs-orgmode

At Wed, 1 Jul 2009 13:40:21 +0530,
Manish wrote:
> 
> There are property and mapping APIs documented in the manual under
> section on hacking.

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))
)

The first function (dmj/assure-creation-property) processes every
entry in current buffer that match the search query Creation_Time="",
i.e. entries with an empty or no Creation_Time property at all and
calls dmj/org-insert-creation-property to insert a Creation_Time
property with the current time into this entry.

The tag search query should be refined to only match headlines with
(certain) TODO keywords.

The first function is defined as interactive so you can call it via
M-x -- and of course this is just a fast hack with no warranty at all.

Regards

  -- David

-- 
OpenPGP... 0x316F4BE4670716FD
Jabber.... dmjena@jabber.org
Email..... maus.david@gmail.com
ICQ....... 241051416

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
  2009-06-30 20:04 wish list: sort tasks by age Christopher League
       [not found] ` <87tz1wzy1o.wl%maus.david@gmail.com>
@ 2009-07-01 11:57 ` Bastien
  1 sibling, 0 replies; 7+ messages in thread
From: Bastien @ 2009-07-01 11:57 UTC (permalink / raw)
  To: Christopher League; +Cc: Emacs-orgmode

Christopher League <league@contrapunctus.net> writes:

> I would love to be able to sort TODOs by their age, so it becomes
> painfully obvious what I have been ignoring.  Since org relies on free- 
> form text (a strength), it's tricky to ensure that every item gets a
> creation-time' property.  But it doesn't need to be accurate to the
> second; even a script that added that property once every day or so
> might do the trick.

Check org-expiry.el in Org's contrib directory, it might do what you
want.  (I still need to write a tutorial about this.)

-- 
 Bastien

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
  2009-07-01 10:24     ` David Maus
@ 2009-07-01 11:58       ` Bastien
  2009-07-01 13:26         ` Christopher League
  0 siblings, 1 reply; 7+ messages in thread
From: Bastien @ 2009-07-01 11:58 UTC (permalink / raw)
  To: David Maus; +Cc: Emacs-orgmode

David Maus <maus.david@gmail.com> writes:

> At Wed, 1 Jul 2009 13:40:21 +0530,
> Manish wrote:
>> 
>> There are property and mapping APIs documented in the manual under
>> section on hacking.
>
> 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))
> )
>
> The first function (dmj/assure-creation-property) processes every
> entry in current buffer that match the search query Creation_Time="",
> i.e. entries with an empty or no Creation_Time property at all and
> calls dmj/org-insert-creation-property to insert a Creation_Time
> property with the current time into this entry.

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!

-- 
 Bastien

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
  2009-07-01 11:58       ` Bastien
@ 2009-07-01 13:26         ` Christopher League
  2009-07-01 14:46           ` Bastien
  0 siblings, 1 reply; 7+ messages in thread
From: Christopher League @ 2009-07-01 13:26 UTC (permalink / raw)
  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 <maus.david@gmail.com> 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)))))

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: wish list: sort tasks by age
  2009-07-01 13:26         ` Christopher League
@ 2009-07-01 14:46           ` Bastien
  0 siblings, 0 replies; 7+ messages in thread
From: Bastien @ 2009-07-01 14:46 UTC (permalink / raw)
  To: Christopher League; +Cc: org-mode mailing list

Christopher League <league@contrapunctus.net> writes:

> 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 wrote org-expiry.el a long time ago, it certainly deserves some
rethinking.

-- 
 Bastien

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-07-01 14:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-30 20:04 wish list: sort tasks by age Christopher League
     [not found] ` <87tz1wzy1o.wl%maus.david@gmail.com>
2009-07-01  8:10   ` Manish
2009-07-01 10:24     ` David Maus
2009-07-01 11:58       ` Bastien
2009-07-01 13:26         ` Christopher League
2009-07-01 14:46           ` Bastien
2009-07-01 11:57 ` Bastien

Code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).