Function: org-search-view

org-search-view is an autoloaded, interactive and byte-compiled function defined in org-agenda.el.gz.

Signature

(org-search-view &optional TODO-ONLY STRING EDIT-AT)

Documentation

Show all entries that contain a phrase or words or regular expressions.

With optional prefix argument TODO-ONLY, only consider entries that are TODO entries. The argument STRING can be used to pass a default search string into this function. If EDIT-AT is non-nil, it means that the user should get a chance to edit this string, with cursor at position EDIT-AT.

The search string can be viewed either as a phrase that should be found as is, or it can be broken into a number of snippets, each of which must match in a Boolean way to select an entry. The default depends on the variable org-agenda-search-view-always-boolean. Even if this is turned off (the default) you can always switch to
Boolean search dynamically by preceding the first word with "+" or "-".

The default is a direct search of the whole phrase, where each space in the search string can expand to an arbitrary amount of whitespace, including newlines.

If using a Boolean search, the search string is split on whitespace and each snippet is searched separately, with logical AND to select an entry. Words prefixed with a minus must *not* occur in the entry. Words without a prefix or prefixed with a plus must occur in the entry. Matching is case-insensitive. Words are enclosed by word delimiters (i.e. they must match whole words, not parts of a word) if org-agenda-search-view-force-full-words is set (default is nil).

Boolean search snippets enclosed by curly braces are interpreted as regular expressions that must or (when preceded with "-") must not match in the entry. Snippets enclosed into double quotes will be taken as a whole, to include whitespace.

- If the search string starts with an asterisk, search only in headlines.
- If (possibly after the leading star) the search string starts with an
  exclamation mark, this also means to look at TODO entries only, an effect
  that can also be achieved with a prefix argument.
- If (possibly after star and exclamation mark) the search string starts
  with a colon, this will mean that the (non-regexp) snippets of the
  Boolean search must match as full words.

This command searches the agenda files, and in addition the files listed in org-agenda-text-search-extra-files unless a restriction lock is active.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-agenda.el.gz
;;;###autoload
(defun org-search-view (&optional todo-only string edit-at)
  "Show all entries that contain a phrase or words or regular expressions.

With optional prefix argument TODO-ONLY, only consider entries that are
TODO entries.  The argument STRING can be used to pass a default search
string into this function.  If EDIT-AT is non-nil, it means that the
user should get a chance to edit this string, with cursor at position
EDIT-AT.

The search string can be viewed either as a phrase that should be found as
is, or it can be broken into a number of snippets, each of which must match
in a Boolean way to select an entry.  The default depends on the variable
`org-agenda-search-view-always-boolean'.
Even if this is turned off (the default) you can always switch to
Boolean search dynamically by preceding the first word with  \"+\" or \"-\".

The default is a direct search of the whole phrase, where each space in
the search string can expand to an arbitrary amount of whitespace,
including newlines.

If using a Boolean search, the search string is split on whitespace and
each snippet is searched separately, with logical AND to select an entry.
Words prefixed with a minus must *not* occur in the entry.  Words without
a prefix or prefixed with a plus must occur in the entry.  Matching is
case-insensitive.  Words are enclosed by word delimiters (i.e. they must
match whole words, not parts of a word) if
`org-agenda-search-view-force-full-words' is set (default is nil).

Boolean search snippets enclosed by curly braces are interpreted as
regular expressions that must or (when preceded with \"-\") must not
match in the entry.  Snippets enclosed into double quotes will be taken
as a whole, to include whitespace.

- If the search string starts with an asterisk, search only in headlines.
- If (possibly after the leading star) the search string starts with an
  exclamation mark, this also means to look at TODO entries only, an effect
  that can also be achieved with a prefix argument.
- If (possibly after star and exclamation mark) the search string starts
  with a colon, this will mean that the (non-regexp) snippets of the
  Boolean search must match as full words.

This command searches the agenda files, and in addition the files
listed in `org-agenda-text-search-extra-files' unless a restriction lock
is active."
  (interactive "P")
  (when org-agenda-overriding-arguments
    (setq todo-only (car org-agenda-overriding-arguments)
	  string (nth 1 org-agenda-overriding-arguments)
	  edit-at (nth 2 org-agenda-overriding-arguments)))
  (let* ((props (list 'face nil
		      'done-face 'org-agenda-done
		      'org-not-done-regexp org-not-done-regexp
		      'org-todo-regexp org-todo-regexp
		      'org-complex-heading-regexp org-complex-heading-regexp
		      'mouse-face 'highlight
		      'help-echo "mouse-2 or RET jump to location"))
	 (full-words org-agenda-search-view-force-full-words)
	 (org-agenda-text-search-extra-files org-agenda-text-search-extra-files)
	 regexp rtn rtnall files file pos inherited-tags
	 marker category level tags c neg re boolean
	 ee txt beg end last-search-end words regexps+ regexps- hdl-only buffer beg1 str)
    (unless (and (not edit-at)
		 (stringp string)
		 (string-match "\\S-" string))
      (setq string (read-string
		    (if org-agenda-search-view-always-boolean
			"[+-]Word/{Regexp} ...: "
		      "Phrase or [+-]Word/{Regexp} ...: ")
		    (cond
		     ((integerp edit-at) (cons string edit-at))
		     (edit-at string))
		    'org-agenda-search-history)))
    (catch 'exit
      (setq org-agenda-buffer-name
	    (org-agenda--get-buffer-name
	     (and org-agenda-sticky
		  (if (stringp string)
		      (format "*Org Agenda(%s:%s)*"
			      (or org-keys (or (and todo-only "S") "s"))
			      string)
		    (format "*Org Agenda(%s)*"
			    (or (and todo-only "S") "s"))))))
      (org-agenda-prepare "SEARCH")
      (org-compile-prefix-format 'search)
      (org-set-sorting-strategy 'search)
      (setq org-agenda-redo-command
	    (list 'org-search-view (if todo-only t nil)
		  (list 'if 'current-prefix-arg nil string)))
      (setq org-agenda-query-string string)
      (if (equal (string-to-char string) ?*)
	  (setq hdl-only t
		words (substring string 1))
	(setq words string))
      (when (equal (string-to-char words) ?!)
	(setq todo-only t
	      words (substring words 1)))
      (when (equal (string-to-char words) ?:)
	(setq full-words t
	      words (substring words 1)))
      (when (or org-agenda-search-view-always-boolean
		(member (string-to-char words) '(?- ?+ ?\{)))
	(setq boolean t))
      (setq words (split-string words))
      (let (www w)
	(while (setq w (pop words))
	  (while (and (string-match "\\\\\\'" w) words)
	    (setq w (concat (substring w 0 -1) " " (pop words))))
	  (push w www))
	(setq words (nreverse www) www nil)
	(while (setq w (pop words))
	  (when (and (string-match "\\`[-+]?{" w)
		     (not (string-match "}\\'" w)))
	    (while (and words (not (string-match "}\\'" (car words))))
	      (setq w (concat w " " (pop words))))
	    (setq w (concat w " " (pop words))))
	  (push w www))
	(setq words (nreverse www)))
      (setq org-agenda-last-search-view-search-was-boolean boolean)
      (when boolean
	(let (wds w)
	  (while (setq w (pop words))
	    (when (or (equal (substring w 0 1) "\"")
		      (and (> (length w) 1)
			   (member (substring w 0 1) '("+" "-"))
			   (equal (substring w 1 2) "\"")))
	      (while (and words (not (equal (substring w -1) "\"")))
		(setq w (concat w " " (pop words)))))
	    (and (string-match "\\`\\([-+]?\\)\"" w)
		 (setq w (replace-match "\\1" nil nil w)))
	    (and (equal (substring w -1) "\"") (setq w (substring w 0 -1)))
	    (push w wds))
	  (setq words (nreverse wds))))
      (if boolean
	  (mapc (lambda (w)
		  (setq c (string-to-char w))
		  (if (equal c ?-)
		      (setq neg t w (substring w 1))
		    (if (equal c ?+)
			(setq neg nil w (substring w 1))
		      (setq neg nil)))
		  (if (string-match "\\`{.*}\\'" w)
		      (setq re (substring w 1 -1))
		    (if full-words
			(setq re (concat "\\<" (regexp-quote (downcase w)) "\\>"))
		      (setq re (regexp-quote (downcase w)))))
		  (if neg (push re regexps-) (push re regexps+)))
		words)
	(push (mapconcat #'regexp-quote words "\\s-+")
	      regexps+))
      (setq regexps+ (sort regexps+ (lambda (a b) (> (length a) (length b)))))
      (if (not regexps+)
	  (setq regexp org-outline-regexp-bol)
	(setq regexp (pop regexps+))
	(when hdl-only (setq regexp (concat org-outline-regexp-bol ".*?"
					    regexp))))
      (setq files (org-agenda-files nil 'ifmode))
      ;; Add `org-agenda-text-search-extra-files' unless there is some
      ;; restriction.
      (when (eq (car org-agenda-text-search-extra-files) 'agenda-archives)
	(pop org-agenda-text-search-extra-files)
	(unless (get 'org-agenda-files 'org-restrict)
	  (setq files (org-add-archive-files files))))
      ;; Uniquify files.  However, let `org-check-agenda-file' handle
      ;; non-existent ones.
      (setq files (cl-remove-duplicates
		   (append files org-agenda-text-search-extra-files)
		   :test (lambda (a b)
			   (and (file-exists-p a)
				(file-exists-p b)
				(file-equal-p a b))))
	    rtnall nil)
      (while (setq file (pop files))
	(setq ee nil)
	(catch 'nextfile
	  (org-check-agenda-file file)
	  (setq buffer (if (file-exists-p file)
			   (org-get-agenda-file-buffer file)
			 (error "No such file %s" file)))
	  (unless buffer
	    ;; If file does not exist, make sure an error message is sent
	    (setq rtn (list (format "ORG-AGENDA-ERROR: No such org-file %s"
				    file))))
	  (with-current-buffer buffer
	    (with-syntax-table (org-search-syntax-table)
	      (unless (derived-mode-p 'org-mode)
		(error "Agenda file %s is not in Org mode" file))
	      (let ((case-fold-search t))
		(save-excursion
		  (save-restriction
		    (if (eq buffer org-agenda-restrict)
			(narrow-to-region org-agenda-restrict-begin
					  org-agenda-restrict-end)
		      (widen))
		    (goto-char (point-min))
		    (unless (or (org-at-heading-p)
				(outline-next-heading))
		      (throw 'nextfile t))
		    (goto-char (max (point-min) (1- (point))))
		    (while (re-search-forward regexp nil t)
                      (setq last-search-end (point))
		      (org-back-to-heading t)
		      (while (and (not (zerop org-agenda-search-view-max-outline-level))
				  (> (org-reduced-level (org-outline-level))
				     org-agenda-search-view-max-outline-level)
				  (forward-line -1)
				  (org-back-to-heading t)))
		      (skip-chars-forward "* ")
                      (setq beg (line-beginning-position)
			    beg1 (point)
			    end (progn
				  (outline-next-heading)
				  (while (and (not (zerop org-agenda-search-view-max-outline-level))
					      (> (org-reduced-level (org-outline-level))
						 org-agenda-search-view-max-outline-level)
					      (forward-line 1)
					      (outline-next-heading)))
				  (point)))

		      (catch :skip
			(goto-char beg)
			(org-agenda-skip)
			(setq str (buffer-substring-no-properties
                                   (line-beginning-position)
                                   (if hdl-only (line-end-position) end)))
			(mapc (lambda (wr) (when (string-match wr str)
					     (goto-char (1- end))
					     (throw :skip t)))
			      regexps-)
			(mapc (lambda (wr) (unless (string-match wr str)
					     (goto-char (1- end))
					     (throw :skip t)))
			      (if todo-only
				  (cons (concat "^\\*+[ \t]+"
                                                org-not-done-regexp)
					regexps+)
				regexps+))
			(goto-char beg)
			(setq marker (org-agenda-new-marker (point))
			      category (org-get-category)
			      level (make-string (org-reduced-level (org-outline-level)) ? )
			      inherited-tags
			      (or (eq org-agenda-show-inherited-tags 'always)
				  (and (listp org-agenda-show-inherited-tags)
				       (memq 'todo org-agenda-show-inherited-tags))
				  (and (eq org-agenda-show-inherited-tags t)
				       (or (eq org-agenda-use-tag-inheritance t)
					   (memq 'todo org-agenda-use-tag-inheritance))))
			      tags (org-get-tags nil (not inherited-tags))
			      txt (org-agenda-format-item
				   ""
				   (buffer-substring-no-properties
                                    beg1 (line-end-position))
				   level category tags t))
			(org-add-props txt props
			  'org-marker marker 'org-hd-marker marker
			  'org-todo-regexp org-todo-regexp
			  'level level
			  'org-complex-heading-regexp org-complex-heading-regexp
			  'priority 1000
			  'type "search")
			(push txt ee)
			(goto-char (max (1- end) last-search-end))))))))))
	(setq rtn (nreverse ee))
	(setq rtnall (append rtnall rtn)))
      (org-agenda--insert-overriding-header
	(with-temp-buffer
	  (insert "Search words: ")
	  (add-text-properties (point-min) (1- (point))
			       (list 'face 'org-agenda-structure))
	  (setq pos (point))
	  (insert string "\n")
	  (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure-filter))
	  (setq pos (point))
	  (unless org-agenda-multi
	    (insert (substitute-command-keys "\\<org-agenda-mode-map>\
Press `\\[org-agenda-manipulate-query-add]', \
`\\[org-agenda-manipulate-query-subtract]' to add/sub word, \
`\\[org-agenda-manipulate-query-add-re]', \
`\\[org-agenda-manipulate-query-subtract-re]' to add/sub regexp, \
`\\[universal-argument] \\[org-agenda-redo]' for a fresh search\n"))
	    (add-text-properties pos (1- (point))
				 (list 'face 'org-agenda-structure-secondary)))
	  (buffer-string)))
      (org-agenda-mark-header-line (point-min))
      (when rtnall
	(insert (org-agenda-finalize-entries rtnall 'search) "\n"))
      (goto-char (point-min))
      (or org-agenda-multi (org-agenda-fit-window-to-buffer))
      (add-text-properties (point-min) (point-max)
			   `(org-agenda-type search
					     org-last-args (,todo-only ,string ,edit-at)
					     org-redo-cmd ,org-agenda-redo-command
					     org-series-cmd ,org-cmd))
      (org-agenda-finalize)
      (setq buffer-read-only t))))