org: Special agenda views

 
 A.8 Special agenda views
 ========================
 
 Org provides a special hook that can be used to narrow down the
 selection made by these agenda views: ‘agenda’, ‘agenda*’(1), ‘todo’,
 ‘alltodo’, ‘tags’, ‘tags-todo’, ‘tags-tree’.  You may specify a function
 that is used at each match to verify if the match should indeed be part
 of the agenda view, and if not, how much should be skipped.  You can
 specify a global condition that will be applied to all agenda views,
 this condition would be stored in the variable
 ‘org-agenda-skip-function-global’.  More commonly, such a definition is
 applied only to specific custom searches, using
 ‘org-agenda-skip-function’.
 
    Let’s say you want to produce a list of projects that contain a
 WAITING tag anywhere in the project tree.  Let’s further assume that you
 have marked all tree headings that define a project with the TODO
 keyword PROJECT.  In this case you would run a TODO search for the
 keyword PROJECT, but skip the match unless there is a WAITING tag
 anywhere in the subtree belonging to the project line.
 
    To achieve this, you must write a function that searches the subtree
 for the tag.  If the tag is found, the function must return ‘nil’ to
 indicate that this match should not be skipped.  If there is no such
 tag, return the location of the end of the subtree, to indicate that
 search should continue from there.
 
      (defun my-skip-unless-waiting ()
        "Skip trees that are not waiting"
        (let ((subtree-end (save-excursion (org-end-of-subtree t))))
          (if (re-search-forward ":waiting:" subtree-end t)
              nil          ; tag found, do not skip
            subtree-end))) ; tag not found, continue after end of subtree
 
    Now you may use this function in an agenda custom command, for
 example like this:
 
      (org-add-agenda-custom-command
       '("b" todo "PROJECT"
         ((org-agenda-skip-function 'my-skip-unless-waiting)
          (org-agenda-overriding-header "Projects waiting for something: "))))
 
    Note that this also binds ‘org-agenda-overriding-header’ to get a
 meaningful header in the agenda view.
 
    A general way to create custom searches is to base them on a search
 for entries with a certain level limit.  If you want to study all
 entries with your custom search function, simply do a search for
 ‘LEVEL>0’(2), and then use ‘org-agenda-skip-function’ to select the
 entries you really want to have.
 
    You may also put a Lisp form into ‘org-agenda-skip-function’.  In
 particular, you may use the functions ‘org-agenda-skip-entry-if’ and
 ‘org-agenda-skip-subtree-if’ in this form, for example:
 
 ‘(org-agenda-skip-entry-if 'scheduled)’
      Skip current entry if it has been scheduled.
 ‘(org-agenda-skip-entry-if 'notscheduled)’
      Skip current entry if it has not been scheduled.
 ‘(org-agenda-skip-entry-if 'deadline)’
      Skip current entry if it has a deadline.
 ‘(org-agenda-skip-entry-if 'scheduled 'deadline)’
      Skip current entry if it has a deadline, or if it is scheduled.
 ‘(org-agenda-skip-entry-if 'todo '("TODO" "WAITING"))’
      Skip current entry if the TODO keyword is TODO or WAITING.
 ‘(org-agenda-skip-entry-if 'todo 'done)’
      Skip current entry if the TODO keyword marks a DONE state.
 ‘(org-agenda-skip-entry-if 'timestamp)’
      Skip current entry if it has any timestamp, may also be deadline or
      scheduled.
 ‘(org-agenda-skip-entry-if 'regexp "regular expression")’
      Skip current entry if the regular expression matches in the entry.
 ‘(org-agenda-skip-entry-if 'notregexp "regular expression")’
      Skip current entry unless the regular expression matches.
 ‘(org-agenda-skip-subtree-if 'regexp "regular expression")’
      Same as above, but check and skip the entire subtree.
 
    Therefore we could also have written the search for WAITING projects
 like this, even without defining a special function:
 
      (org-add-agenda-custom-command
       '("b" todo "PROJECT"
         ((org-agenda-skip-function '(org-agenda-skip-subtree-if
                                      'regexp ":waiting:"))
          (org-agenda-overriding-header "Projects waiting for something: "))))
 
    ---------- Footnotes ----------
 
    (1) The ‘agenda*’ view is the same than ‘agenda’ except that it only
 considers _appointments_, i.e., scheduled and deadline items that have a
 time specification ‘[h]h:mm’ in their time-stamps.
 
    (2) Note that, when using ‘org-odd-levels-only’, a level number
 corresponds to order in the hierarchy, not to the number of stars.