|
@@ -891,14 +891,39 @@ current display in the agenda."
|
|
|
:group 'org-agenda-daily/weekly
|
|
|
:type 'plist)
|
|
|
|
|
|
-(defcustom org-agenda-search-view-search-words-only nil
|
|
|
- "Non-nil means, the search string is interpreted as individual words
|
|
|
-The search then looks for each word separately in each entry and
|
|
|
-selects entries that have matches for all words.
|
|
|
-When nil, matching as loose words will only take place if the first
|
|
|
-word is preceded by + or -. If that is not the case, the search
|
|
|
-string will just be matched as a substring in the entry, but with
|
|
|
-each space character allowing for any whitespace, including newlines."
|
|
|
+(defcustom org-agenda-search-view-always-boolean nil
|
|
|
+ "Non-nil means, the search string is interpreted as individual parts.
|
|
|
+
|
|
|
+The search string for search view can either be interpreted as a phrase,
|
|
|
+or as a list of snippets that define a boolean search for a number of
|
|
|
+strings.
|
|
|
+
|
|
|
+When this is non-nil, the string will be split on whitespace, and each
|
|
|
+snippet will be searched individually, and all must match in order to
|
|
|
+select an entry. If a snippet is preceeded by \"-\", the snippet
|
|
|
+must *not* match. \"+\" is syntactic sugar for positive selection.
|
|
|
+Each snipped may be found as a full word or a partial word, but see
|
|
|
+the variable `org-agenda-search-view-force-full-words'.
|
|
|
+
|
|
|
+When this is nil, search will look for the entire search phrase as one,
|
|
|
+with each space character matching any amount of whitespace, including
|
|
|
+line breaks.
|
|
|
+
|
|
|
+Even when this is nil, you can still switch to Boolean search dynamically
|
|
|
+by preceeding the first snippet with \"+\" or \"-\". If the first snippet
|
|
|
+is a regexp marked with braces like \"{abc}\", this will also switch to
|
|
|
+boolean search."
|
|
|
+ :group 'org-agenda-search-view
|
|
|
+ :type 'boolean)
|
|
|
+
|
|
|
+(if (fboundp 'defvaralias)
|
|
|
+ (defvaralias 'org-agenda-search-view-search-words-only
|
|
|
+ 'org-agenda-search-view-always-boolean))
|
|
|
+
|
|
|
+(defcustom org-agenda-search-view-force-full-words nil
|
|
|
+ "Non-nil me
|
|
|
+ans, search words must be matches as complete words.
|
|
|
+When nil, they may also match part of a word."
|
|
|
:group 'org-agenda-search-view
|
|
|
:type 'boolean)
|
|
|
|
|
@@ -3209,8 +3234,6 @@ that when \"+Ameli\" is searched as a work, it will also match \"Ameli's\"")
|
|
|
;;;###autoload
|
|
|
(defun org-search-view (&optional todo-only string edit-at)
|
|
|
"Show all entries that contain words or regular expressions.
|
|
|
-If the first character of the search string is an asterisks,
|
|
|
-search only the headlines.
|
|
|
|
|
|
With optional prefix argument TODO-ONLY, only consider entries that are
|
|
|
TODO entries. The argument STRING can be used to pass a default search
|
|
@@ -3218,28 +3241,36 @@ 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 is broken into \"words\" by splitting at whitespace.
|
|
|
-Depending on the variable `org-agenda-search-view-search-words-only'
|
|
|
-and on whether the first character in the search string is \"+\" or \"-\",
|
|
|
-The string is then interpreted either as a substring with variable amounts
|
|
|
-of whitespace, or as a list or individual words that should be matched.
|
|
|
-
|
|
|
-The default is a substring match, where each space in the search string
|
|
|
-can expand to an arbitrary amount of whitespace, including newlines.
|
|
|
-
|
|
|
-If matching individual words, these words are then interpreted as a
|
|
|
-boolean expression with logical AND. 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 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.
|
|
|
-
|
|
|
-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.
|
|
|
+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 preceeding 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 snipped is search 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 preceeded with \"-\") must not
|
|
|
+match in the entry.
|
|
|
+
|
|
|
+- 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 seatch string starts
|
|
|
+ with a colon, this will mean that the 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'."
|
|
@@ -3254,17 +3285,21 @@ in `org-agenda-text-search-extra-files'."
|
|
|
'org-complex-heading-regexp org-complex-heading-regexp
|
|
|
'mouse-face 'highlight
|
|
|
'help-echo (format "mouse-2 or RET jump to location")))
|
|
|
+ (full-words org-agenda-search-view-force-full-words)
|
|
|
regexp rtn rtnall files file pos
|
|
|
- marker category tags c neg re as-words
|
|
|
+ marker category tags c neg re boolean
|
|
|
ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str)
|
|
|
(unless (and (not edit-at)
|
|
|
(stringp string)
|
|
|
(string-match "\\S-" string))
|
|
|
- (setq string (read-string "[+-]Word/{Regexp} ...: "
|
|
|
- (cond
|
|
|
- ((integerp edit-at) (cons string edit-at))
|
|
|
- (edit-at string))
|
|
|
- 'org-agenda-search-history)))
|
|
|
+ (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)))
|
|
|
(org-set-local 'org-todo-only todo-only)
|
|
|
(setq org-agenda-redo-command
|
|
|
(list 'org-search-view (if todo-only t nil) string
|
|
@@ -3278,21 +3313,40 @@ in `org-agenda-text-search-extra-files'."
|
|
|
(when (equal (string-to-char words) ?!)
|
|
|
(setq todo-only t
|
|
|
words (substring words 1)))
|
|
|
- (if (or org-agenda-search-view-search-words-only
|
|
|
- (member (string-to-char string) '(?- ?+)))
|
|
|
- (setq as-words t))
|
|
|
+ (when (equal (string-to-char words) ?:)
|
|
|
+ (setq full-words t
|
|
|
+ words (substring words 1)))
|
|
|
+ (if (or org-agenda-search-view-always-boolean
|
|
|
+ (member (string-to-char string) '(?- ?+ ?\{)))
|
|
|
+ (setq boolean t))
|
|
|
(setq words (org-split-string words))
|
|
|
- (if as-words
|
|
|
+ (when boolean
|
|
|
+ (let (wds w)
|
|
|
+ (while (setq w (pop words))
|
|
|
+ (if (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)))
|
|
|
+ (setq neg nil)))
|
|
|
(if (string-match "\\`{.*}\\'" w)
|
|
|
(setq re (substring w 1 -1))
|
|
|
- (setq re (concat "\\<" (regexp-quote (downcase w)) "\\>")))
|
|
|
+ (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 (lambda (w) (regexp-quote w)) words "\\s-+")
|