emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[O] [PATCH] Support modifiers in effort durations (was: Re: Does Effort


From: Lawrence Mitchell
Subject: [O] [PATCH] Support modifiers in effort durations (was: Re: Does Effort support hours only?)
Date: Mon, 28 Feb 2011 11:43:33 +0000
User-agent: Gnus/5.110012 (No Gnus v0.12) Emacs/24.0.50 (gnu/linux)

Luke Crook wrote:
> Is it possible to specify estimated effort in something other
> than hours (0.5, or 0:30)?

> For example 1w, 1m, 2d etc?

Here's a cleaned up patch that allows user-specified modifiers
for effort strings.  The new variable `org-effort-durations'
lists modifiers, and their mapping to minutes (words, as well as
single-letter modifiers, are supported).  The default value is:

(("h" . 60)
 ("d" . 480) ; 8 hours
 ("w" . 2400) ; five days
 ("m" . 9600) ; 4 weeks
 ("y" . 96000)) ; 40 weeks

But you can change this.

Old effort strings (HH:MM) are still interpreted correctly.  See
the docstrings of `org-effort-durations' and
`org-duration-string-to-minutes' for more details.

>From a0e24b14755eb4087d9c47bb4eea11eb9151efcf Mon Sep 17 00:00:00 2001
From: Lawrence Mitchell <address@hidden>
Date: Fri, 18 Feb 2011 11:01:46 +0000
Subject: [PATCH] Allow human-readable effort durations
To: address@hidden

* lisp/org.el (org-effort-durations): New variable.
* lisp/org.el (org-duration-string-to-minutes): New function.
* lisp/org-agenda.el (org-agenda-filter-effort-form)
(org-format-agenda-item): Use it.
* lisp/org-clock.el (org-clock-notify-once-if-expired)
(org-clock-modify-effort-estimate, org-clock-get-clock-string): Use it.

Specifying large effort durations in hours and minutes is difficult.
Is 130:25 more than two weeks effort?  More than three?  This patch
allows specification of an effort duration as a friendly string.  For
example 2w 5d is two weeks and five days of effort.  Existing H:MM
entries will still be recognised correctly.
---
 lisp/org-agenda.el |    4 ++--
 lisp/org-clock.el  |    8 ++++----
 lisp/org.el        |   41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index dee23e0..87602dc 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -5334,7 +5334,7 @@ Any match of REMOVE-RE will be removed from TXT."
                       (get-text-property 0 'org-marker txt)))
                (error nil)))
        (when effort
-         (setq neffort (org-hh:mm-string-to-minutes effort)
+         (setq neffort (org-duration-string-to-minutes effort)
                effort (setq effort (concat "[" effort "]" )))))
 
       (when remove-re
@@ -6061,7 +6061,7 @@ E looks like \"+<2:25\"."
                   ((equal op ??) op)
                   (t '=)))
     (list 'org-agenda-compare-effort (list 'quote op)
-         (org-hh:mm-string-to-minutes e))))
+         (org-duration-string-to-minutes e))))
 
 (defun org-agenda-compare-effort (op value)
   "Compare the effort of the current line with VALUE, using OP.
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 6b45ca5..cc11f3c 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -487,7 +487,7 @@ If not, show simply the clocked time like 01:50."
         (m (- clocked-time (* 60 h))))
     (if org-clock-effort
        (let* ((effort-in-minutes
-               (org-hh:mm-string-to-minutes org-clock-effort))
+               (org-duration-string-to-minutes org-clock-effort))
               (effort-h (floor effort-in-minutes 60))
               (effort-m (- effort-in-minutes (* effort-h 60)))
               (work-done-str
@@ -561,10 +561,10 @@ the mode line."
        ;; A string.  See if it is a delta
        (setq sign (string-to-char value))
        (if (member sign '(?- ?+))
-          (setq current (org-hh:mm-string-to-minutes current)
+          (setq current (org-duration-string-to-minutes current)
                 value (substring value 1))
         (setq current 0))
-       (setq value (org-hh:mm-string-to-minutes value))
+       (setq value (org-duration-string-to-minutes value))
        (if (equal ?- sign)
           (setq value (- current value))
         (if (equal ?+ sign) (setq value (+ current value)))))
@@ -581,7 +581,7 @@ the mode line."
   "Show notification if we spent more time than we estimated before.
 Notification is shown only once."
   (when (org-clocking-p)
-    (let ((effort-in-minutes (org-hh:mm-string-to-minutes org-clock-effort))
+    (let ((effort-in-minutes (org-duration-string-to-minutes org-clock-effort))
          (clocked-time (org-clock-get-clocked-time)))
       (if (setq org-task-overrun
                (if (or (null effort-in-minutes) (zerop effort-in-minutes))
diff --git a/lisp/org.el b/lisp/org.el
index 03f0b72..9cf1c94 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -15499,6 +15499,47 @@ If no number is found, the return value is 0."
     (string-to-number (match-string 1 s)))
    (t 0)))
 
+(defcustom org-effort-durations
+  `(("h" . 60)
+    ("d" . ,(* 60 8))
+    ("w" . ,(* 60 8 5))
+    ("m" . ,(* 60 8 5 4))
+    ("y" . ,(* 60 8 5 40)))
+  "Conversion factor to minutes for an effort modifier.
+
+Each entry has the form (MODIFIER . MINUTES).
+
+In an effort string, a number followed by MODIFIER is multiplied
+by the specified number of MINUTES to obtain an effort in
+minutes.
+
+For example, if the value of this variable is ((\"hours\" . 60)), then an
+effort string \"2hours\" is equivalent to 120 minutes."
+  :group 'org-agenda
+  :type '(alist :key-type (string :tag "Modifier")
+               :value-type (number :tag "Minutes")))
+
+(defun org-duration-string-to-minutes (s)
+  "Convert a duration string S to minutes.
+
+A bare number is interpreted as minutes, modifiers can be set by
+customizing `org-effort-durations' (which see).
+
+Entries containing a colon are interpreted as H:MM by
+`org-hh:mm-string-to-minutes'."
+  (let ((result 0)
+       (regex (rx-to-string (group (1+ (any "0-9")))
+                            (0+ (syntax whitespace))
+                            (group
+                             (eval (cons 'or
+                                         (mapcar 'car 
org-effort-durations)))))))
+    (while (string-match regex s)
+      (incf result (* (cdr (assoc (match-string 2 s) org-effort-durations))
+                     (string-to-number (match-string 1 s))))
+      (setq s (replace-match "" nil t s)))
+    (incf result (org-hh:mm-string-to-minutes s))
+    result))
+
 ;;;; Files
 
 (defun org-save-all-org-buffers ()
-- 
1.7.4.rc2.18.gb20e9



reply via email to

[Prev in Thread] Current Thread [Next in Thread]