浏览代码

Implementing search view.

Carsten Dominik 17 年之前
父节点
当前提交
4f7cb263f3
共有 4 个文件被更改,包括 149 次插入26 次删除
  1. 11 0
      ChangeLog
  2. 9 4
      ORGWEBPAGE/Changes.org
  3. 101 18
      org.el
  4. 28 4
      org.texi

+ 11 - 0
ChangeLog

@@ -1,3 +1,14 @@
+2008-02-29  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org.el (org-agenda-text-search-extra-files): Renamed from
+	`org-agenda-multi-occur-extra-files'.
+	(org-agenda-manipulate-query-add)
+	(org-agenda-manipulate-query-subtract)
+	(org-agenda-manipulate-query-add-regexp)
+	(org-agenda-manipulate-query-subtract-regexp)
+	(org-agenda-manipulate-query): New functions.
+	(org-agenda-query-register): New option.
+
 2008-02-28  Carsten Dominik  <dominik@science.uva.nl>
 
 	* org.el (org-auto-repeat-maybe): Make sure that the repeat stuff

+ 9 - 4
ORGWEBPAGE/Changes.org

@@ -15,8 +15,9 @@
 
     `C-c a s' now invokes a special agenda view that can be used
     to search notes by keyword and regular expressions.  The
-    search knows the boundaries of an entry, and it can use
-    simple Boolean logic.  For example, the search string
+    search knows the boundaries of an entry, can use simple
+    Boolean logic and is reasonably fast.  For example, the
+    search string
 
     : +computer +wifi -ethernet -{8\.11[bg]}
 
@@ -29,12 +30,16 @@
     otherwise it will look at the headine and the text below it,
     up to the next (possibly sub-) heading.
 
-    If find it very useful to define a custom command to do such
+    The command searches all agenda files, and in addition the
+    files listed in `org-agenda-text-search-extra-files'.
+    
+    I find it very useful to define a custom command to do such
     a search only in a limited number of files (my notes files),
     like this:
 
     : ("N" "Search notes" search ""
-    :   ((org-agenda-files '("~/org/notes.org" "~/org/computer.org"))))    
+    :   ((org-agenda-files '("~/org/notes.org" "~/org/computer.org"))
+    :    (org-agenda-text-search-extra-files nil)))
 
 *** Many new extensions available in the CONTRIB directory
 

+ 101 - 18
org.el

@@ -2262,12 +2262,21 @@ Nil means to remove them, after a query, from the list."
   :group 'org-agenda
   :type 'boolean)
 
-(defcustom org-agenda-multi-occur-extra-files nil
-  "List of extra files to be searched by `org-occur-in-agenda-files'.
-The files in `org-agenda-files' are always searched."
+(defcustom org-agenda-text-search-extra-files nil
+  "List of extra files to be searched by text search commands.
+These files will be search in addition to the agenda files bu the
+commands `org-search-view' (`C-c a s') and `org-occur-in-agenda-files'.
+Note that these files will only be searched for text search commands,
+not for the other agenda views like todo lists, tag earches or the weekly
+agenda.  This variable is intended to list notes and possibly archive files
+that should also be searched by these two commands."
   :group 'org-agenda
   :type '(repeat file))
 
+(if (fboundp 'defvaralias)
+    (defvaralias 'org-agenda-multi-occur-extra-files
+      'org-agenda-text-search-extra-files))
+
 (defcustom org-agenda-confirm-kill 1
   "When set, remote killing from the agenda buffer needs confirmation.
 When t, a confirmation is always needed.  When a number N, confirmation is
@@ -2492,6 +2501,13 @@ should provide a description for the prefix, like
 		 (string :tag "Access Key(s)")
 		 (string :tag "Description  ")))))
 
+(defcustom org-agenda-query-register ?o
+  "The register holding the current query string.
+The prupose of this is that if you construct a query string interactively,
+you can then use it to define a custom command."
+  :group 'org-agenda-custom-commands
+  :type 'character)
+
 (defcustom org-stuck-projects
   '("+LEVEL=2/-DONE" ("TODO" "NEXT" "NEXTACTION") nil "")
   "How to identify stuck projects.
@@ -19329,6 +19345,7 @@ FIXME: describe the elements."
 (defvar org-agenda-follow-mode nil)
 (defvar org-agenda-show-log nil)
 (defvar org-agenda-redo-command nil)
+(defvar org-agenda-query-string nil)
 (defvar org-agenda-mode-hook nil)
 (defvar org-agenda-type nil)
 (defvar org-agenda-force-single-file nil)
@@ -19465,6 +19482,11 @@ The following commands are available:
 (org-defkey org-agenda-mode-map [(left)] 'org-agenda-earlier)
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-c" 'org-agenda-columns)
 
+(org-defkey org-agenda-mode-map "[" 'org-agenda-manipulate-query-add)
+(org-defkey org-agenda-mode-map "]" 'org-agenda-manipulate-query-subtract)
+(org-defkey org-agenda-mode-map "{" 'org-agenda-manipulate-query-add-re)
+(org-defkey org-agenda-mode-map "}" 'org-agenda-manipulate-query-subtract-re)
+
 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
   "Local keymap for agenda entries from Org-mode.")
 
@@ -20878,7 +20900,10 @@ Words without a prefix or prefixed with a plus must occur in the entry.
 Matching is case-insensitive and the words are enclosed by word delimiters.
 
 Words enclosed by curly braces are interpreted as regular expressions
-that must or must not match in the entry."
+that must or must not match in the entry.
+
+This command searches the agenda files, and in addition the files listed
+in `org-agenda-text-search-extra-files'."
   (interactive "P")
   (org-compile-prefix-format 'search)
   (org-set-sorting-strategy 'search)
@@ -20890,18 +20915,20 @@ that must or must not match in the entry."
 		      'mouse-face 'highlight
 		      'keymap org-agenda-keymap
 		      'help-echo (format "mouse-2 or RET jump to location")))
-	 ;; FIXME: get rid of the \n at some point  but watch out
-	 (regexp (concat "^" org-outline-regexp))
-	 rtn rtnall files file pos
-	 marker priority category tags
+	 regexp rtn rtnall files file pos
+	 marker priority category tags c neg re
 	 ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str)
-    (unless (and (stringp string)
+    (unless (and (not arg)
+		 (stringp string)
 		 (string-match "\\S-" string))
-      (setq string (read-string "Word Search: " nil
+      (setq string (read-string "[+-]Word/{Regexp} ...: "
+				(cond
+				 ((integerp arg) (cons string arg))
+				 (arg string))
 				'org-agenda-search-history)))
-
     (setq org-agenda-redo-command
 	  (list 'org-search-view 'current-prefix-arg string))
+    (setq org-agenda-query-string string)
 
     (if (equal (string-to-char string) ?*)
 	(setq hdl-only t
@@ -20920,7 +20947,13 @@ that must or must not match in the entry."
 	      (setq re (concat "\\<" (regexp-quote (downcase w)) "\\>")))
 	    (if neg (push re regexps-) (push re regexps+)))
 	  words)
-    (setq files (org-agenda-files)
+    (setq regexps+ (sort regexps+ (lambda (a b) (> (length a) (length b)))))
+    (if (not regexps+)
+	(setq regexp (concat "^" org-outline-regexp))
+      (setq regexp (pop regexps+))
+      (if hdl-only (setq regexp (concat "^" org-outline-regexp ".*?"
+					regexp))))
+    (setq files (append (org-agenda-files) org-agenda-text-search-extra-files)
 	  rtnall nil)
     (while (setq file (pop files))
       (setq ee nil)
@@ -20944,11 +20977,17 @@ that must or must not match in the entry."
 				      org-agenda-restrict-end)
 		  (widen))
 		(goto-char (point-min))
+		(unless (or (org-on-heading-p)
+			    (outline-next-heading))
+		  (throw 'nextfile t))
+		(goto-char (max (point-min) (1- (point))))
 		(while (re-search-forward regexp nil t)
+		  (org-back-to-heading t)
+		  (skip-chars-forward "* ")
+		  (setq beg (point-at-bol)
+			beg1 (point)
+			end (progn (outline-next-heading) (point)))
 		  (catch :skip
-		    (setq beg (point-at-bol)
-			  beg1 (match-end 0)
-			  end (progn (outline-next-heading) (point)))
 		    (goto-char beg)
 		    (org-agenda-skip)
 		    (setq str (buffer-substring-no-properties
@@ -20977,7 +21016,7 @@ that must or must not match in the entry."
 		      'type "search")
 		    (push txt ee)
 		    (goto-char (1- end)))))))))
-      (setq rtn ee)
+      (setq rtn (nreverse ee))
       (setq rtnall (append rtnall rtn)))
     (if org-agenda-overriding-header
 	(insert (org-add-props (copy-sequence org-agenda-overriding-header)
@@ -20988,7 +21027,11 @@ that must or must not match in the entry."
       (setq pos (point))
       (insert string "\n")
       (add-text-properties pos (1- (point)) (list 'face 'org-warning))
-      (setq pos (point)))
+      (setq pos (point))
+      (unless org-agenda-multi
+	(insert "Press `[', `]' to add/sub word, `{', `}' to add/sub regexp, `C-u r' to edit\n")
+	(add-text-properties pos (1- (point))
+			     (list 'face 'org-agenda-structure))))
     (when rtnall
       (insert (org-finalize-agenda-entries rtnall) "\n"))
     (goto-char (point-min))
@@ -22440,6 +22483,46 @@ When this is the global TODO list, a prefix argument will be interpreted."
     (goto-line line)
     (recenter window-line)))
 
+(defun org-agenda-manipulate-query-add ()
+  "Manipulate the query by adding a search term with positive selection.
+Positive selection means, the term must be matched for selection of an entry."
+  (interactive)
+  (org-agenda-manipulate-query ?\[))
+(defun org-agenda-manipulate-query-subtract ()
+  "Manipulate the query by adding a search term with negative selection.
+Negative selection means, term must not be matched for selection of an entry."
+  (interactive)
+  (org-agenda-manipulate-query ?\]))
+(defun org-agenda-manipulate-query-add-re ()
+  "Manipulate the query by adding a search regexp with positive selection.
+Positive selection means, the regexp must match for selection of an entry."
+  (interactive)
+  (org-agenda-manipulate-query ?\{))
+(defun org-agenda-manipulate-query-subtract-re ()
+  "Manipulate the query by adding a search regexp with negative selection.
+Negative selection means, regexp must not match for selection of an entry."
+  (interactive)
+  (org-agenda-manipulate-query ?\}))
+(defun org-agenda-manipulate-query (char)
+  (cond
+   ((eq org-agenda-type 'search)
+    (org-add-to-string
+     'org-agenda-query-string
+     (cdr (assoc char '((?\[ . " +") (?\] . " -")
+			(?\{ . " +{}") (?\} . " -{}")))))
+    (setq org-agenda-redo-command
+	  (list 'org-search-view
+		(+ (length org-agenda-query-string)
+		   (if (member char '(?\{ ?\})) 0 1))
+		org-agenda-query-string))
+    (set-register org-agenda-query-register org-agenda-query-string)
+    (org-agenda-redo))
+   (t (error "Canot manipulate query for %s-type agenda buffers"
+	     org-agenda-type))))
+
+(defun org-add-to-string (var string)
+  (set var (concat (symbol-value var) string)))
+
 (defun org-agenda-goto-date (date)
   "Jump to DATE in agenda."
   (interactive (list (org-read-date)))
@@ -27776,7 +27859,7 @@ really on, so that the block visually is on the match."
   (interactive "sOrg-files matching: \np")
   (let* ((files (org-agenda-files))
 	 (tnames (mapcar 'file-truename files))
-	 (extra org-agenda-multi-occur-extra-files)
+	 (extra org-agenda-text-search-extra-files)
 	 f)
     (while (setq f (pop extra))
       (unless (member (file-truename f) tnames)

+ 28 - 4
org.texi

@@ -5127,12 +5127,15 @@ string
 +computer +wifi -ethernet -@{8\.11[bg]@}
 @end example
 
-Will search for note entries that contain the keywords @code{computer}
+@noindent
+will search for note entries that contain the keywords @code{computer}
 and @code{wifi}, but not the keyword @code{ethernet}, and which are also
 not matched by the regular expression @code{8\.11[bg]}, meaning to
 exclude both 8.11b and 8.11g.
-@end table
 
+Note that in addition to the agenda files, this command will also search
+the files listed in @code{org-agenda-text-search-extra-files}.
+@end table
 
 @node Stuck projects,  , Timeline, Built-in agenda views
 @subsection Stuck projects
@@ -5426,6 +5429,23 @@ Display the previous dates.
 @item .
 Goto today.
 
+@tsubheading{Query editing}
+@cindex query editing, in agenda
+
+@kindex [
+@kindex ]
+@kindex @{
+@kindex @}
+@item [ ] @{ @}
+In the @i{search view} (@pxref{Keyword search}), these keys add new
+search words (@kbd{[} and @kbd{]}) or new regular expressions (@kbd{@{}
+and @kbd{@}}) to the query string.  The opening bracket/brace will add a
+positive search term prefixed by @samp{+}, indicating that this search
+term @i{must} occur/match in the entry.  Closing bracket/brace add a
+negative search term which @i{must not} occur/match in the entry for it
+to be selected.
+
+
 @tsubheading{Remote editing}
 @cindex remote editing, from agenda
 
@@ -5744,7 +5764,10 @@ right spot in @code{org-agenda-custom-commands}.  For example:
           (org-agenda-prefix-format "  Mixed: ")))
         ("U" tags-tree "+boss-urgent"
          ((org-show-following-heading nil)
-          (org-show-hierarchy-above nil)))))
+          (org-show-hierarchy-above nil)))
+        ("N" search ""
+         ((org-agenda-files '("~org/notes.org"))
+          (org-agenda-text-search-extra-files nil)))))          
 @end group
 @end lisp
 
@@ -5754,7 +5777,8 @@ priority, and the prefix format is modified to just say @samp{  Mixed: }
 instead of giving the category of the entry.  The sparse tags tree of
 @kbd{C-c a U} will now turn out ultra-compact, because neither the
 headline hierarchy above the match, nor the headline following the match
-will be shown.
+will be shown.  The command @kbd{C-c a N} will do a text search limited
+to only a single file.
 
 For command sets creating a block agenda,
 @code{org-agenda-custom-commands} has two separate spots for setting