* [PATCH] New org-depend trigger for finding next highest priority/effort item
@ 2011-07-24 18:58 Max Mikhanosha
2011-07-26 11:48 ` Bastien
0 siblings, 1 reply; 10+ messages in thread
From: Max Mikhanosha @ 2011-07-24 18:58 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 581 bytes --]
org-depend TRIGGER chain-siblings(NEXT) property is hardly usable for
me, because it requires too much effort to keep items nicely sorted.
For example if next headline is already in DONE state, chain-siblings
would still change it. I prefer to sort my items by setting their
priorities and/or effort estimate, leaving DONE items in place for
some time.
Attached patch implements new TRIGGER chain-find-next(NEXT[,options])
trigger, which allows to flexibly select which of the siblings will be
changed to NEXT.
Example: chain-find-next(NEXT,from-current,priority-up,todo-only)
[-- Attachment #2: 0011-Add-chain-find-next-trigger-option.patch --]
[-- Type: application/octet-stream, Size: 7711 bytes --]
From 10ac42d25793eedc595641555186321219818cec Mon Sep 17 00:00:00 2001
From: Max Mikhanosha <max@openchat.com>
Date: Sun, 24 Jul 2011 14:44:44 -0400
Subject: [PATCH 11/11] Add chain-find-next trigger option.
---
contrib/lisp/org-depend.el | 142 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 140 insertions(+), 2 deletions(-)
diff --git a/contrib/lisp/org-depend.el b/contrib/lisp/org-depend.el
index 089a6a0..aa8e728 100644
--- a/contrib/lisp/org-depend.el
+++ b/contrib/lisp/org-depend.el
@@ -55,7 +55,43 @@
;; - The sibling also gets the same TRIGGER property
;; "chain-siblings-scheduled", so the chain can continue.
;;
-;; 3) If the TRIGGER property contains any other words like
+;; 3) If the TRIGGER property contains the string
+;; "chain-find-next(KEYWORD[,OPTIONS])", then switching that entry
+;; to DONE do the following:
+;; - All siblings are of the entry are collected into a temporary
+;; list and then filtered and sorted according to OPTIONS
+;; - The first sibling on the list is changed into KEYWORD state
+;; - The sibling also gets the same TRIGGER property
+;; "chain-siblings-scheduled", so the chain can continue.
+;; OPTIONS should be a comma separated string without spaces, and
+;; can contain following options:
+;;
+;; - from-top the candidate list is all of the siblings in
+;; the current subtree
+;;
+;; - from-bottom candidate list are all siblings from bottom up
+;;
+;; - from-current candidate list are all siblings from current item
+;; until end of subtree, then wrapped around from
+;; first sibling
+;;
+;; - no-wrap candidate list are siblings from current one down
+;;
+;; - include-done include siblings with TODO in `org-done-keywords',
+;; they are excluded by default
+;;
+;; - todo-only Only consider siblings that have TODO only, by default
+;; siblings without TODO keyword are considered too
+;;
+;; - priority-up sort by highest priority
+;; - priority-down sort by lowest priority
+;; - effort-up sort by highest effort
+;; - effort-down sort by lowest effort
+;;
+;; Default OPTIONS are from-top
+;;
+;;
+;; 4) If the TRIGGER property contains any other words like
;; XYZ(KEYWORD), these are treated as entry id's with keywords. That
;; means Org-mode will search for an entry with the ID property XYZ
;; and switch that entry to KEYWORD as well.
@@ -121,6 +157,7 @@
;;
(require 'org)
+(require 'cl)
(defcustom org-depend-tag-blocked t
"Whether to indicate blocked TODO items by a special tag."
@@ -143,6 +180,8 @@ copying the sibling spec TRIGGER-VAL to the next sibling."
(org-entry-add-to-multivalued-property
nil "TRIGGER" ,trigger-val))))
+(defvar org-depend-doing-chain-find-next nil)
+
(defun org-depend-trigger-todo (change-plist)
"Trigger new TODO entries after the current is switched to DONE.
This does two different kinds of triggers:
@@ -184,12 +223,111 @@ This does two different kinds of triggers:
;; Go through all the triggers
(while (setq tr (pop triggers))
(cond
+ ((and (not org-depend-doing-chain-find-next)
+ (string-match "\\`chain-find-next(\\b\\(.+?\\)\\b\\(.*\\))\\'" tr))
+ ;; smarter sibling selection
+ ;; keywords
+ ;;
+ ;; include-done => include siblings in DONE todo states
+ ;; todo-only => only todo items, otherwise will consider items without any todo keyword too
+ ;; from-top => candidates siblings are in sequential order
+ ;; from-bottom => candidate siblings are in reverse order
+ ;; from-current => candidate siblings are from current one down
+ ;; no-wrap => used together with from current, stop if reached
+ ;; the end, otherwise it wraps
+ ;; priority-up => use highest priority
+ ;; effort-down => use shortest effort
+ (let* ((org-depend-doing-chain-find-next t)
+ (kwd (match-string 1 tr))
+ (options (match-string 2 tr))
+ (include-done (string-match "include-done" options))
+ (todo-only (string-match "todo-only" options))
+ (from-top (string-match "from-top" options))
+ (from-bottom (string-match "from-bottom" options))
+ (from-current (string-match "from-current" options))
+ (no-wrap (string-match "no-wrap" options))
+ (priority-up (string-match "priority-up" options))
+ (priority-down (string-match "priority-down" options))
+ (effort-up (string-match "effort-up" options))
+ (effort-down (string-match "effort-down" options)))
+ (save-excursion
+ (org-back-to-heading t)
+ (let ((this-item (point)))
+ ;; go up to the parent headline, then advance to next child
+ (org-up-heading-safe)
+ (let ((end (save-excursion (org-end-of-subtree t)
+ (point)))
+ (done nil)
+ (items '()))
+ (outline-next-heading)
+ (while (not done)
+ (if (not (looking-at org-complex-heading-regexp))
+ (setq done t)
+ (let ((todo-kwd (match-string 2))
+ (tags (match-string 5))
+ (priority (org-get-priority (or (match-string 3) "")))
+ (effort (when (or effort-up effort-down)
+ (let ((effort (org-get-effort)))
+ (when effort
+ (org-duration-string-to-minutes effort))))))
+ (push (list (point) todo-kwd priority tags effort)
+ items))
+ (unless (org-goto-sibling)
+ (setq done t))))
+ ;; massage the list according to options
+ (setq items
+ (cond (from-top (nreverse items))
+ (from-bottom items)
+ ((or from-current no-wrap)
+ (let* ((items (nreverse items))
+ (pos (position this-item items :key #'first))
+ (items-before (subseq items 0 pos))
+ (items-after (subseq items pos)))
+ (if no-wrap items-after
+ (append items-after items-before))))
+ (t (nreverse items))))
+ (setq items (remove-if
+ (lambda (item)
+ (or (equal (first item) this-item)
+ (and (not include-done)
+ (member (second item) org-done-keywords))
+ (and todo-only (null (second item)))))
+ items))
+ (setq items
+ (sort
+ items
+ (lambda (item1 item2)
+ (let* ((p1 (third item1))
+ (p2 (third item2))
+ (e1 (fifth item1))
+ (e2 (fifth item2))
+ (p1-lt (< p1 p2))
+ (p1-gt (> p1 p2))
+ (e1-lt (and e1 (or (not e2) (< e1 e2))))
+ (e2-gt (and e2 (or (not e1) (> e1 e2)))))
+ (cond (priority-up
+ (or p1-gt
+ (and (equal p1 p2)
+ (or (and effort-up e1-gt)
+ (and effort-down e1-lt)))))
+ (priority-down
+ (or p1-lt
+ (and (equal p1 p2)
+ (or (and effort-up e1-gt)
+ (and effort-down e1-lt)))))
+ (effort-up
+ (or e1-gt (and (equal e1 e2) p1-gt)))
+ (effort-down
+ (or e1-lt (and (equal e1 e2) p1-gt))))))))
+ (when items
+ (goto-char (first (first items)))
+ (org-entry-add-to-multivalued-property nil "TRIGGER" tr)
+ (org-todo kwd)))))))
((string-match "\\`chain-siblings(\\(.*?\\))\\'" tr)
;; This is a TODO chain of siblings
(setq kwd (match-string 1 tr))
(org-depend-act-on-sibling (format "chain-siblings(%s)" kwd)
(org-todo kwd)))
-
((string-match "\\`\\(\\S-+\\)(\\(.*?\\))\\'" tr)
;; This seems to be ENTRY_ID(KEYWORD)
(setq id (match-string 1 tr)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-24 18:58 [PATCH] New org-depend trigger for finding next highest priority/effort item Max Mikhanosha
@ 2011-07-26 11:48 ` Bastien
2011-07-26 12:52 ` Sebastien Vauban
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Bastien @ 2011-07-26 11:48 UTC (permalink / raw)
To: Max Mikhanosha; +Cc: emacs-orgmode
Hi Max,
Max Mikhanosha <max@openchat.com> writes:
> org-depend TRIGGER chain-siblings(NEXT) property is hardly usable for
> me, because it requires too much effort to keep items nicely sorted.
>
> For example if next headline is already in DONE state, chain-siblings
> would still change it. I prefer to sort my items by setting their
> priorities and/or effort estimate, leaving DONE items in place for
> some time.
>
> Attached patch implements new TRIGGER chain-find-next(NEXT[,options])
> trigger, which allows to flexibly select which of the siblings will be
> changed to NEXT.
Thanks for this!
> Example: chain-find-next(NEXT,from-current,priority-up,todo-only)
>
>
>From 10ac42d25793eedc595641555186321219818cec Mon Sep 17 00:00:00 2001
> From: Max Mikhanosha <max@openchat.com>
> Date: Sun, 24 Jul 2011 14:44:44 -0400
> Subject: [PATCH 11/11] Add chain-find-next trigger option.
>
> ---
> contrib/lisp/org-depend.el | 142 +++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 140 insertions(+), 2 deletions(-)
>
> diff --git a/contrib/lisp/org-depend.el b/contrib/lisp/org-depend.el
> index 089a6a0..aa8e728 100644
> --- a/contrib/lisp/org-depend.el
> +++ b/contrib/lisp/org-depend.el
> @@ -55,7 +55,43 @@
> ;; - The sibling also gets the same TRIGGER property
> ;; "chain-siblings-scheduled", so the chain can continue.
> ;;
> -;; 3) If the TRIGGER property contains any other words like
> +;; 3) If the TRIGGER property contains the string
> +;; "chain-find-next(KEYWORD[,OPTIONS])", then switching that entry
> +;; to DONE do the following:
> +;; - All siblings are of the entry are collected into a temporary
> +;; list and then filtered and sorted according to OPTIONS
> +;; - The first sibling on the list is changed into KEYWORD state
> +;; - The sibling also gets the same TRIGGER property
> +;; "chain-siblings-scheduled", so the chain can continue.
^^^^^^^^^^^^^^^^^^^^^^^^
This should rather be "chain-find-next" here, right?
> +;; OPTIONS should be a comma separated string without spaces, and
> +;; can contain following options:
> +;;
> +;; - from-top the candidate list is all of the siblings in
> +;; the current subtree
> +;;
> +;; - from-bottom candidate list are all siblings from bottom up
> +;;
> +;; - from-current candidate list are all siblings from current item
> +;; until end of subtree, then wrapped around from
> +;; first sibling
> +;;
> +;; - no-wrap candidate list are siblings from current one down
I'm not sure to understand the difference between "from-top" and
"from-current", and between "from-top" and "no-wrap".
Can you give an example?
> +;;
> +;; - include-done include siblings with TODO in `org-done-keywords',
> +;; they are excluded by default
The phrasing is a bit confusing to me -- perhaps removing "they are
excluded by default" is enough.
> +;; - todo-only Only consider siblings that have TODO only, by default
> +;; siblings without TODO keyword are considered too
I suggest this:
"Only consider siblings that have a TODO keyword."
I suppose "todo-only" and "include-done" are compatible, right?
What about using exclusive options like "todo-only" and
"todo-and-done-only"? So that you would need to use only one.
> +;; - priority-up sort by highest priority
> +;; - priority-down sort by lowest priority
> +;; - effort-up sort by highest effort
> +;; - effort-down sort by lowest effort
> +;;
> +;; Default OPTIONS are from-top
> +;;
> +;;
> +;; 4) If the TRIGGER property contains any other words like
> ;; XYZ(KEYWORD), these are treated as entry id's with keywords. That
> ;; means Org-mode will search for an entry with the ID property XYZ
> ;; and switch that entry to KEYWORD as well.
> @@ -121,6 +157,7 @@
> ;;
>
> (require 'org)
> +(require 'cl)
This (eval-when-compile (require 'cl)) -- Emacs has a policy of
preventing (require 'cl) only...
Thanks for further feedback on this! If you can provide a small
Org file where I can test the new functionalities that will help
a lot.
Best,
--
Bastien
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 11:48 ` Bastien
@ 2011-07-26 12:52 ` Sebastien Vauban
2011-07-26 14:59 ` Bastien
2011-07-26 21:56 ` Max Mikhanosha
2011-07-26 23:34 ` Max Mikhanosha
2 siblings, 1 reply; 10+ messages in thread
From: Sebastien Vauban @ 2011-07-26 12:52 UTC (permalink / raw)
To: emacs-orgmode-mXXj517/zsQ
Hi Bastien,
Bastien wrote:
>> +(require 'cl)
>
> This (eval-when-compile (require 'cl)) -- Emacs has a policy of
> preventing (require 'cl) only...
Shouldn't we do that (require cl only) in our custom .emacs files neither?
I do have such for accessing functions like `push'...
Best regards,
Seb
--
Sebastien Vauban
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 12:52 ` Sebastien Vauban
@ 2011-07-26 14:59 ` Bastien
0 siblings, 0 replies; 10+ messages in thread
From: Bastien @ 2011-07-26 14:59 UTC (permalink / raw)
To: Sebastien Vauban; +Cc: emacs-orgmode
"Sebastien Vauban" <wxhgmqzgwmuf@spammotel.com> writes:
> Shouldn't we do that (require cl only) in our custom .emacs files
> neither?
~/.emacs.el is precisely the place where you do what you want :)
--
Bastien
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 11:48 ` Bastien
2011-07-26 12:52 ` Sebastien Vauban
@ 2011-07-26 21:56 ` Max Mikhanosha
2011-07-27 11:33 ` Bastien
2011-07-26 23:34 ` Max Mikhanosha
2 siblings, 1 reply; 10+ messages in thread
From: Max Mikhanosha @ 2011-07-26 21:56 UTC (permalink / raw)
To: Bastien; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 4273 bytes --]
At Tue, 26 Jul 2011 13:48:30 +0200,
Bastien wrote:
>
> > +;; list and then filtered and sorted according to OPTIONS
> > +;; - The first sibling on the list is changed into KEYWORD state
> > +;; - The sibling also gets the same TRIGGER property
> > +;; "chain-siblings-scheduled", so the chain can continue.
>
> This should rather be "chain-find-next" here, right?
Yes thats a typo, I was trying to select a more appropriate name for it.
> > +;; OPTIONS should be a comma separated string without spaces, and
> > +;; can contain following options:
> > +;;
> > +;; - from-top the candidate list is all of the siblings in
> > +;; the current subtree
> > +;;
> > +;; - from-bottom candidate list are all siblings from bottom up
> > +;;
> > +;; - from-current candidate list are all siblings from current item
> > +;; until end of subtree, then wrapped around from
> > +;; first sibling
> > +;;
> > +;; - no-wrap candidate list are siblings from current one down
>
> I'm not sure to understand the difference between "from-top" and
> "from-current", and between "from-top" and "no-wrap".
>
> Can you give an example?
* Parent
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (the one with TRIGGER property)
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
Below are example list of candidates depending on option
from-top => 1,2,3,4,6,7,8
from-bottom => 8,7,6,4,3,2,1
from-current => 6,7,8,1,2,3,4
from-current,no-wrap => 6,7,8
Adding todo-only will eliminate item 7 from all of above, adding
include-done will include item 9.
After inital candidate list is established as above, its sorted by priority
or effort, then 1st item is made NEXT.
> > +;;
> > +;; - include-done include siblings with TODO in `org-done-keywords',
> > +;; they are excluded by default
>
> The phrasing is a bit confusing to me -- perhaps removing "they are
> excluded by default" is enough.
Agree, maybe whole option can be eliminated, I had an opposite option
initially (skip-done), to have default compatible with original
trigger, but decided that skipping done may be a better default.
> > +;; - todo-only Only consider siblings that have TODO only, by default
> > +;; siblings without TODO keyword are considered too
>
> I suggest this:
>
> "Only consider siblings that have a TODO keyword."
>
> I suppose "todo-only" and "include-done" are compatible, right?
todo-only excludes items without any todo keyword, ie plain
headlines. See example above on if item 7 is included or not.
include-done forces items with a DONE/CANCELLEd keyword to be considered
>
> What about using exclusive options like "todo-only" and
> "todo-and-done-only"? So that you would need to use only one.
I'm fine with that, will change.
> >
> > (require 'org)
> > +(require 'cl)
>
> this (eval-when-compile (require 'cl)) -- emacs has a policy of
> preventing (require 'cl) only...
I grepped *.el and saw other file using it without eval-when-compile
(it was htmlize.el i think), so I thought it was ok in contrib. My
worry was that using functions as opposite to macros needs it loaded,
since I use (remove-if) and (position)
But I just tested it on clean file and emacs -Q, and
(eval-when-compile (require 'cl)) and then using 'cl-seq functions
like remove-if seems to works fine.
I'll submit updated patch later today taken above comments inte
consideration. Attached is an org file where you can test various
options
> Thanks for further feedback on this! If you can provide a small
> Org file where I can test the new functionalities that will help
> a lot.
Attached is a test file you can use for all the situation that you
asked clarification for. After testing this file I'm thinking maybe
from-current should be a default instead of from-top. Basically I'm
open to suggestion as to the most sensible default options. I myself
use a hook that auto-inserts TRIGGER line i want when entry becomes
next, maybe such hook should be included into org-depend also? At
least as example?
[-- Attachment #2: org-depend-chain-find-next-test.org --]
[-- Type: application/octet-stream, Size: 2533 bytes --]
* Default
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-top (same as default)
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-top)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-bottom
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-bottom)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current,priority-up
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO [#A] Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,priority-up)
:END:
** TODO Item 6
** Item 7
** TODO [#B] Item 8
** DONE Item 9
* from-current,no-wrap,priority-up
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO [#A] Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,no-wrap,priority-up)
:END:
** TODO Item 6
** Item 7
** TODO [#B] Item 8
** DONE Item 9
* from-current, without todo-only
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current)
:END:
** Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current, with todo-only
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,todo-only)
:END:
** Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current without include-done
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current)
:END:
** DONE Item 6
CLOSED: [2011-07-26 Tue 17:49]
** Item 7
** TODO Item 8
** DONE Item 9
* from-current with include-done
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,include-done)
:END:
** DONE Item 6
CLOSED: [2011-07-26 Tue 17:49]
** Item 7
** TODO Item 8
** DONE Item 9
* end
[-- Attachment #3: Type: text/plain, Size: 3 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 11:48 ` Bastien
2011-07-26 12:52 ` Sebastien Vauban
2011-07-26 21:56 ` Max Mikhanosha
@ 2011-07-26 23:34 ` Max Mikhanosha
2011-07-27 11:33 ` Bastien
2 siblings, 1 reply; 10+ messages in thread
From: Max Mikhanosha @ 2011-07-26 23:34 UTC (permalink / raw)
To: Bastien; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 8122 bytes --]
Amended patch attached, changes:
- use (eval-when-compile) with require 'cl
- changed include-done to todo-and-done-only
- Added defcustom org-depend-find-next-options for default options
which are now: from-current,todo-only,priority-up
- cleaned up documentation
Also attached is updated test file, added #+TODO line since NEXT is
not in default list of keywords.
Content-Disposition: attachment; filename="0011-Add-chain-find-next-trigger-option.patch"][8bit]]
From 6140261b2fe0e15ac36d8222c38790680cd3f9d4 Mon Sep 17 00:00:00 2001
From: Max Mikhanosha <max@openchat.com>
Date: Sun, 24 Jul 2011 14:44:44 -0400
Subject: [PATCH 11/11] Add chain-find-next trigger option.
---
contrib/lisp/org-depend.el | 145 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 143 insertions(+), 2 deletions(-)
diff --git a/contrib/lisp/org-depend.el b/contrib/lisp/org-depend.el
index 089a6a0..77a7c68 100644
--- a/contrib/lisp/org-depend.el
+++ b/contrib/lisp/org-depend.el
@@ -55,7 +55,43 @@
;; - The sibling also gets the same TRIGGER property
;; "chain-siblings-scheduled", so the chain can continue.
;;
-;; 3) If the TRIGGER property contains any other words like
+;; 3) If the TRIGGER property contains the string
+;; "chain-find-next(KEYWORD[,OPTIONS])", then switching that entry
+;; to DONE do the following:
+;; - All siblings are of the entry are collected into a temporary
+;; list and then filtered and sorted according to OPTIONS
+;; - The first sibling on the list is changed into KEYWORD state
+;; - The sibling also gets the same TRIGGER property
+;; "chain-find-next", so the chain can continue.
+;;
+;; OPTIONS should be a comma separated string without spaces, and
+;; can contain following options:
+;;
+;; - from-top the candidate list is all of the siblings in
+;; the current subtree
+;;
+;; - from-bottom candidate list are all siblings from bottom up
+;;
+;; - from-current candidate list are all siblings from current item
+;; until end of subtree, then wrapped around from
+;; first sibling
+;;
+;; - no-wrap candidate list are siblings from current one down
+;;
+;; - todo-only Only consider siblings that have a todo keyword
+;; -
+;; - todo-and-done-only
+;; Same as above but also include done items.
+;;
+;; - priority-up sort by highest priority
+;; - priority-down sort by lowest priority
+;; - effort-up sort by highest effort
+;; - effort-down sort by lowest effort
+;;
+;; Default OPTIONS are from-top
+;;
+;;
+;; 4) If the TRIGGER property contains any other words like
;; XYZ(KEYWORD), these are treated as entry id's with keywords. That
;; means Org-mode will search for an entry with the ID property XYZ
;; and switch that entry to KEYWORD as well.
@@ -121,12 +157,20 @@
;;
(require 'org)
+(eval-when-compile
+ (require 'cl))
(defcustom org-depend-tag-blocked t
"Whether to indicate blocked TODO items by a special tag."
:group 'org
:type 'boolean)
+(defcustom org-depend-find-next-options
+ "from-current,todo-only,priority-up"
+ "Default options for chain-find-next trigger"
+ :group 'org
+ :type 'string)
+
(defmacro org-depend-act-on-sibling (trigger-val &rest rest)
"Perform a set of actions on the next sibling, if it exists,
copying the sibling spec TRIGGER-VAL to the next sibling."
@@ -143,6 +187,8 @@ copying the sibling spec TRIGGER-VAL to the next sibling."
(org-entry-add-to-multivalued-property
nil "TRIGGER" ,trigger-val))))
+(defvar org-depend-doing-chain-find-next nil)
+
(defun org-depend-trigger-todo (change-plist)
"Trigger new TODO entries after the current is switched to DONE.
This does two different kinds of triggers:
@@ -184,12 +230,107 @@ This does two different kinds of triggers:
;; Go through all the triggers
(while (setq tr (pop triggers))
(cond
+ ((and (not org-depend-doing-chain-find-next)
+ (string-match "\\`chain-find-next(\\b\\(.+?\\)\\b\\(.*\\))\\'" tr))
+ ;; smarter sibling selection
+ (let* ((org-depend-doing-chain-find-next t)
+ (kwd (match-string 1 tr))
+ (options (match-string 2 tr))
+ (options (if (or (null options)
+ (equal options ""))
+ org-depend-find-next-options
+ options))
+ (todo-only (string-match "todo-only" options))
+ (todo-and-done-only (string-match "todo-and-done-only"
+ options))
+ (from-top (string-match "from-top" options))
+ (from-bottom (string-match "from-bottom" options))
+ (from-current (string-match "from-current" options))
+ (no-wrap (string-match "no-wrap" options))
+ (priority-up (string-match "priority-up" options))
+ (priority-down (string-match "priority-down" options))
+ (effort-up (string-match "effort-up" options))
+ (effort-down (string-match "effort-down" options)))
+ (save-excursion
+ (org-back-to-heading t)
+ (let ((this-item (point)))
+ ;; go up to the parent headline, then advance to next child
+ (org-up-heading-safe)
+ (let ((end (save-excursion (org-end-of-subtree t)
+ (point)))
+ (done nil)
+ (items '()))
+ (outline-next-heading)
+ (while (not done)
+ (if (not (looking-at org-complex-heading-regexp))
+ (setq done t)
+ (let ((todo-kwd (match-string 2))
+ (tags (match-string 5))
+ (priority (org-get-priority (or (match-string 3) "")))
+ (effort (when (or effort-up effort-down)
+ (let ((effort (org-get-effort)))
+ (when effort
+ (org-duration-string-to-minutes effort))))))
+ (push (list (point) todo-kwd priority tags effort)
+ items))
+ (unless (org-goto-sibling)
+ (setq done t))))
+ ;; massage the list according to options
+ (setq items
+ (cond (from-top (nreverse items))
+ (from-bottom items)
+ ((or from-current no-wrap)
+ (let* ((items (nreverse items))
+ (pos (position this-item items :key #'first))
+ (items-before (subseq items 0 pos))
+ (items-after (subseq items pos)))
+ (if no-wrap items-after
+ (append items-after items-before))))
+ (t (nreverse items))))
+ (setq items (remove-if
+ (lambda (item)
+ (or (equal (first item) this-item)
+ (and (not todo-and-done-only)
+ (member (second item) org-done-keywords))
+ (and (or todo-only
+ todo-and-done-only)
+ (null (second item)))))
+ items))
+ (setq items
+ (sort
+ items
+ (lambda (item1 item2)
+ (let* ((p1 (third item1))
+ (p2 (third item2))
+ (e1 (fifth item1))
+ (e2 (fifth item2))
+ (p1-lt (< p1 p2))
+ (p1-gt (> p1 p2))
+ (e1-lt (and e1 (or (not e2) (< e1 e2))))
+ (e2-gt (and e2 (or (not e1) (> e1 e2)))))
+ (cond (priority-up
+ (or p1-gt
+ (and (equal p1 p2)
+ (or (and effort-up e1-gt)
+ (and effort-down e1-lt)))))
+ (priority-down
+ (or p1-lt
+ (and (equal p1 p2)
+ (or (and effort-up e1-gt)
+ (and effort-down e1-lt)))))
+ (effort-up
+ (or e1-gt (and (equal e1 e2) p1-gt)))
+ (effort-down
+ (or e1-lt (and (equal e1 e2) p1-gt))))))))
+ (when items
+ (goto-char (first (first items)))
+ (org-entry-add-to-multivalued-property nil "TRIGGER" tr)
+ (org-todo kwd)))))))
((string-match "\\`chain-siblings(\\(.*?\\))\\'" tr)
;; This is a TODO chain of siblings
(setq kwd (match-string 1 tr))
(org-depend-act-on-sibling (format "chain-siblings(%s)" kwd)
(org-todo kwd)))
-
((string-match "\\`\\(\\S-+\\)(\\(.*?\\))\\'" tr)
;; This seems to be ENTRY_ID(KEYWORD)
(setq id (match-string 1 tr)
--
1.7.3.4
[-- Attachment #2: Type: text/plain, Size: 1 bytes --]
[-- Attachment #3: org-depend-chain-find-next-test.org --]
[-- Type: application/octet-stream, Size: 2576 bytes --]
#+TODO: TODO NEXT | DONE CANCELED
* Default
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-top (same as default)
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-top)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-bottom
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-bottom)
:END:
** TODO Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current,priority-up
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO [#A] Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,priority-up)
:END:
** TODO Item 6
** Item 7
** TODO [#B] Item 8
** DONE Item 9
* from-current,no-wrap,priority-up
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO [#A] Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,no-wrap,priority-up)
:END:
** TODO Item 6
** Item 7
** TODO [#B] Item 8
** DONE Item 9
* from-current, without todo-only
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current)
:END:
** Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current, with todo-only
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,todo-only)
:END:
** Item 6
** Item 7
** TODO Item 8
** DONE Item 9
* from-current without include-done
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current)
:END:
** DONE Item 6
CLOSED: [2011-07-26 Tue 17:49]
** Item 7
** TODO Item 8
** DONE Item 9
* from-current with include-done
** TODO Item 1
** TODO Item 2
** TODO Item 3
** TODO Item 4
** NEXT Item 5 Current (mark me done)
:PROPERTIES:
:TRIGGER: chain-find-next(NEXT,from-current,todo-and-done-only)
:END:
** DONE Item 6
CLOSED: [2011-07-26 Tue 17:49]
** Item 7
** TODO Item 8
** DONE Item 9
* end
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 21:56 ` Max Mikhanosha
@ 2011-07-27 11:33 ` Bastien
2011-07-27 19:45 ` Max Mikhanosha
0 siblings, 1 reply; 10+ messages in thread
From: Bastien @ 2011-07-27 11:33 UTC (permalink / raw)
To: Max Mikhanosha; +Cc: emacs-orgmode
Hi Max,
Max Mikhanosha <max@openchat.com> writes:
>> Can you give an example?
>
> * Parent
> ** TODO Item 1
> ** TODO Item 2
> ** TODO Item 3
> ** TODO Item 4
> ** NEXT Item 5 Current (the one with TRIGGER property)
> ** TODO Item 6
> ** Item 7
> ** TODO Item 8
> ** DONE Item 9
>
> Below are example list of candidates depending on option
>
> from-top => 1,2,3,4,6,7,8
> from-bottom => 8,7,6,4,3,2,1
> from-current => 6,7,8,1,2,3,4
> from-current,no-wrap => 6,7,8
>
> Adding todo-only will eliminate item 7 from all of above, adding
> include-done will include item 9.
>
> After inital candidate list is established as above, its sorted by priority
> or effort, then 1st item is made NEXT.
Cristal-clear, thanks!
> I grepped *.el and saw other file using it without eval-when-compile
> (it was htmlize.el i think), so I thought it was ok in contrib.
To be clear: it *is* okay in contrib/ as files in contrib/ will not go
to Emacs core. But the more we can avoid this the better.
> Attached is a test file you can use for all the situation that you
> asked clarification for. After testing this file I'm thinking maybe
> from-current should be a default instead of from-top.
Yes, I also think from-current should be the default.
Also, it would be really nice to update this tutorial on Worg and to
show how to use the new feature you introduced:
http://orgmode.org/worg/org-contrib/org-depend.html
Thanks!
--
Bastien
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-26 23:34 ` Max Mikhanosha
@ 2011-07-27 11:33 ` Bastien
0 siblings, 0 replies; 10+ messages in thread
From: Bastien @ 2011-07-27 11:33 UTC (permalink / raw)
To: Max Mikhanosha; +Cc: emacs-orgmode
Hi Max,
Max Mikhanosha <max@openchat.com> writes:
> Amended patch attached, changes:
>
> - use (eval-when-compile) with require 'cl
> - changed include-done to todo-and-done-only
> - Added defcustom org-depend-find-next-options for default options
> which are now: from-current,todo-only,priority-up
> - cleaned up documentation
Great. Applied, thanks for the fast rewrite!
--
Bastien
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-27 11:33 ` Bastien
@ 2011-07-27 19:45 ` Max Mikhanosha
2011-07-28 7:11 ` Bastien
0 siblings, 1 reply; 10+ messages in thread
From: Max Mikhanosha @ 2011-07-27 19:45 UTC (permalink / raw)
To: Bastien; +Cc: emacs-orgmode
At Wed, 27 Jul 2011 13:33:16 +0200,
Bastien wrote:
>
> Also, it would be really nice to update this tutorial on Worg and to
> show how to use the new feature you introduced:
>
> http://orgmode.org/worg/org-contrib/org-depend.html
>
Done, will push once I have permissions
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] New org-depend trigger for finding next highest priority/effort item
2011-07-27 19:45 ` Max Mikhanosha
@ 2011-07-28 7:11 ` Bastien
0 siblings, 0 replies; 10+ messages in thread
From: Bastien @ 2011-07-28 7:11 UTC (permalink / raw)
To: Max Mikhanosha; +Cc: emacs-orgmode
Hi Max,
Max Mikhanosha <max@openchat.com> writes:
> At Wed, 27 Jul 2011 13:33:16 +0200,
> Bastien wrote:
>>
>> Also, it would be really nice to update this tutorial on Worg and to
>> show how to use the new feature you introduced:
>>
>> http://orgmode.org/worg/org-contrib/org-depend.html
>
> Done, will push once I have permissions
Great -- thanks.
The person to contact to get write access to Worg's repo is Matt Lundin,
but if you give me your username on repo.or.cz I can add you now.
Best,
--
Bastien
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-07-28 8:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-24 18:58 [PATCH] New org-depend trigger for finding next highest priority/effort item Max Mikhanosha
2011-07-26 11:48 ` Bastien
2011-07-26 12:52 ` Sebastien Vauban
2011-07-26 14:59 ` Bastien
2011-07-26 21:56 ` Max Mikhanosha
2011-07-27 11:33 ` Bastien
2011-07-27 19:45 ` Max Mikhanosha
2011-07-28 7:11 ` Bastien
2011-07-26 23:34 ` Max Mikhanosha
2011-07-27 11:33 ` Bastien
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).