From mboxrd@z Thu Jan 1 00:00:00 1970 From: Carsten Dominik Subject: Re: Feature request and patch - blocked TODO to say BLOCKED Date: Fri, 9 Jan 2009 09:16:19 +0100 Message-ID: References: <20090101170227.C707734803@mail2.panix.com> <1131.66.30.178.137.1230850437.squirrel@mail.panix.com> Mime-Version: 1.0 (Apple Message framework v929.2) Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LLCXa-0008MC-9x for emacs-orgmode@gnu.org; Fri, 09 Jan 2009 03:16:26 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LLCXY-0008M0-Tj for emacs-orgmode@gnu.org; Fri, 09 Jan 2009 03:16:25 -0500 Received: from [199.232.76.173] (port=49336 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LLCXY-0008Lx-NM for emacs-orgmode@gnu.org; Fri, 09 Jan 2009 03:16:24 -0500 Received: from mx20.gnu.org ([199.232.41.8]:28613) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LLCXY-0007oQ-5L for emacs-orgmode@gnu.org; Fri, 09 Jan 2009 03:16:24 -0500 Received: from ug-out-1314.google.com ([66.249.92.173]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LLCXX-0001OA-BQ for emacs-orgmode@gnu.org; Fri, 09 Jan 2009 03:16:23 -0500 Received: by ug-out-1314.google.com with SMTP id 36so20202uga.17 for ; Fri, 09 Jan 2009 00:16:21 -0800 (PST) In-Reply-To: <1131.66.30.178.137.1230850437.squirrel@mail.panix.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: "Tom Breton (Tehom)" Cc: emacs-orgmode@gnu.org Hi Tom, I am hesitant to apply this relatively complex patch which I have not had the time to study closely enough. I am wondering: Instead of setting a TODO keyword, would it not be simpler and equally effective to set a special tag when an entry is blocked? You could use a bright font to mark this tag, in order to make it obvious. And you could use a custom query to look for blocked items, to see what can be done about them.... - Carsten On Jan 1, 2009, at 11:53 PM, Tom Breton (Tehom) wrote: > > Motivating incident: I had a todo-type item that contained no tasks > itself, directly, but linked to other tasks. I arranged it this way > in order that those other tasks could be placed neatly in a hierarchy > and not appear as "TODO" in two places. I used the org-depend.el > BLOCKER code to manage this situation. BTW, it works nicely. > > But when a task is blocked, the heading is left with no "TODO" marking > at all. That's not so bad for sibling tasks, because there's one > right above it that says "TODO" (or something). But for distant-link > style tasks, IMO it gives a misleading impression that there is > nothing to do. > > I request the following: > > * Object: One TODO workflow keyword set that relates specially to > "BLOCKER". It would be something like (sequence "BLOCKED" "|" > "UNBLOCKED"). > * Behavior: When a C-c C-t change to a heading is blocked, instead of > doing nothing, mark the heading with the first entry in the > blockage workflow keyword set. > * Behavior: Also do so when there is a blocked C-c C-t change to any > heading whose TODO mark is in a state in the blockage workflow > keyword set. > * Behavior: Ordinarily don't offer the blockage workflow keyword set > for C-c C-t and related commands. > > I append a patch which does this. > > The change mostly affects org.el, because allowing new TODO keywords > requires org.el to know about them, at least in computing some regular > expressions. It was also a lot neater to let org-todo react to > blocked transitions than to try to make `org-depend-block-todo' do it, > which also avoided `org-todo' indirectly calling itself. > > Summary of changes > > Added 3 variables: > * org-todo-use-blockage-keywords-p :: whether to use this > * org-todo-blockage-keywords :: configurable keywords > * org-blockage-keywords-1 :: internal > > Encapsulated part of `org-set-regexps-and-options' as > `org-set-todo-constants'. I had to because it needed to be called > twice, once for normal keywords and once with a flag for blockage > keywords. I used encap-sexp to do it automatically (it's on my site, > http://panix.com/~tehom/my-code/), so no code changed, and I kept that > comment aligned with the regexp. > > Made `org-set-regexps-and-options' also process > `org-todo-blockage-keywords'. > > Changed the behavior of org-todo and org-depend-block-todo as > described > above. > > Tom Breton (Tehom) > > *** org-depend.el 2008-12-18 18:26:05.000000000 -0500 > --- new-org-depend.el 2009-01-01 17:13:13.000000000 -0500 > *************** > *** 196,204 **** > (unless (eq type 'todo-state-change) > ;; We are not handling this kind of change > (throw 'return t)) > ! (unless (and (not from) (member to org-not-done-keywords)) > ! ;; This is not a change from nothing to TODO, ignore it > ! (throw 'return t)) > > ;; OK, the plan is to switch from nothing to TODO > ;; Lets see if we will allow it. Find the BLOCKER property > --- 196,210 ---- > (unless (eq type 'todo-state-change) > ;; We are not handling this kind of change > (throw 'return t)) > ! ;;Act on only the right types of TODO-change: > ! (unless > ! (or > ! ;;A change from a member of the blockage set > ! (member from org-todo-blockage-keywords) > ! ;;A change from nothing to TODO > ! (and (not from) (member to org-not-done-keywords))) > ! ;; Otherwise ignore it > ! (throw 'return t)) > > ;; OK, the plan is to switch from nothing to TODO > ;; Lets see if we will allow it. Find the BLOCKER property > *** old-org.el 2008-12-18 18:26:05.000000000 -0500 > --- org.el 2009-01-01 17:25:32.000000000 -0500 > *************** > *** 1458,1464 **** > (const :tag "Type (cycling directly to DONE)" type)) > (repeat > (string :tag "Keyword")))))) > - > (defvar org-todo-keywords-1 nil > "All TODO and DONE keywords active in a buffer.") > (make-variable-buffer-local 'org-todo-keywords-1) > --- 1458,1463 ---- > *************** > *** 1483,1488 **** > --- 1482,1494 ---- > (make-variable-buffer-local 'org-todo-key-alist) > (defvar org-todo-key-trigger nil) > (make-variable-buffer-local 'org-todo-key-trigger) > + (defvar org-todo-use-blockage-keywords-p t) > + (defvar org-todo-blockage-keywords > + '(sequence "BLOCKED" "|" "UNBLOCKED") > + "Keywords of the blocking workflow keyword set." ) > + (defvar org-blockage-keywords-1 nil > + "All blockage keywords active in a buffer" ) > + (make-variable-buffer-local 'org-blockage-keywords-1) > > (defcustom org-todo-interpretation 'sequence > "Controls how TODO keywords are interpreted. > *************** > *** 2997,3002 **** > --- 3003,3079 ---- > set this variable to if the option is found. An optional forth > element > PUSH > means to push this value onto the list in the variable.") > > + (defun org-set-todo-constants (kwds block) > + "" > + (let > + (inter kws kw) > + (while > + (setq kws (pop kwds)) > + (setq > + inter (pop kws) > + sep (member "|" kws) > + kws0 (delete "|" > + (copy-sequence kws)) > + kwsa nil > + kws1 > + (mapcar > + (lambda > + (x) > + (if > + ;; 1 2 > + (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x) > + (progn > + (setq kw > + (match-string 1 x) > + key > + (and > + (match-end 2) > + (match-string 2 x)) > + log > + (org-extract-log-state-settings x)) > + (push > + (cons kw > + (and key > + (string-to-char key))) > + kwsa) > + (and log > + (push log org-todo-log-states)) > + kw) > + (error "Invalid TODO keyword %s" x))) > + kws0) > + kwsa > + (if kwsa > + (append > + '((:startgroup)) > + (nreverse kwsa) > + '((:endgroup)))) > + hw (car kws1) > + dws (if sep > + (org-remove-keyword-keys > + (cdr sep)) > + (last kws1)) > + tail (list inter hw > + (car dws) > + (org-last dws))) > + (add-to-list 'org-todo-heads hw 'append) > + (push kws1 org-todo-sets) > + (setq org-done-keywords > + (append org-done-keywords dws nil)) > + (setq org-todo-key-alist > + (append org-todo-key-alist kwsa)) > + (mapc > + (lambda > + (x) > + (push > + (cons x tail) > + org-todo-kwd-alist)) > + kws1) > + (if block > + (setq org-blockage-keywords-1 > + (append org-blockage-keywords-1 kws1 nil))) > + (setq org-todo-keywords-1 > + (append org-todo-keywords-1 kws1 nil))))) > + > (defun org-set-regexps-and-options () > "Precompute regular expressions for current buffer." > (when (org-mode-p) > *************** > *** 3116,3156 **** > (setq kwds (list (cons org-todo-interpretation > (default-value 'org-todo-keywords))))) > (setq kwds (reverse kwds))) > ! (setq kwds (nreverse kwds)) > ! (let (inter kws kw) > ! (while (setq kws (pop kwds)) > ! (setq inter (pop kws) sep (member "|" kws) > ! kws0 (delete "|" (copy-sequence kws)) > ! kwsa nil > ! kws1 (mapcar > ! (lambda (x) > ! ;; 1 2 > ! (if (string-match "^\\(.*?\\)\\(?:(\\([^!@/]\\)?.*?)\\)?$" x) > ! (progn > ! (setq kw (match-string 1 x) > ! key (and (match-end 2) (match-string 2 x)) > ! log (org-extract-log-state-settings x)) > ! (push (cons kw (and key (string-to-char key))) kwsa) > ! (and log (push log org-todo-log-states)) > ! kw) > ! (error "Invalid TODO keyword %s" x))) > ! kws0) > ! kwsa (if kwsa (append '((:startgroup)) > ! (nreverse kwsa) > ! '((:endgroup)))) > ! hw (car kws1) > ! dws (if sep (org-remove-keyword-keys (cdr sep)) (last kws1)) > ! tail (list inter hw (car dws) (org-last dws))) > ! (add-to-list 'org-todo-heads hw 'append) > ! (push kws1 org-todo-sets) > ! (setq org-done-keywords (append org-done-keywords dws nil)) > ! (setq org-todo-key-alist (append org-todo-key-alist kwsa)) > ! (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1) > ! (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil))) > ! (setq org-todo-sets (nreverse org-todo-sets) > ! org-todo-kwd-alist (nreverse org-todo-kwd-alist) > ! org-todo-key-trigger (delq nil (mapcar 'cdr org-todo-key- > alist)) > ! org-todo-key-alist (org-assign-fast-keys org-todo-key- > alist))) > ;; Process the constants > (when const > (let (e cst) > --- 3193,3209 ---- > (setq kwds (list (cons org-todo-interpretation > (default-value 'org-todo-keywords))))) > (setq kwds (reverse kwds))) > ! ;;(setq kwds (append (nreverse kwds) (list > org-todo-blockage-keywords))) > ! (org-set-todo-constants (nreverse kwds) nil) > ! (when org-todo-use-blockage-keywords-p > ! (org-set-todo-constants (list org-todo-blockage-keywords) t)) > ! (setq > ! org-todo-sets (nreverse org-todo-sets) > ! org-todo-kwd-alist (nreverse org-todo-kwd-alist) > ! org-todo-key-trigger (delq nil > ! (mapcar 'cdr org-todo-key-alist)) > ! org-todo-key-alist (org-assign-fast-keys org-todo-key-alist)) > ! > ;; Process the constants > (when const > (let (e cst) > *************** > *** 8222,8232 **** > (save-match-data > (run-hook-with-args-until-failure > 'org-blocker-hook change-plist))) > ! (if (interactive-p) > ! (error "TODO state change from %s to %s blocked" this state) > ! ;; fail silently > ! (message "TODO state change from %s to %s blocked" this > state) > ! (throw 'exit nil)))) > (store-match-data match-data) > (replace-match next t t) > (unless (pos-visible-in-window-p hl-pos) > --- 8275,8294 ---- > (save-match-data > (run-hook-with-args-until-failure > 'org-blocker-hook change-plist))) > ! (if > ! org-todo-use-blockage-keywords-p > ! (let > ! ((blocked-state (car org-blockage-keywords-1))) > ! (setq arg 'none) > ! (setq next (concat " " blocked-state " ")) > ! (unless > ! (string= state blocked-state) > ! (message "TODO state change from %s to %s blocked" this > state))) > ! (if (interactive-p) > ! (error "TODO state change from %s to %s blocked" this state) > ! ;; fail silently > ! (message "TODO state change from %s to %s blocked" this state) > ! (throw 'exit nil))))) > (store-match-data match-data) > (replace-match next t t) > (unless (pos-visible-in-window-p hl-pos) > > > > > _______________________________________________ > Emacs-orgmode mailing list > Remember: use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode