浏览代码

Added context-aware, tag auto-exclusion (/ RET)

(org-agenda-auto-exclude-function): New customization variable for
allowing the user to create an "auto exclusion" filter for doing
context-aware auto tag filtering.

(org-agenda-filter-by-tag): Changes to support the use of
`org-agenda-auto-exclude-function'.  See the new manual addition,.
John Wiegley 15 年之前
父节点
当前提交
85878aadbf
共有 3 个文件被更改,包括 69 次插入14 次删除
  1. 26 0
      doc/org.texi
  2. 8 0
      lisp/ChangeLog
  3. 35 14
      lisp/org-agenda.el

+ 26 - 0
doc/org.texi

@@ -7224,6 +7224,32 @@ application of the operator, entries without a defined effort will be treated
 according to the value of @code{org-sort-agenda-noeffort-is-high}.  To filter
 for tasks without effort definition, press @kbd{?} as the operator.
 
+Org also supports automatic, context-aware tag filtering.  If the variable
+@code{org-agenda-auto-exclude-function} is set to a user-defined function,
+that function can decide which tags should be excluded from the agenda
+automatically.  Once this is set, the @kbd{/} command then accepts @kbd{RET}
+as a sub-option key and runs the auto exclusion logic.  For example, let's
+say you use a @code{Net} tag to identify tasks which need network access, an
+@code{Errand} tag for errands in town, and a @code{Call} tag for making phone
+calls.  You could auto-exclude these tags based on the availability of the
+Internet, and outside of business hours, with something like this:
+
+@lisp
+@group
+(defun org-my-auto-exclude-function (tag)
+  (and (cond
+	((string= tag "Net")
+	 (/= 0 (call-process "/sbin/ping" nil nil nil
+			     "-c1" "-q" "-t1" "mail.gnu.org")))
+	((or (string= tag "Errand") (string= tag "Call"))
+	 (let ((hour (nth 2 (decode-time))))
+	   (or (< hour 8) (> hour 21)))))
+       (concat "-" tag)))
+
+(setq org-agenda-auto-exclude-function 'org-my-auto-exclude-function)
+@end group
+@end lisp
+
 @kindex \
 @item \
 Narrow the current agenda filter by an additional condition.  When called with

+ 8 - 0
lisp/ChangeLog

@@ -1,3 +1,11 @@
+2009-10-19  John Wiegley  <johnw@newartisans.com>
+
+	* org-agenda.el (org-agenda-auto-exclude-function): New
+	customization variable for allowing the user to create an "auto
+	exclusion" filter for doing context-aware auto tag filtering.
+	(org-agenda-filter-by-tag): Changes to support the use of
+	`org-agenda-auto-exclude-function'.  See the new manual addition,.
+
 2009-10-18  John Wiegley  <johnw@newartisans.com>
 
 	* org.el (org-files-list): Don't attempt to return a file name for

+ 35 - 14
lisp/org-agenda.el

@@ -1276,6 +1276,15 @@ estimate."
   :group 'org-agenda-column-view
   :type 'boolean)
 
+(defcustom org-agenda-auto-exclude-function nil
+  "A function called with a tag to decide if it is filtered on '/ RET'.
+The sole argument to the function, which is called once for each
+possible tag, is a string giving the name of the tag.  The
+function should return either nil if the tag should be included
+as normal, or \"-<TAG>\" to exclude the tag."
+  :group 'org-agenda
+  :type 'function)
+
 (eval-when-compile
   (require 'cl))
 (require 'org)
@@ -5037,22 +5046,23 @@ used to narrow the search - the interactive user can also press `-' or `+'
 to switch to narrowing."
   (interactive "P")
   (let* ((alist org-tag-alist-for-agenda)
-	(tag-chars (mapconcat
-		    (lambda (x) (if (cdr x) (char-to-string (cdr x)) ""))
-		    alist ""))
-	(efforts (org-split-string
-		  (or (cdr (assoc (concat org-effort-property "_ALL")
-				  org-global-properties))
-		      "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"		      "")))
-	(effort-op org-agenda-filter-effort-default-operator)
-	(effort-prompt "")
-	(inhibit-read-only t)
-	(current org-agenda-filter)
-	char a n tag)
+	 (tag-chars (mapconcat
+		     (lambda (x) (if (cdr x) (char-to-string (cdr x)) ""))
+		     alist ""))
+	 (efforts (org-split-string
+		   (or (cdr (assoc (concat org-effort-property "_ALL")
+				   org-global-properties))
+		       "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"		      "")))
+	 (effort-op org-agenda-filter-effort-default-operator)
+	 (effort-prompt "")
+	 (inhibit-read-only t)
+	 (current org-agenda-filter)
+	 char a n tag)
     (unless char
       (message
-       "%s by tag [%s ], [TAB], [/]:off, [+-]:narrow, [>=<?]:effort: "
-       (if narrow "Narrow" "Filter") tag-chars)
+       "%s by tag [%s ], [TAB], %s[/]:off, [+-]:narrow, [>=<?]:effort: "
+       (if narrow "Narrow" "Filter") tag-chars
+       (if org-agenda-auto-exclude-function "[RET], " ""))
       (setq char (read-char)))
     (when (member char '(?+ ?-))
       ;; Narrowing down
@@ -5084,6 +5094,17 @@ to switch to narrowing."
 	(setq tag (org-icompleting-read
 		   "Tag: " org-global-tags-completion-table))))
     (cond
+     ((equal char ?\r)
+      (org-agenda-filter-by-tag-show-all)
+      (when org-agenda-auto-exclude-function
+	(setq org-agenda-filter '())
+	(dolist (tag org-tag-alist-for-agenda)
+	  (let ((modifier (funcall org-agenda-auto-exclude-function
+				   (car tag))))
+	    (if modifier
+		(push modifier org-agenda-filter))))
+	(if (not (null org-agenda-filter))
+	    (org-agenda-filter-apply org-agenda-filter))))
      ((equal char ?/)
       (org-agenda-filter-by-tag-show-all)
       (when (get 'org-agenda-filter :preset-filter)