The first function works when executed on or in the body of an org headline. The second function doesn't return anything even though more than one headline in my set of agenda files has the org properties noted in the doc string to the first function. Perhaps I should use org-element-map instead? Please help me get this working:
(require 's) ; s.el string library for s-split
(defun my-org-task-schedule-warn-func ()
"Use org properties such as
:PROPERTIES:
:COMPLETE-BEFORE: <2016-04-19 Tue 19:55>
:Effort: 1:00
:END:
on an org headline to generate scheduling warnings, ala Watership Planner."
;; Only match headlines with the COMPLETE-BEFORE and EFFORT properties.
(if (and (assoc "COMPLETE-BEFORE" (org-entry-properties))
(assoc "EFFORT" (org-entry-properties)))
(let* ((props (org-entry-properties)) ; Get the properties for the
; current headline.
(complete-before-string
(cdr (assoc "COMPLETE-BEFORE" props)))
(complete-before
(org-read-date nil t
complete-before-string nil))
(effort-string
(cdr (assoc "EFFORT" props))) ; Using h:mm format.
(effort-string-components (s-split ":" effort-string))
(effort-hours (string-to-int (first effort-string-components)))
;; Turn org-mode effort format into minutes.
(effort-minutes
(+ (* effort-hours 60)
(string-to-int (second effort-string-components))))
(time-buffer-minutes 15) ; Amount of warning time (in minutes) within
; which to start notifying user that
; they might not meet their scheduling
; objective. This would ideally be a
; customizable value.
(current-time-plus-effort
(time-add (current-time)
(seconds-to-time (* effort-minutes 60))))
(current-time-plus-effort-plus-buffer
(time-add
current-time-plus-effort
(seconds-to-time (* time-buffer-minutes 60)))))
(print (current-time-string complete-before))
(print (current-time-string current-time-plus-effort-plus-buffer))
(if (time-less-p complete-before current-time-plus-effort-plus-buffer)
(progn
(let ((msg (nth 4 (org-heading-components))))
(print
(concat
"Warning! You are in danger of not completing the task titled: "
msg))
(if (fboundp 'my-org-task-schedule-warn)
;; Pop up an OS X notifier window with msg and play warning sound
(my-org-task-schedule-warn
"Schedule warning for task:"
msg))))
(print "You are still ok.")))))
;;; TODO: It'd be nice to set the MATCH to only those headlines with
;;; the COMPLETE-BEFORE and EFFORT properties at the level of
;;; org-map-entries instead of inside my-org-task-schedule-warn.
(defun my-org-check-schedule-warnings ()
(org-map-entries
(my-org-task-schedule-warn-func) nil 'agenda))
UPDATE: Responding to @lawlist's request below, for the curious, I can say this is just a germinal idea toward implementing a small bit of functionality available in the Windows scheduling app named 'Watership Planner'. It doesn't compete with org agenda or any other features of org. Watership Planner has this nice feature (for my purposes - especially with org habits) whereby you can say that you want to complete a task before a certain time of day. WP looks at the duration you have specified for the task and if the current time is such that you are getting close to running out of time to start the task in order to finish by the completion time then it will warn you with a notification and sound. It is sort of like having a personal scheduling assistant since you don't specify exactly when you want to do something, just a window of time on a given day and the WP agent notifies you when your window is elapsing without completion. The first hack I have here does just that but it doesn't work like Watership Planner's version of this feature yet. If you are still curious, you can download Watership Planner demo and run it for free to see what I am talking about. Again, it is only this feature that I am exploring, not other aspects of Watership Planner, many of which would be redundant with org mode.
org-map-entries
to create something like the*Org Agenda*
buffer or to extract the raw data that is used to create that buffer or similar calendar buffers such ascalfw
: emacs.stackexchange.com/a/12563/2287 I understand you want to have something to do with setting alarms and so forth, but I'd rather not guess.my-org-task-schedule-warn-func
does not return a function. Therefore I assume that you should replace(my-org-task-schedule-warn-func)
inmy-org-check-shedule-warnings
with#'my-org-task-schedule-warn-func
(note the function-quote).s-split
.s-split
is just a wrapper forsplit-string
. So, see the help forsplit-string
and simplify the example by usingsplit-string
and removing(require 's)
.org-map-entries
with function argument. So I wrote an answer anyway and formulated it as clear as possible.