diff options
Diffstat (limited to 'org-urgency.el')
-rw-r--r-- | org-urgency.el | 118 |
1 files changed, 97 insertions, 21 deletions
diff --git a/org-urgency.el b/org-urgency.el index 2e0fd53..4e50b87 100644 --- a/org-urgency.el +++ b/org-urgency.el @@ -44,6 +44,14 @@ ;; is of the given state, whereas `org-urgency-by-effort' will multiply the ;; effort of the heading by the number passed, and return that. +;; Note on the values of the N argument to the `org-urgency-by-' functions: + +;; Between two predicate functions, N values of the same order of magnitude +;; will produce urgencies of the same order of magnitude. That is, if you +;; pass an N of 10 to `org-urgency-by-deadline' and an N of 10 to +;; `org-urgency-by-effort', you will get two urgencies of the same order of +;; magnitude. (Any behavior to the contrary is a bug.) + ;;; Code: (require 'org) @@ -104,22 +112,37 @@ H. BODY should evaluate to a number, which will be added to the heading's total urgency, or nil." - (declare (indent 2)) - `(defun ,(intern (format "org-urgency-by-%s" name)) (h ,@args n) - "Weight function for use in `org-urgency-functions'." - (cl-flet ((get (prop) - (org-urgency--get h prop))) - ,@body))) + (declare (indent 2) + (doc-string 3)) + (let ((doc + (when (stringp (car body)) + (pop body)))) + `(defun ,(intern (format "org-urgency-by-%s" name)) (h ,@args n) + ,@(when doc (list doc)) + (cl-flet ((get (prop) + (org-urgency--get h prop))) + ,@body)))) (org-urgency-define priority= (prio) + "Urgency N when H has priority PRIO." (when (= (get 'priority) prio) n)) (org-urgency-define priority () - (* (get 'priority) n)) + "Urgency is H's priority multiplied by N. + +When N is 1, the urgency from this function is equal to the position of +the priority of H in the range between `org-priority-highest' and +`org-priority-lowest'. + +E.g. if H has a priority of [#A] and `org-priority-highest' and +`org-priority-lowest' are ?A and ?C respectively, then when N is 1, H +will have an urgency of 2 according to this function." + (* (/ (get 'priority) 1000) n)) (org-urgency-define scheduled? () + "Urgency N when H is scheduled." (when (org-get-scheduled-time (get 'org-marker)) n)) @@ -130,37 +153,59 @@ total urgency, or nil." n)) (org-urgency-define deadline? () + "Urgency N when H is deadlined." (when (org-get-deadline-time (get 'org-marker)) n)) (org-urgency-define near-deadline () + "Urgency is N times how close H is to its deadline. + +If H has no deadline, this function contributes nothing. + +When N is 1, the urgency from this function is equal to +`org-deadline-warning-days' minus the number of days till H's deadline." (when-let* ((deadline (org-get-deadline-time (get 'org-marker))) - (remaining (float-time + (remaining (time-to-number-of-days (time-subtract deadline (org-current-time)))) (remaining (max remaining 0)) - (maximum (* org-deadline-warning-days 24 60 60)) + (maximum org-deadline-warning-days) (coeff (- maximum remaining))) (* n coeff))) (org-urgency-define tag? (tag) + "Urgency N when H has tag TAG." (when (member tag (get 'tags)) n)) (org-urgency-define habit? () + "Urgency N when H is a habit." (require 'org-habit) (when (org-is-habit-p (get 'org-marker)) n)) (org-urgency-define state? (state) + "Urgency N when H is in TODO state STATE." (when (equal (get 'todo-state) state) n)) (org-urgency-define effort () + "Urgency is the effort of H multiplied by N. + +When N is 1, the urgency from this function is equal to the effort +estimate, in minutes." (* (or (get 'effort-minutes) 60.0) n)) (org-urgency-define random () - (random (concat (format-time-string "%Y %m %d %A ") h)) + "Urgency is a random number between 0 and N. + +The text of H, along with the date of the current agenda is used to seed +the random number. The system PRNG seed is restored after this function +is called." + (random (concat (format-time-string + "%Y %m %d %A " + org-agenda-current-date) + h)) (prog1 (random n) (random t))) @@ -182,16 +227,29 @@ will become (cdr x))) list)) -(defun org-urgency-calculate (h) - "Calculate the urgency of H." +(defun org-urgency-calculate (h &optional keep-names) + "Caluclate the urgencies of H. + +If KEEP-NAMES is nil, simply return the list of urgency numbers. +Otherwise, return a list of pairs of function+arguments and +corresponding urgency number. + +Uses `org-urgency-functions', which see." + (thread-last + org-urgency-functions + (mapcar (lambda (x) + (cl-destructuring-bind (f &rest args) x + (if keep-names + (cons (cons f 'h args) (apply f h args)) + (apply f h args))))) + (seq-remove #'null))) + +(defun org-urgency-total (h) + "Sum the various urgencies of H. + +Urgencies are calculated by `org-urgency-calulate', which see." (if (not (equal (org-urgency--get h 'type) "diary")) - (thread-last - org-urgency-functions - (mapcar (lambda (x) - (cl-destructuring-bind (f &rest args) x - (apply f h args)))) - (seq-remove #'null) - (apply #'+)) + (apply #'+ (org-urgency-calculate h)) 0)) ;;;###autoload @@ -199,11 +257,29 @@ will become "Compare heading A to heading B. This function is suitable as a value for `org-agenda-cmp-user-defined'." - (let ((a (org-urgency-calculate a)) - (b (org-urgency-calculate b))) + (let ((a (org-urgency-total a)) + (b (org-urgency-total b))) (cond ((> a b) +1) ((< a b) -1) (t nil)))) +;;;###autoload +(defun org-urgency-show () + "Show a how the org-urgency rules apply to the current heading." + (interactive nil org-agenda-mode) + (unless (derived-mode-p '(org-agenda-mode)) + (user-error "Must be called in an Org-Agenda mode buffer")) + (message + "%s" + (string-join + (mapcar + (lambda (x) + (format "%S :: %s" + (car x) (cdr x))) + (org-urgency-calculate + (org-current-line-string) + t)) + "\n"))) + (provide 'org-urgency) ;;; org-urgency.el ends here |