6

Q: how can I make org-mode warn me when I'm about to schedule a task on top of another task?

I frequently schedule tasks or meetings (with org-deadline or org-schedule) at a specific hour on some day in the distant future. However, I rarely remember what I already have scheduled on that day, and often discover later that I have double-booked a time slot.

Example: I use org-deadline to schedule a meeting for next Thursday from 9am-10am, but already have a preexisting meeting next Thursday from 8:30am-10:30am.

Is there any way, when entering a timestamp/scheduled event/deadline, to have org-mode warn me when I'm about to double-book a timeslot?

4
  • Can you please provide some of your org-todo-keywords, so that I (or another forum participant) can give a precise sample answer? Just the ones used with deadlines and scheduling are sufficient.
    – lawlist
    Nov 29, 2014 at 16:53
  • 1
    @lawlist: nothing fancy: TODO, WORK, DONE. I rarely use the actual keywords, though.
    – Dan
    Nov 29, 2014 at 17:03
  • 1
    (defun example () "Doc-string." (interactive) (goto-char (point-max)) (while (re-search-backward "\\* \\(TODO\\|WORK\\|DONE\\)" nil t) (unless (org-at-heading-p) (org-back-to-heading t)) (let* ( (element (org-element-at-point)) (todo-state (org-element-property :todo-keyword element)) (deadline (ignore-errors (org-element-property :deadline element))) (deadline-time-stamp (ignore-errors (time-to-days (org-time-string-to-time (org-element-property :raw-value deadline))))) (today (time-to-days (current-time))) (title (org-element-property :title element)) ) INSERT-CONDITIONS-HERE )))
    – lawlist
    Nov 29, 2014 at 17:09
  • 1
    I have some other projects that need to get out the door this morning, but will check back later today to see if this issue has been resolved. The above draft example needs a similar section for scheduled. The example illustrates how to extract various values from an org-mode todo entry.
    – lawlist
    Nov 29, 2014 at 17:10

1 Answer 1

3

This example contemplates the existence of the following criteria:

  • A range of time for a particular meeting / appointment is not presently supported. The initial testing has been done with only one start time -- e.g., DEADLINE: <2014-12-01 Mon 08:30> SCHEDULED: <2014-12-01 Mon>

  • "TODO", "WORK" and "DONE" are among some of the org-todo-keywords that have been predefined by the user.

  • Line 21 needs to be modified with the name of the *.org buffer that contains the TODO that need to be checked against for availability. This is the raw *.org file (which must already be in the major-mode org-mode), NOT an *Org Agenda* buffer. In my testing, the *.org buffer is named .todo

  • The example checks both deadlines and scheduled time-stamps.

  • The regexp is looking for just one star to the left of the keyword -- it can be tweaked to be more precise to match the needs of the user.

  • The example assumes the *.org buffer (containing the TODO to be checked against) is already open -- burried or visible will work.

It is certainly possible to get more elaborate by creating a custom org-read-date function that performs the check when manually entering a time-stamp; however, that is beyond the scope of this basic example.

Another idea would be to use the check-availability function following the usage of org-deadline -- i.e., the let-bound variable date-time (in this example) would be set to (org-time-string-to-time org-last-inserted-timestamp).

(defun check-availability (&optional date)
"Doc-string."
(interactive)
  (let* (
      not-available
      (date (if date date (read-string "Date:  ")))
      (date-parsed (parse-time-string date))
      (date-time
        (cond
          ((and
               (not (null (nth 0 date-parsed)))
               (not (null (nth 1 date-parsed)))
               (not (null (nth 2 date-parsed))))
            (date-to-time date))
          ((and
              (null (nth 0 date-parsed))
              (null (nth 1 date-parsed))
              (null (nth 2 date-parsed)))
            (date-to-time (concat date " 00:00")))))
      (date-seconds (time-to-seconds date-time)) )
    (with-current-buffer (get-buffer ".todo")
      (save-excursion
        (goto-char (point-max))
        (catch 'found
          (while (re-search-backward "\\* \\(TODO\\|WORK\\|DONE\\)" nil t)
            (unless (org-at-heading-p)
              (org-back-to-heading t))
            (let* (
                (element (org-element-at-point))
                (deadline (org-element-property :deadline element))
                (deadline-seconds
                  (when deadline
                    (time-to-seconds
                      (org-time-string-to-time
                        (org-element-property :raw-value deadline)))))
                (scheduled (org-element-property :scheduled element))
                (scheduled-seconds
                  (when scheduled
                    (time-to-seconds
                      (org-time-string-to-time
                        (org-element-property :raw-value scheduled))))) )
              (when
                  (or
                    (and
                      deadline-seconds
                      (= date-seconds deadline-seconds))
                    (and
                      scheduled-seconds
                      (= date-seconds scheduled-seconds)))
                (setq not-available t)
                (throw 'found (message "Not Available!")))))))
      (unless not-available 
        (message "Congratulations -- you are available!")))))
3
  • +1. Consider adapting your let statement to follow standard elisp indentation.
    – Malabarba
    Nov 30, 2014 at 9:25
  • Thanks for thoughts -- it gives me a few useful ideas to proceed. It's not yet doing what I had in mind, however, in part because I'm trying to have org-deadline and org-schedule warn me when I'm about to double-book something, while this function would be a separate step to check dates/times in the first place. (That's also a useful bit of functionality I hadn't thought of, by the way!)
    – Dan
    Dec 1, 2014 at 17:30
  • Agreed, this answer is only meant to be a launching point -- i.e., a step in the right direction. It is possible for you to make this very elaborate, including displaying the day calendar in a separate buffer so that you can adjust your schedule (rather than just receive a warning message). org-deadline sets the variable org-last-inserted-timestamp -- that might be an ideal place to introduce your check-availability function -- the let-bound variable date-time (in this example) would be set to (org-time-string-to-time org-last-inserted-timestamp). And, you'll need to add ranges.
    – lawlist
    Dec 1, 2014 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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