Agenda: Add new todo-unblocked and nottodo-unblocked skip conditions
authorToby S. Cubitt <tsc25@cantab.net>
Sat, 28 Jan 2012 17:26:21 +0000 (18:26 +0100)
committerBastien Guerry <bzg@altern.org>
Fri, 20 Apr 2012 10:12:42 +0000 (12:12 +0200)
* lisp/org-agenda.el (org-agenda-skip-if, org-agenda-skip-if-todo):
Add new todo-unblocked and nottodo-unblocked skip conditions.  These
match as for todo and nottodo, but only for unblocked todo items.

TINYCHANGE

This patch adds two new tests to `org-agenda-skip-if': 'todo-unblocked
and 'nottodo-unblocked.  These match like 'todo and 'nottodo, but only on
unblocked todo items.  This type of test is useful when compiling custom
agenda views containing lists of currently actionable todo items.

Whilst it's possible to code such tests in `org-agenda-custom-commands'
directly (well, Elisp is Turing-complete: you can in principle code
anything!), it's far less convenient than a simple `org-agenda-skip-if'
test which can reuse much of the existing machinery.

Note that the attached patch applies on top of my other "Fix
org-agenda-skip-if bug" patch, though this new feature is independent of
that bug-fix.

lisp/org-agenda.el

index 6e4b2f7..ffc27cc 100644 (file)
@@ -4463,15 +4463,18 @@ that can be put into `org-agenda-skip-function' for the duration of a command."
           (not (re-search-forward (nth 1 m) end t)))
       (and (or
            (setq m (memq 'nottodo conditions))
+           (setq m (memq 'todo-unblocked conditions))
+           (setq m (memq 'nottodo-unblocked conditions))
            (setq m (memq 'todo conditions)))
           (org-agenda-skip-if-todo m end)))
      end)))
 
 (defun org-agenda-skip-if-todo (args end)
   "Helper function for `org-agenda-skip-if', do not use it directly.
-ARGS is a list with first element either `todo' or `nottodo'.
-The remainder is either a list of TODO keywords, or a state symbol
-`todo' or `done' or `any'."
+ARGS is a list with first element either `todo', `nottodo',
+`todo-unblocked' or `nottodo-unblocked'. The remainder is either
+a list of TODO keywords, or a state symbol `todo' or `done' or
+`any'."
   (let ((kw (car args))
        (arg (cadr args))
        todo-wds todo-re)
@@ -4495,9 +4498,20 @@ The remainder is either a list of TODO keywords, or a state symbol
          (concat "^\\*+[ \t]+\\<\\("
                  (mapconcat 'identity todo-wds  "\\|")
                  "\\)\\>"))
-    (if (eq kw 'todo)
-       (re-search-forward todo-re end t)
-      (not (re-search-forward todo-re end t)))))
+    (cond
+     ((eq kw 'todo) (re-search-forward todo-re end t))
+     ((eq kw 'nottodo) (not (re-search-forward todo-re end t)))
+     ((eq kw 'todo-unblocked)
+      (catch 'unblocked
+       (while (re-search-forward todo-re end t)
+         (or (org-entry-blocked-p) (throw 'unblocked t)))
+       nil))
+     ((eq kw 'nottodo-unblocked)
+      (catch 'unblocked
+       (while (re-search-forward todo-re end t)
+         (or (org-entry-blocked-p) (throw 'unblocked nil)))
+       t))
+     )))
 
 ;;;###autoload
 (defun org-agenda-list-stuck-projects (&rest ignore)