emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Displaying deadline datestamp in todo agenda list?
@ 2016-05-23 17:06 Karl Fogel
  2016-05-23 21:53 ` Karl Fogel
  0 siblings, 1 reply; 5+ messages in thread
From: Karl Fogel @ 2016-05-23 17:06 UTC (permalink / raw)
  To: Org Mode

I'm using the DEADLINE keyword with TODO entries, and I'd like the DEADLINE date to be displayed as a datestamp next to each TODO item, when I list deadlined todo items.  In other words, I don't want to have to duplicate the DEADLINE timestamp as a timestamp on the TODO line itself in my Org Mode file -- since the timestamp is already present as the value of the DEADLINE keyword, can't Org Mode just use it?

Assume I have these Org Mode entries:

  * STARTED <2016-05-23> Org Mode scheduling test KIWI.
    DEADLINE: <2016-05-23>

  * TODO <2016-05-25> Org Mode scheduling test MELON.
    DEADLINE: <2016-05-25>

  * STARTED <2016-05-24> Org Mode scheduling test LIME.
    DEADLINE: <2016-05-24>

  * STARTED <2016-06-16> Org Mode scheduling test TARDIGRADE.
    SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16>

And I have this custom code to bind "d" to show just the TODO items that have deadlines, in my `org-agenda' keymap:

  (defun ots-org-entry-skip-non-deadline ()
    "Return non-nil iff this org entry does not have the DEADLINE keyword."
    (if (not (org-entry-get (point) "DEADLINE"))
        (progn (outline-next-heading) (1- (point)))))
  
  (defvar ots-org-agenda-custom-commands-updated-p nil
    "If non-nil, we've already updated `org-agenda-custom-commands',
  so don't do it again.")
  
  ;; TBD: Oh, could use `org-add-agenda-custom-command' to do this.
  (unless ots-org-agenda-custom-commands-updated-p
    (unless (boundp 'org-agenda-custom-commands)
      (setq org-agenda-custom-commands ()))
    (setq org-agenda-custom-commands
          (cons '("d" "Deadlines and scheduled work" alltodo ""
                  ((org-agenda-skip-function 'ots-org-entry-skip-non-deadline)
                   ;; Add code here to control deadline date display?
                   (org-agenda-prefix-format '((agenda . " %i %-12:c%?-12t% s")
                                               (timeline . "  % s")
                                               (todo . " %i %-12:c %s")
                                               (tags . " %i %-12:c")
                                               (search . " %i %-12:c")))
                   (org-agenda-sorting-strategy '(deadline-up))))
                org-agenda-custom-commands))
    (setq ots-org-agenda-custom-commands-updated-p t))

Now if I do `M-x org-agenda' and then type `d', the four items are displayed like this:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:           STARTED   Org Mode scheduling test KIWI.
    OTS:           STARTED   Org Mode scheduling test LIME.
    OTS:           TODO      Org Mode scheduling test MELON.
    OTS:           STARTED   Org Mode scheduling test TARDIGRADE.
  
But what I want is for each to show its corresponding DEADLINE datestamp, say like this:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:         <2016-05-23>  STARTED   Org Mode scheduling test KIWI.
    OTS:         <2016-05-24>  STARTED   Org Mode scheduling test LIME.
    OTS:         <2016-05-25>  TODO      Org Mode scheduling test MELON.
    OTS:         <2016-06-16>  STARTED   Org Mode scheduling test TARDIGRADE.

I haven't found any way to make that happen.  After reading various Info pages, I started digging into the Org Mode code.  Now I'm looking at `org-agenda-get-todos' in org-agenda.el, which calls `org-agenda-format-item', passing "" as the first argument (EXTRA).  The doc string for `org-agenda-format-item' says:

  "EXTRA must be a string to replace the `%s' specifier in the prefix format."

I thought that maybe passing (org-agenda-get-deadlines) there instead of "" would supply `org-agenda-format-item' with the information it needs, but alas, that doesn't work and in fact the third call or so of `org-agenda-get-deadlines' raises an error.  (The doc strings for `org-agenda-get-todos and `org-agenda-get-deadlines' don't say all that much; it's quite possible I'm misunderstanding what the latter is for.)

However, if I pass a hardcoded non-empty value of EXTRA to the call to `org-agenda-format-item', it works.  That is, if I pass the hardcoded string "DEADLINE: <2016-05-24>" as the EXTRA argument in `org-agenda-get-todos', thus changing this line:

  txt (org-agenda-format-item "" txt level category tags t)

to this:

  txt (org-agenda-format-item "FISH" txt level category tags t)

...I get this result:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:         FISH  STARTED   Org Mode scheduling test KIWI.
    OTS:         FISH  STARTED   Org Mode scheduling test LIME.
    OTS:         FISH  TODO      Org Mode scheduling test MELON.
    OTS:         FISH  STARTED   Org Mode scheduling test TARDIGRADE.

Okay, that's roughly what I expected, given that in my custom setting of `org-agenda-custom-commands', I set `org-agenda-prefix-format' so that the `todo' entry's value has "%s" at the end.

So this looks promising.  But now the question is, what is the Right Way to fetch the value of the DEADLINE keyword for the given TODO entry, at that point in the code, so I can pass that instead of "FISH"?  I had thought `org-agenda-get-deadlines' might do it, but that doesn't work.

Or am I going about this all wrong?  Hints welcome.  I hope it's clear what my goal is here, and I think it's a goal that others who use the DEADLINE keyword for TODO items might share.  This would be a great way to manage deadlines, if it worked :-).

Best regards,
-Karl

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

* Re: Displaying deadline datestamp in todo agenda list?
  2016-05-23 17:06 Displaying deadline datestamp in todo agenda list? Karl Fogel
@ 2016-05-23 21:53 ` Karl Fogel
  2016-05-25 17:56   ` Matt Lundin
  2016-05-25 18:33   ` Matt Lundin
  0 siblings, 2 replies; 5+ messages in thread
From: Karl Fogel @ 2016-05-23 21:53 UTC (permalink / raw)
  To: Org Mode

Sigh, sorry.  I messed up one important background fact in my original post, by mistakenly presenting these as the example Org Mode entries I was working with: 

>   * STARTED <2016-05-23> Org Mode scheduling test KIWI.
>     DEADLINE: <2016-05-23>
> 
>   * TODO <2016-05-25> Org Mode scheduling test MELON.
>     DEADLINE: <2016-05-25>
> 
>   * STARTED <2016-05-24> Org Mode scheduling test LIME.
>     DEADLINE: <2016-05-24>
> 
>   * STARTED <2016-06-16> Org Mode scheduling test TARDIGRADE.
>     SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16>

The above is wrong (I copied-and-pasted from a later incarnation that included redundant timestamps).  The block should look like below, i.e., *without* datestamps in the todo headings:

   * STARTED Org Mode scheduling test KIWI.
     DEADLINE: <2016-05-23>
 
   * TODO Org Mode scheduling test MELON.
     DEADLINE: <2016-05-25>
 
   * STARTED Org Mode scheduling test LIME.
     DEADLINE: <2016-05-24>
 
   * STARTED Org Mode scheduling test TARDIGRADE.
     SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16>

The rest of the post is as before, and I'll just reproduce it here (with the mistake corrected) in case it's easier for people to follow up to:

-----------------------------------
Original post, but with correction:
-----------------------------------

I'm using the DEADLINE keyword with TODO entries, and I'd like the DEADLINE date to be displayed as a datestamp next to each TODO item, when I list deadlined todo items.  In other words, I don't want to have to duplicate the DEADLINE timestamp as a timestamp on the TODO line itself in my Org Mode file -- since the timestamp is already present as the value of the DEADLINE keyword, can't Org Mode just use it?

Assume I have these Org Mode entries:

  * STARTED Org Mode scheduling test KIWI.
    DEADLINE: <2016-05-23>

  * TODO Org Mode scheduling test MELON.
    DEADLINE: <2016-05-25>

  * STARTED Org Mode scheduling test LIME.
    DEADLINE: <2016-05-24>

  * STARTED Org Mode scheduling test TARDIGRADE.
    SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16>

And I have this custom code to bind "d" to show just the TODO items that have deadlines, in my `org-agenda' keymap:

  (defun ots-org-entry-skip-non-deadline ()
    "Return non-nil iff this org entry does not have the DEADLINE keyword."
    (if (not (org-entry-get (point) "DEADLINE"))
        (progn (outline-next-heading) (1- (point)))))
  
  (defvar ots-org-agenda-custom-commands-updated-p nil
    "If non-nil, we've already updated `org-agenda-custom-commands',
  so don't do it again.")
  
  ;; TBD: Oh, could use `org-add-agenda-custom-command' to do this.
  (unless ots-org-agenda-custom-commands-updated-p
    (unless (boundp 'org-agenda-custom-commands)
      (setq org-agenda-custom-commands ()))
    (setq org-agenda-custom-commands
          (cons '("d" "Deadlines and scheduled work" alltodo ""
                  ((org-agenda-skip-function 'ots-org-entry-skip-non-deadline)
                   ;; Add code here to control deadline date display?
                   (org-agenda-prefix-format '((agenda . " %i %-12:c%?-12t% s")
                                               (timeline . "  % s")
                                               (todo . " %i %-12:c %s")
                                               (tags . " %i %-12:c")
                                               (search . " %i %-12:c")))
                   (org-agenda-sorting-strategy '(deadline-up))))
                org-agenda-custom-commands))
    (setq ots-org-agenda-custom-commands-updated-p t))

Now if I do `M-x org-agenda' and then type `d', the four items are displayed like this:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:           STARTED   Org Mode scheduling test KIWI.
    OTS:           STARTED   Org Mode scheduling test LIME.
    OTS:           TODO      Org Mode scheduling test MELON.
    OTS:           STARTED   Org Mode scheduling test TARDIGRADE.
  
But what I want is for each to show its corresponding DEADLINE datestamp, say like this:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:         <2016-05-23>  STARTED   Org Mode scheduling test KIWI.
    OTS:         <2016-05-24>  STARTED   Org Mode scheduling test LIME.
    OTS:         <2016-05-25>  TODO      Org Mode scheduling test MELON.
    OTS:         <2016-06-16>  STARTED   Org Mode scheduling test TARDIGRADE.

I haven't found any way to make that happen.  After reading various Info pages, I started digging into the Org Mode code.  Now I'm looking at `org-agenda-get-todos' in org-agenda.el, which calls `org-agenda-format-item', passing "" as the first argument (EXTRA).  The doc string for `org-agenda-format-item' says:

  "EXTRA must be a string to replace the `%s' specifier in the prefix format."

I thought that maybe passing (org-agenda-get-deadlines) there instead of "" would supply `org-agenda-format-item' with the information it needs, but alas, that doesn't work and in fact the third call or so of `org-agenda-get-deadlines' raises an error.  (The doc strings for `org-agenda-get-todos and `org-agenda-get-deadlines' don't say all that much; it's quite possible I'm misunderstanding what the latter is for.)

However, if I pass a hardcoded non-empty value of EXTRA to the call to `org-agenda-format-item', it works.  That is, if I pass the hardcoded string "DEADLINE: <2016-05-24>" as the EXTRA argument in `org-agenda-get-todos', thus changing this line:

  txt (org-agenda-format-item "" txt level category tags t)

to this:

  txt (org-agenda-format-item "FISH" txt level category tags t)

...I get this result:

  Global list of TODO items of type: ALL
  Available with ‘N r’: (0)[ALL] (1)TODO (2)STARTED (3)DONE
    OTS:         FISH  STARTED   Org Mode scheduling test KIWI.
    OTS:         FISH  STARTED   Org Mode scheduling test LIME.
    OTS:         FISH  TODO      Org Mode scheduling test MELON.
    OTS:         FISH  STARTED   Org Mode scheduling test TARDIGRADE.

Okay, that's roughly what I expected, given that in my custom setting of `org-agenda-custom-commands', I set `org-agenda-prefix-format' so that the `todo' entry's value has "%s" at the end.

So this looks promising.  But now the question is, what is the Right Way to fetch the value of the DEADLINE keyword for the given TODO entry, at that point in the code, so I can pass that instead of "FISH"?  I had thought `org-agenda-get-deadlines' might do it, but that doesn't work.

Or am I going about this all wrong?  Hints welcome.  I hope it's clear what my goal is here, and I think it's a goal that others who use the DEADLINE keyword for TODO items might share.  This would be a great way to manage deadlines, if it worked :-).

Best regards,
-Karl

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

* Re: Displaying deadline datestamp in todo agenda list?
  2016-05-23 21:53 ` Karl Fogel
@ 2016-05-25 17:56   ` Matt Lundin
  2016-05-25 18:33   ` Matt Lundin
  1 sibling, 0 replies; 5+ messages in thread
From: Matt Lundin @ 2016-05-25 17:56 UTC (permalink / raw)
  To: Karl Fogel; +Cc: Org Mode

Karl Fogel <kfogel@red-bean.com> writes:
> 
> I'm using the DEADLINE keyword with TODO entries, and I'd like 
> the DEADLINE date to be displayed as a datestamp next to each 
> TODO item, when I list deadlined todo items. In other words, I 
> don't want to have to duplicate the DEADLINE timestamp as a 
> timestamp on the TODO line itself in my Org Mode file -- since 
> the timestamp is already present as the value of the DEADLINE 
> keyword, can't Org Mode just use it? 
> 
> Assume I have these Org Mode entries: 
> 
>   * STARTED Org Mode scheduling test KIWI. 
>     DEADLINE: <2016-05-23> 
> 
>   * TODO Org Mode scheduling test MELON. 
>     DEADLINE: <2016-05-25> 
> 
>   * STARTED Org Mode scheduling test LIME. 
>     DEADLINE: <2016-05-24> 
> 
>   * STARTED Org Mode scheduling test TARDIGRADE. 
>     SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16> 
> 
> And I have this custom code to bind "d" to show just the TODO 
> items that have deadlines, in my `org-agenda' keymap: 
> 
>   (defun ots-org-entry-skip-non-deadline () 
>     "Return non-nil iff this org entry does not have the 
>     DEADLINE keyword."  (if (not (org-entry-get (point) 
>     "DEADLINE")) 
>         (progn (outline-next-heading) (1- (point))))) 
>    (defvar ots-org-agenda-custom-commands-updated-p nil 
>     "If non-nil, we've already updated 
>     `org-agenda-custom-commands', 
>   so don't do it again.")   ;; TBD: Oh, could use 
>   `org-add-agenda-custom-command' to do this.  (unless 
>   ots-org-agenda-custom-commands-updated-p 
>     (unless (boundp 'org-agenda-custom-commands) 
>       (setq org-agenda-custom-commands ())) 
>     (setq org-agenda-custom-commands 
>           (cons '("d" "Deadlines and scheduled work" alltodo "" 
>                   ((org-agenda-skip-function 
>                   'ots-org-entry-skip-non-deadline) 
>                    ;; Add code here to control deadline date 
>                    display?  (org-agenda-prefix-format '((agenda 
>                    . " %i %-12:c%?-12t% s") 
>                                                (timeline . "  % 
>                                                s") (todo . " %i 
>                                                %-12:c %s") (tags 
>                                                . " %i %-12:c") 
>                                                (search . " %i 
>                                                %-12:c"))) 
>                    (org-agenda-sorting-strategy 
>                    '(deadline-up)))) 
>                 org-agenda-custom-commands)) 
>     (setq ots-org-agenda-custom-commands-updated-p t)) 
> 

Hi Karl,

Here's a working implementation, using 
org-agenda-add-custom-command and the built-in mechanism for 
skipping non-deadline entries (you can get rid of 
ots-org-entry-skip-non-deadline). I also added some justification 
(the -22) to accommodate my rather long timestamp strings. Adjust 
as needed:

(org-add-agenda-custom-command 
 '("d" "Deadlines and scheduled work" alltodo "" 
         ((org-agenda-skip-function '(org-agenda-skip-entry-if 
         'notdeadline)) 
          (org-agenda-prefix-format '((todo . " %i 
          %-22(org-entry-get nil \"DEADLINE\") %-12:c %s"))) 
          (org-agenda-sorting-strategy '(deadline-up)))))

Matt

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

* Re: Displaying deadline datestamp in todo agenda list?
  2016-05-23 21:53 ` Karl Fogel
  2016-05-25 17:56   ` Matt Lundin
@ 2016-05-25 18:33   ` Matt Lundin
  2016-05-25 23:23     ` Karl Fogel
  1 sibling, 1 reply; 5+ messages in thread
From: Matt Lundin @ 2016-05-25 18:33 UTC (permalink / raw)
  To: Karl Fogel; +Cc: Org Mode

Karl Fogel <kfogel@red-bean.com> writes:

> I'm using the DEADLINE keyword with TODO entries, and I'd like the
> DEADLINE date to be displayed as a datestamp next to each TODO item,
> when I list deadlined todo items. In other words, I don't want to have
> to duplicate the DEADLINE timestamp as a timestamp on the TODO line
> itself in my Org Mode file -- since the timestamp is already present
> as the value of the DEADLINE keyword, can't Org Mode just use it?
>
> Assume I have these Org Mode entries:
>
>   * STARTED Org Mode scheduling test KIWI.
>     DEADLINE: <2016-05-23>
>
>   * TODO Org Mode scheduling test MELON.
>     DEADLINE: <2016-05-25>
>
>   * STARTED Org Mode scheduling test LIME.
>     DEADLINE: <2016-05-24>
>
>   * STARTED Org Mode scheduling test TARDIGRADE.
>     SCHEDULED: <2016-05-23> DEADLINE: <2016-06-16>
>
> And I have this custom code to bind "d" to show just the TODO items that have deadlines, in my `org-agenda' keymap:
>
>   (defun ots-org-entry-skip-non-deadline ()
>     "Return non-nil iff this org entry does not have the DEADLINE keyword."
>     (if (not (org-entry-get (point) "DEADLINE"))
>         (progn (outline-next-heading) (1- (point)))))
>   
>   (defvar ots-org-agenda-custom-commands-updated-p nil
>     "If non-nil, we've already updated `org-agenda-custom-commands',
>   so don't do it again.")
>   
>   ;; TBD: Oh, could use `org-add-agenda-custom-command' to do this.
>   (unless ots-org-agenda-custom-commands-updated-p
>     (unless (boundp 'org-agenda-custom-commands)
>       (setq org-agenda-custom-commands ()))
>     (setq org-agenda-custom-commands
>           (cons '("d" "Deadlines and scheduled work" alltodo ""
>                   ((org-agenda-skip-function 'ots-org-entry-skip-non-deadline)
>                    ;; Add code here to control deadline date display?
>                    (org-agenda-prefix-format '((agenda . " %i %-12:c%?-12t% s")
>                                                (timeline . "  % s")
>                                                (todo . " %i %-12:c %s")
>                                                (tags . " %i %-12:c")
>                                                (search . " %i %-12:c")))
>                    (org-agenda-sorting-strategy '(deadline-up))))
>                 org-agenda-custom-commands))
>     (setq ots-org-agenda-custom-commands-updated-p t))
>

[My apologies for the previous email: I accidentally had format=flowed
enabled.]

Here's a working implementation, using org-agenda-add-custom-command and
the built-in mechanism for skipping non-deadline entries (you can get
rid of ots-org-entry-skip-non-deadline). I also added some justification
(the -22) to accommodate my rather long timestamp strings. Adjust as
needed:

(org-add-agenda-custom-command
 '("d" "Deadlines and scheduled work" alltodo ""
   ((org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline))
    (org-agenda-prefix-format '((todo . " %i %-22(org-entry-get nil \"DEADLINE\") %-12:c %s")))
    (org-agenda-sorting-strategy '(deadline-up)))))

Matt

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

* Re: Displaying deadline datestamp in todo agenda list?
  2016-05-25 18:33   ` Matt Lundin
@ 2016-05-25 23:23     ` Karl Fogel
  0 siblings, 0 replies; 5+ messages in thread
From: Karl Fogel @ 2016-05-25 23:23 UTC (permalink / raw)
  To: Org Mode; +Cc: Matt Lundin

Matt Lundin <mdl@imapmail.org> writes:
>Here's a working implementation, using org-agenda-add-custom-command and
>the built-in mechanism for skipping non-deadline entries (you can get
>rid of ots-org-entry-skip-non-deadline). I also added some justification
>(the -22) to accommodate my rather long timestamp strings. Adjust as
>needed:
>
>(org-add-agenda-custom-command
> '("d" "Deadlines and scheduled work" alltodo ""
>   ((org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline))
>    (org-agenda-prefix-format '((todo . " %i %-22(org-entry-get nil \"DEADLINE\") %-12:c %s")))
>    (org-agenda-sorting-strategy '(deadline-up)))))
>
>Matt

Matt, I can't thank you enough -- this is great.  (Our company runs on Org Mode, so this will help more free software hackers than just me :-) .)

The core trick is obviously "(org-entry-get nil \"DEADLINE\")".  I knew about embedding a Lisp expression into the format string, but didn't know about that particular function -- now that I know it exists, I suspect we'll be using it a lot.  And the "(org-agenda-skip-entry-if 'notdeadline)" part saves us a bunch of custom code too.

This is the best kind of solution: it solved the immediate problem and gives us infrastructure for solving future problems as well.

Thanks!

-Karl

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

end of thread, other threads:[~2016-05-25 23:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-23 17:06 Displaying deadline datestamp in todo agenda list? Karl Fogel
2016-05-23 21:53 ` Karl Fogel
2016-05-25 17:56   ` Matt Lundin
2016-05-25 18:33   ` Matt Lundin
2016-05-25 23:23     ` Karl Fogel

Code repositories for project(s) associated with this public 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).