I organize a technical user group and as part of that I use org-mode to schedule the same task tree every month so I remember to do everything for our meetings (food, speakers, projector, etc.) This, to me, sounds like a perfect use case for a capture template. What I'd like to do is specify an event name and date and have the rest of the tasks automatically calculated based on that. Here's the template I have so far (simplified a bit to show what I want to do):

("m" "Meetup" (file+headline "~/org/STLPython.org" "events")
 "** %^{Event}\n%^{Date}t\n*** Send a reminder to the group\nSCHEDULED: <%<%^{Date}t -5d>>"))

Ideally, I'd get this output, after specifying "Event" and "Date" once each:

** Documenting with Sphinx: Beyond Quickstart
<2015-05-05 Tue>
*** Send a reminder to the group
SCHEDULED: <2015-05-30 Thu>

Instead, I get this output, and I have to specify "Date" twice:

** Documenting with Sphinx: Beyond Quickstart
<2015-05-05 Tue>
*** Send a reminder to the group
Scheduled: <<2015-05-05 Tue> -5d>

So I guess I have two questions:

  1. how can I "reuse" an already captured variable?
  2. how can I modify the date? I saw an answer using %(...) and now can't find it again, and at any rate it didn't seem to accept arguments.

Instead of using the built in templates you can build your own via a function and pass this as the final argument to the capture template. Then you can use arbitrary elisp to manipulate data. Here is an example in your case, that uses org-completing-read-no-i for string prompts and org-read-date for date input. I have updated it to show how to set a schedule on a date 5 days earlier (calculated as 3600 secs times 24 times 5):

(defun my-event-template ()
    "Capture template for events"
  (let* ((event (org-completing-read-no-i "Event: " nil))
         (date-input (org-read-date nil t nil "Date: "))
         (date (format-time-string 
                      (car org-time-stamp-formats)
         (date+shift (concat (substring date 0 -1) " -5d" (substring date -1)))
         (date-schedule (format-time-string (car org-time-stamp-formats)
                                            (time-subtract date-input 
                                                           (seconds-to-time (* 3600 24 5))))))
  (format "** %s\n  %s\n*** Send a reminder to the group\n  DEADLINE: %s SCHEDULED: %s"
   event date date+shift date-schedule)))

     (("m" "Meetup" entry (file+headline "~/org/STLPython.org" "events")
       (function my-event-template))))))

Typical output from this is

** My event
  <2015-03-29 Sun>
*** Send a reminder to the group
  DEADLINE: <2015-03-29 Sun -5d> SCHEDULED: <2015-03-24 Tue>

The object (car org-time-stamp-formats) is the standard format for an active timestamp.

  • nice! How would I actually shift the date though? I want it to be scheduled five days before instead of just a reminder on that day. – Brian Hicks Mar 27 '15 at 18:20
  • 1
    No problem - answer updated now with deadline set as your earlier schedule proposed, and with a relative scheduled date – Andrew Swann Mar 29 '15 at 12:09

Here is my solution to a similar situation. I create a headline for a candidate, which contains a property with today's date, and add a child headline with a deadline two days in the future from today.

Here is the portion of the capture template for the child headline:

*** %\\1                  :waitreply:sentrequest:
     DEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2\"))

It took me longer than I care to admit to figure this out, but I'm happy with the solution. org-read-date with these parameters produces an internal time value, which org-insert-time-stamp converts into a timestamp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.