7

You can use org-agenda-prefix-format to have the effort shown for each TODO headline:

(setq org-agenda-custom-commands
      '(("c" "My TODOs"
         ((tags-todo "mytag"
                     ((org-agenda-prefix-format " %6e ")))))))

Which shows something like:

       TODO Some patent task
[0:30] ..TODO Some sub-task
[0:30] ..TODO Some other sub-task

Unlike a clocktable the effort of the sub-tasks is not summed up for the parent task. I would like it to look like this:

[1:00] TODO Some patent task
[0:30] ..TODO Some sub-task
[0:30] ..TODO Some other sub-task

Looking at the documentation for org-agenda-prefix-format shows nothing similar to %e that also does summing, but there is a generic %(expression), with no explanation.

What %(expression) would give me output like the above?

5

It turns out that %(expression) is not a function which is passed any arguments, but the (point) is set to the current headline as it is processed, so you can write something like:

(org-agenda-prefix-format " %e %(or (org-entry-get (point) "Effort") "0:00") ")

...and the reported effort should agree with %e.

Now, org-entry-get does support searching up the hierarchy if the property is not set on the current item, but what's required is gathering all the properties down the hierarchy, so we can sum up the effort.

Here's a first go:

(defun my-org-entry-get-subtree (property)
  (save-excursion
    (save-restriction
      (org-narrow-to-subtree)
      (goto-char (point-max))
      (save-match-data
        (cl-loop while (re-search-backward org-heading-regexp nil t)
                 collect (org-entry-get (point) property))))))

Which can be used to sum the effort:

(defun my-org-effort-sum-current-item ()
  (org-minutes-to-hh:mm-string
    (cl-loop for minutes in (my-org-entry-get-subtree "Effort")
             sum (org-hh:mm-string-to-minutes (or minutes "0:00")))))

Problem: if you have a TODO with 3 sub-TODOs each with one hour of effort, and the you complete one sub-TODO, the sum remaining effort is 2 hours. But the above code includes the effort from the item in the DONE state, miss-stating 3 hours.

We must match only the items in the subtree which are in the TODO state:

(defun my-org-effort-sum-current-item-in-state (state)
  (org-minutes-to-hh:mm-string
    (cl-loop for minutes in (my-org-entry-subtree-in-state-get state "Effort")
             sum (org-hh:mm-string-to-minutes (or minutes "0:00")))))

(defun my-org-entry-subtree-in-state-get (state property)
  (save-excursion
    (save-restriction
      (org-narrow-to-subtree)
      (goto-char (point-max))
      (save-match-data
        (cl-loop while (re-search-backward org-heading-regexp nil t)
                 when (string-equal state (org-get-todo-state))
                 collect (org-entry-get (point) property))))))

Add this to the org-agenda-prefix-format:

(setq org-agenda-custom-commands
      '(("c" "My TODOs"
         ((tags-todo "mytag"
                     ((org-agenda-prefix-format "[%(my-org-effort-sum-current-item-in-state "TODO")] ")
                      (org-tags-match-list-sublevels t)))))))

...and you end up with something like this:

Projects
[3:00] TODO Some Project Task
[1:00] TODO Sub-task A
[1:00] TODO Sub-task B
[1:00] TODO Sub-task C

(see this other question for how to get the sub-tasks to indent)

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.