1 #+TITLE: org-depend.el -- TODO dependencies for Org-mode
2 #+OPTIONS: ^:{} author:nil
5 # This file is released by its authors and contributors under the GNU
6 # Free Documentation license v1.3 or later, code examples are released
7 # under the GNU General Public License v3 or later.
11 /org-depend.el/ demonstrates a mechanism for creating TODO
12 dependencies. Note that Org-mode does already have [[https://orgmode.org/manual/TODO-dependencies.html#TODO-dependencies][built-in local
13 dependencies]] which are simpler and cover most of what one usually
14 wants to do. However, the built-in implementation covers only the
15 following two concepts:
17 - blocking an entry from changing its state to DONE while it still has
18 children that are not done, or checkboxes that are unchecked
19 - blocking an entry from changing its state to DONE while it still has
20 un-done siblings above it, in this way enforcing sequential work on
23 /org-depend.el/ was originally a proof-of-concept implementation of
24 TODO dependencies, using two special hooks, =org-blocker-hook= and
25 =org-trigger-hook=. It remains in the distribution as an example on
26 how more complex dependencies between entries can be implemented. In
27 particular it shows how to implement the following:
29 - Dependencies on remote entries identified by ID. These entries do
30 not have to be near-by and may even be located in a different file.
31 - The possibility to /trigger/ actions in other entries.
33 * What is implemented?
37 1) If an entry contains a TRIGGER property that contains the string
38 =chain-siblings(KEYWORD)=, then switching that entry to DONE does
40 - The sibling following this entry switched to todo-state KEYWORD.
41 - The sibling also gets a TRIGGER property =chain-sibling(KEYWORD)=,
42 property, to make sure that, when *it* is DONE, the chain will
45 2) If an entry contains a TRIGGER property that contains the string
46 =chain-siblings-scheduled=, then switching that entry to DONE does
47 the following actions, similarly to =chain-siblings(KEYWORD)=:
48 - The sibling receives the same scheduled time as the entry
49 marked as DONE (or, in the case, in which there is no scheduled
50 time, the sibling does not get any either).
51 - The sibling also gets the same TRIGGER property
52 =chain-siblings-scheduled=, so the chain can continue.
54 3) If the TRIGGER property contains the string
55 =chain-find-next(KEYWORD[,OPTIONS])=, then switching that entry
56 to DONE do the following:
57 - All siblings are of the entry are collected into a temporary
58 list and then filtered and sorted according to =OPTIONS=
59 - The first sibling on the list is changed into =KEYWORD= state
60 - The sibling also gets the same TRIGGER property
61 =chain-find-next=, so the chain can continue.
63 OPTIONS should be a comma separated string without spaces, and can
64 contain following options:
66 - =from-top= the candidate list is all of the siblings in the
68 - =from-bottom= candidate list are all siblings from bottom up
69 - =from-current= candidate list are all siblings from current item
70 until end of subtree, then wrapped around from first sibling
71 - =no-wrap= candidate list are siblings from current one down
72 - =todo-only= Only consider siblings that have a todo keyword
73 - =todo-and-done-only= Same as above but also include done items.
74 - =priority-up= sort by highest priority
75 - =priority-down= sort by lowest priority
76 - =effort-up= sort by highest effort
77 - =effort-down= sort by lowest effort
79 There is also customizable variable =org-depend-find-next-options=
80 that contains default options if none are specified. Its default
81 value is =from-current,todo-only,priority-up=
83 4) If the TRIGGER property contains any other words like
84 =XYZ(KEYWORD)=, these are treated as entry IDs with keywords.
85 That means, Org-mode will search for an entry with the ID property
86 XYZ and switch that entry to KEYWORD as well.
90 1) If an entry contains a BLOCKER property that contains the word
91 =previous-sibling=, the sibling above the current entry is
92 checked when you try to mark it DONE. If it is still in a TODO
93 state, the current state change is blocked.
95 2) If the BLOCKER property contains any other words, these are
96 treated as entry IDs. That means, Org-mode will search for an
97 entry with the ID property exactly equal to this word. If any
98 of these entries is not yet marked DONE, the current state change
101 3) Whenever a state change is blocked, an org-mark is pushed, so that
102 you can find the offending entry with =C-c &=.
106 When trying this example, make sure that the settings for TODO keywords
107 have been activated, i.e. include the following line and press C-c C-c
108 on the line before working with the example:
111 #+TYP_TODO: TODO NEXT | DONE
114 OK, here is the example.
117 ,* TODO Win a million in Las Vegas
119 :ID: I-cannot-do-it-without-money
122 The "third" TODO (see above) cannot become a TODO without this money.
125 ,* Do this by doing a chain of TODOs
126 ,** NEXT This is the first in this chain
128 :TRIGGER: chain-siblings(NEXT)
131 ,** This is the second in this chain
133 ,** This is the third in this chain
135 :BLOCKER: I-cannot-do-it-without-money
138 ,** This is the forth in this chain
140 :TRIGGER: XYZ-is-my-id(TODO)
143 When this is DONE, we will also trigger entry XYZ-is-my-id
145 ,** This is the fifth in this chain
147 ,* Start writing report
153 * Advanced Triggerring Example
155 In advanced example we will add a hook to automatically insert
156 =chain-find-next= TRIGGER when entry is changed to NEXT and
157 automatically remove it otherwise.
159 First evaluate the following lisp code:
161 #+begin_src emacs-lisp
162 (defun mm/org-insert-trigger ()
163 "Automatically insert chain-find-next trigger when entry becomes NEXT"
164 (cond ((equal org-state "NEXT")
165 (unless org-depend-doing-chain-find-next
166 (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-down)")))
167 ((not (member org-state org-done-keywords))
168 (org-delete-property "TRIGGER"))))
170 (add-hook 'org-after-todo-state-change-hook 'mm/org-insert-trigger)
173 Now in the following org file, try changing item TODO state to
174 NEXT. You should see properties drawer appear with the TRIGGER
177 Try marking the NEXT item DONE. The next item should automatically
180 Change priority of one of the items to =[#A]=, then mark the NEXT item
181 DONE. The highest priority item will automatically become NEXT.
184 #+TYP_TODO: TODO NEXT | DONE
187 ,** TODO Make me NEXT, then mark me DONE
191 ,** TODO Change my priority
196 [[http://karl-voit.at/2016/12/18/org-depend/][Here is a blog article]] that shows the usage of org-depend in
197 combination with [[https://github.com/joaotavora/yasnippet][yasnipet]] or [[https://github.com/Kungsgeten/yankpad][yankpad]].
199 An advanced workflow with dependencies is auto-generated from a
200 template snippet using the =BLOCKER= and =TRIGGER= keywords.
202 Some of those things were demonstrated in [[http://karl-voit.at/2014/12/03/emacs-chat/][an Emacs Chat by Sacha Chua
205 [[http://karl-voit.at/2016/12/18/org-depend/][The blog article]] further discusses some ideas on how to improve the
206 =org-depend= functionality with an ID picker, a mnemonic ID
207 auto-generator, a workflow assistent, advanced =TRIGGER= commands to
208 add scheduled dates, and inheritance of todo-cancelation.