Browse Source

General operators for property searches.

We have now numerical comparisons, and we can do < and > for strings.
Carsten Dominik 17 years ago
parent
commit
d38aab0443
5 changed files with 98 additions and 92 deletions
  1. 5 0
      ChangeLog
  2. 13 10
      Makefile
  3. 43 70
      doc/org.texi
  4. 1 1
      lisp/org-table.el
  5. 36 11
      lisp/org.el

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+2008-04-23  Carsten Dominik  <dominik@science.uva.nl>
+
+	* lisp/org.el (org-op-to-function, org<>, org-string<=)
+	(org-string>=, org-string<>): New functions.
+
 2008-04-21  Carsten Dominik  <dominik@science.uva.nl>
 
 	* lisp/org-remember.el (org-get-x-clipboard): Protect the call to

+ 13 - 10
Makefile

@@ -61,31 +61,33 @@ CP = cp -p
 
 # The following variables need to be defined by the maintainer
 LISPF      = 	org.el			\
+		org-agenda.el		\
 	     	org-archive.el		\
+		org-bbdb.el		\
+		org-bibtex.el		\
+	     	org-clock.el		\
 	     	org-colview.el		\
 	     	org-colview-xemacs.el	\
 	     	org-compat.el		\
-	     	org-macs.el		\
-	     	org-clock.el		\
-		org-table.el		\
 		org-exp.el		\
-		org-faces.el		\
-		org-remember.el		\
-		org-agenda.el		\
-		org-publish.el		\
-		org-mouse.el		\
 		org-export-latex.el	\
-		org-bbdb.el		\
-		org-bibtex.el		\
+		org-faces.el		\
 		org-gnus.el		\
 		org-info.el		\
 		org-infojs.el		\
 		org-irc.el		\
 		org-mac-message.el	\
+	     	org-macs.el		\
+		org-mew.el              \
 		org-mhe.el		\
+		org-mouse.el		\
+		org-publish.el		\
+		org-remember.el		\
 		org-rmail.el		\
+		org-table.el		\
 		org-vm.el		\
 		org-wl.el
+
 LISPFILES0 = $(LISPF:%=lisp/%)
 LISPFILES  = $(LISPFILES0) lisp/org-install.el
 ELCFILES0  = $(LISPFILES0:.el=.elc)
@@ -279,6 +281,7 @@ lisp/org-bbdb.elc:         lisp/org.elc
 lisp/org-bibtex.elc:       lisp/org.elc
 lisp/org-clock.elc:        lisp/org.elc
 lisp/org-colview.elc:      lisp/org.elc
+lisp/org-colview-xemacs.elc:      lisp/org.elc
 lisp/org-compat.elc:
 lisp/org-exp.elc:          lisp/org.elc lisp/org-agenda.elc
 lisp/org-export-latex.elc: lisp/org.elc lisp/org-exp.elc

+ 43 - 70
doc/org.texi

@@ -3654,23 +3654,30 @@ CLOCKSUM     @r{The sum of CLOCK intervals in the subtree.  @code{org-clock-sum}
 @cindex properties, searching
 @cindex searching, of properties
 
-To create sparse trees and special lists with selection based on
-properties, the same commands are used as for tag searches (@pxref{Tag
-searches}), and the same logic applies.  For example, a search string
+To create sparse trees and special lists with selection based on properties,
+the same commands are used as for tag searches (@pxref{Tag searches}), and
+the same logic applies.  For example, here is a search string:
 
 @example
-+work-boss+PRIORITY="A"+Coffee="unlimited"+Effort=""+With=@{Sarah\|Denny@}
++work-boss+PRIORITY="A"+Coffee="unlimited"+Effort<2+With=@{Sarah\|Denny@}
 @end example
 
 @noindent
-finds entries tagged @samp{:work:} but not @samp{:boss:}, which
-also have a priority value @samp{A}, a @samp{:Coffee:} property with the
-value @samp{unlimited}, an @samp{Effort} property that is undefined or
-empty, and a @samp{:With:} property that is matched by
-the regular expression @samp{Sarah\|Denny}.
-
-You can configure Org mode to use property inheritance during a search,
-see @ref{Property inheritance} for details.
+If the comparison value is a plain number, a numerical comparison is done,
+and the allowed operators are @samp{<}, @samp{=}, @samp{>}, @samp{<=},
+@samp{>=}, and @samp{<>}.  If the comparison value is enclosed in double
+quotes, a string comparison is done, and the same operators are allowed.  If
+the comparison value is enclosed in curly braces, a regexp match is
+performed.  So the search string in the example finds entries tagged
+@samp{:work:} but not @samp{:boss:}, which also have a priority value
+@samp{A}, a @samp{:Coffee:} property with the value @samp{unlimited}, an
+@samp{Effort} property that is numerically smaller than 2, and a
+@samp{:With:} property that is matched by the regular expression
+@samp{Sarah\|Denny}.
+
+You can configure Org mode to use property inheritance during a search, but
+beware that this can slow down searches considerably.  See @ref{Property
+inheritance} for details.
 
 There is also a special command for creating sparse trees based on a
 single property:
@@ -4241,11 +4248,12 @@ M-S-@key{right}/@key{left}   @r{One month forward/backward.}
 @key{RET}           @r{Choose date in calendar.}
 @end example
 
-The actions of the date/time prompt may seem complex, but I assure you
-they will grow on you.  To help you understand what is going on, the
-current interpretation of your input will be displayed live in the
-minibuffer@footnote{If you find this distracting, turn the display of
-with @code{org-read-date-display-live}.}.
+The actions of the date/time prompt may seem complex, but I assure you they
+will grow on you, and you will start getting annoyed by pretty much any other
+way of entering a date/time out there.  To help you understand what is going
+on, the current interpretation of your input will be displayed live in the
+minibuffer@footnote{If you find this distracting, turn the display of with
+@code{org-read-date-display-live}.}.
 
 @node Custom time format,  , The date/time prompt, Creating timestamps
 @subsection Custom time format
@@ -4883,7 +4891,7 @@ for details.
 @item C-u C-c C-w
 Use the refile interface to jump to a heading.
 @kindex C-u C-u C-c C-w
-@item C- C-u C-c C-w
+@item C-u C-u C-c C-w
 Jump to the location where @code{org-refile} last moved a tree to.
 @end table
 
@@ -6469,7 +6477,7 @@ environments and math templates.  Inside Org mode, you can make use of
 some of the features of CDLaTeX mode.  You need to install
 @file{cdlatex.el} and @file{texmathp.el} (the latter comes also with
 AUCTeX) from @url{http://www.astro.uva.nl/~dominik/Tools/cdlatex}.
-Don't turn CDLaTeX mode itself under Org mode, but use the light
+Don't use CDLaTeX mode itself under Org mode, but use the light
 version @code{org-cdlatex-mode} that comes as part of Org mode.  Turn it
 on for the current buffer with @code{M-x org-cdlatex-mode}, or for all
 Org files with
@@ -6829,16 +6837,15 @@ view:    @r{Initial view when website is first shown.  Possible values are}
          showall   @r{Folding interface, all headlines and text visible.}
 sdepth:  @r{Maximum headline level that will still become an independent}
          @r{section for info and folding modes.  The default is taken from}
-         @r{@code{org-headline-levels} (= the @code{H} @code{#+OPTIONS} switch).}
+         @r{@code{org-headline-levels} (= the @code{H} switch in @code{#+OPTIONS}).}
          @r{If this is smaller than in @code{org-headline-levels}, each}
          @r{info/folding section can still contain children headlines.}
-         @r{Default is @code{org-headline-levels} (= the @code{H} @code{#+OPTIONS} switch).}
 toc:     @r{Should the table of content @emph{initially} be visible?}
          @r{Even when @code{nil}, you can always get to the toc with @kbd{i}.}
 tdepth:  @r{The depth of the table of contents.  The defaults are taken from}
          @r{the variables @code{org-headline-levels} and @code{org-export-with-toc}.}
 ltoc:    @r{Should there be short contents (children) in each section?}
-mouse:   @r{Headings are highlighted when the mouse is over themq.  Should be}
+mouse:   @r{Headings are highlighted when the mouse is over them.  Should be}
          @r{@samp{underline} (default) or a background color like @samp{#cccccc}.}
 buttons: @r{Should view-toggle buttons be everywhere?  When @code{nil} (the}
          @r{default), only one such button will be present.}
@@ -8247,51 +8254,11 @@ Org.
 @section Third-party extensions for Org
 @cindex extension, third-party
 
-The following extensions for Org have been written by other people:
-
-@table @asis
-@cindex @file{org-publish.el}
-@item @file{org-publish.el} by David O'Toole
-This package provides facilities for publishing related sets of Org
-files together with linked files like images as web pages.  It is
-highly configurable and can be used for other publishing purposes as
-well.  As of Org version 4.30, @file{org-publish.el} is part of the
-Org distribution.  It is not yet part of Emacs, however, a delay
-caused by the preparations for the 22.1 release.  In the mean time,
-@file{org-publish.el} can be downloaded from David's site:
-@url{http://dto.freeshell.org/e/org-publish.el}.
-@cindex @file{org-mouse.el}
-@item @file{org-mouse.el} by Piotr Zielinski
-This package implements extended mouse functionality for Org.  It
-allows you to cycle visibility and to edit the document structure with
-the mouse.  Best of all, it provides a context-sensitive menu on
-@key{mouse-3} that changes depending on the context of a mouse-click.
-As of Org version 4.53, @file{org-mouse.el} is part of the
-Org distribution.  It is not yet part of Emacs, however, a delay
-caused by the preparations for the 22.1 release.  In the mean time,
-@file{org-mouse.el} can be downloaded from Piotr's site:
-@url{http://www.cl.cam.ac.uk/~pz215/files/org-mouse.el}.
-@cindex @file{org-blog.el}
-@item @file{org-blog.el} by David O'Toole
-A blogging plug-in for @file{org-publish.el}.@*
-@url{http://dto.freeshell.org/notebook/OrgMode.html}.
-@cindex @file{blorg.el}
-@item @file{blorg.el} by Bastien Guerry
-Publish Org files as
-blogs. @url{http://www.cognition.ens.fr/~guerry/blorg.html}.
-@cindex @file{org2rem.el}
-@item @file{org2rem.el} by Bastien Guerry
-Translates Org files into something readable by
-Remind. @url{http://www.cognition.ens.fr/~guerry/u/org2rem.el}.
-@item @file{org-toc.el} by Bastien Guerry
-Produces a simple table of contents of an Org file, for easy
-navigation. @url{http://www.cognition.ens.fr/~guerry/u/org-registry.el}.
-@item @file{org-registry.el} by Bastien Guerry
-Find which Org-file link to a certain document.
-@url{http://www.cognition.ens.fr/~guerry/u/org2rem.el}.
-@end table
-
-@page
+There are lots of extensions that have been written by other people.  Most of
+them have either been integrated into Org by now, or they can be found in the
+Org distribution, in the @file{contrib} directory.  The list has gotten too
+long to cover in any detail here, but there is a seaparate manual for these
+extensions.
 
 @node Adding hyperlink types, Tables in arbitrary syntax, Extensions, Extensions and Hacking
 @section Adding hyperlink types
@@ -8774,7 +8741,8 @@ The corresponding block writer function could look like this:
 If you want to make sure that all dynamic blocks are always up-to-date,
 you could add the function @code{org-update-all-dblocks} to a hook, for
 example @code{before-save-hook}.  @code{org-update-all-dblocks} is
-written in a way that is does nothing in buffers that are not in Org.
+written in a way that is does nothing in buffers that are not in
+@code{org-mode}.
 
 @node Special agenda views, Using the property API, Dynamic blocks, Extensions and Hacking
 @section Special agenda views
@@ -8820,6 +8788,12 @@ like this:
 Note that this also binds @code{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 @samp{LEVEL>0}, and then
+use @code{org-agenda-skip-function} to select the entries you really want to
+have.
+
 You may also put a Lisp form into @code{org-agenda-skip-function}.  In
 particular, you may use the functions @code{org-agenda-skip-entry-if}
 and @code{org-agenda-skip-subtree-if} in this form, for example:
@@ -8852,7 +8826,6 @@ like this, even without defining a special function:
     (org-agenda-overriding-header "Projects waiting for something: "))))
 @end lisp
 
-
 @node Using the property API,  , Special agenda views, Extensions and Hacking
 @section Using the property API
 @cindex API, for properties
@@ -8936,7 +8909,7 @@ incorporate project planning functionality directly into a notes file.
 
 A special thanks goes to @i{Bastien Guerry} who has not only writen a large
 number of extensions to Org (most of them integrated into the core by now),
-but has also helep the development and maintenance of Org so much that e
+but has also helped the development and maintenance of Org so much that he
 should be considered co-author of this package.
 
 Since the first release, literally thousands of emails to me or on

+ 1 - 1
lisp/org-table.el

@@ -1767,7 +1767,7 @@ When NAMED is non-nil, look for a named equation."
       (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
 	(setq strings (org-split-string (match-string 2) " *:: *"))
 	(while (setq string (pop strings))
-	  (when (string-match "\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string)
+	  (when (string-match "\\`\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string)
 	    (setq scol (if (match-end 2)
 			   (match-string 2 string)
 			 (match-string 1 string))

+ 36 - 11
lisp/org.el

@@ -8764,10 +8764,11 @@ also TODO lines."
 
   ;; Parse the string and create a lisp form
   (let ((match0 match)
-	(re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL=\\([0-9]+\\)\\|\\([[:alnum:]_]+\\)=\\({[^}]+}\\|\"[^\"]*\"\\)\\|[[:alnum:]_@]+\\)"))
+	(re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)\\([0-9]+\\)\\|\\([[:alnum:]_]+\\)\\([<>=]\\{1,2\\}\\)\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)\\|[[:alnum:]_@]+\\)"))
 	minus tag mm
 	tagsmatch todomatch tagsmatcher todomatcher kwd matcher
-	orterms term orlist re-p level-p prop-p pn pv cat-p gv)
+	orterms term orlist re-p str-p level-p level-op 
+	prop-p pn pv po cat-p gv)
     (if (string-match "/+" match)
 	;; match contains also a todo-matching request
 	(progn
@@ -8792,24 +8793,32 @@ also TODO lines."
 			   (equal (match-string 1 term) "-"))
 		tag (match-string 2 term)
 		re-p (equal (string-to-char tag) ?{)
-		level-p (match-end 3)
-		prop-p (match-end 4)
+		level-p (match-end 4)
+		prop-p (match-end 5)
 		mm (cond
 		    (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
-		    (level-p `(= level ,(string-to-number
-					 (match-string 3 term))))
+		    (level-p
+		     (setq level-op (org-op-to-function (match-string 3 term)))
+		     `(,level-op level ,(string-to-number
+					 (match-string 4 term))))
 		    (prop-p
-		     (setq pn (match-string 4 term)
-			   pv (match-string 5 term)
+		     (setq pn (match-string 5 term)
+			   po (match-string 6 term)
+			   pv (match-string 7 term)
 			   cat-p (equal pn "CATEGORY")
 			   re-p (equal (string-to-char pv) ?{)
-			   pv (substring pv 1 -1))
+			   str-p (equal (string-to-char pv) ?\")
+			   pv (if (or re-p str-p) (substring pv 1 -1) pv))
+		     (setq po (org-op-to-function po str-p))
 		     (if (equal pn "CATEGORY")
 			 (setq gv '(get-text-property (point) 'org-category))
 		       (setq gv `(org-cached-entry-get nil ,pn)))
 		     (if re-p
 			 `(string-match ,pv (or ,gv ""))
-		       `(equal ,pv (or ,gv ""))))
+		       (if str-p
+			   `(,po (or ,gv "") ,pv)
+			 `(,po (string-to-number (or ,gv ""))
+			       ,(string-to-number pv) ))))
 		    (t `(member ,(downcase tag) tags-list)))
 		mm (if minus (list 'not mm) mm)
 		term (substring term (match-end 0)))
@@ -8822,7 +8831,7 @@ also TODO lines."
       (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
       (setq tagsmatcher
 	    (list 'progn '(setq org-cached-props nil) tagsmatcher)))
-
+    (debug)
     ;; Make the todo matcher
     (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
 	(setq todomatcher t)
@@ -8853,6 +8862,22 @@ also TODO lines."
 		    tagsmatcher))
     (cons match0 matcher)))
 
+(defun org-op-to-function (op &optional stringp)
+  (setq op
+	(cond
+	 ((equal  op   "<"       ) '(<     string<      ))
+	 ((equal  op   ">"       ) '(>     string>      ))
+	 ((member op '("<=" "=<")) '(<=    org-string<= ))
+	 ((member op '(">=" "=>")) '(>=    org-string>= ))
+	 ((member op '("="  "==")) '(=     string=      ))
+	 ((member op '("<>" "!=")) '(org<> org-string<> ))))
+  (nth (if stringp 1 0) op))
+
+(defun org<> (a b) (not (= a b)))
+(defun org-string<= (a b) (or (string= a b) (string< a b)))
+(defun org-string>= (a b) (or (string= a b) (string> a b)))
+(defun org-string<> (a b) (not (string= a b)))
+
 (defun org-match-any-p (re list)
   "Does re match any element of list?"
   (setq list (mapcar (lambda (x) (string-match re x)) list))