emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/bbdb 89d9399 3/3: * lisp/bbdb-com.el (bbdb-search): New


From: Roland Winkler
Subject: [elpa] externals/bbdb 89d9399 3/3: * lisp/bbdb-com.el (bbdb-search): New keywords :invert and :case-fold.
Date: Wed, 1 Jan 2020 23:18:32 -0500 (EST)

branch: externals/bbdb
commit 89d93994177d2352f6458f28650c07decdcbcc1d
Author: Roland Winkler <address@hidden>
Commit: Roland Winkler <address@hidden>

    * lisp/bbdb-com.el (bbdb-search): New keywords :invert and :case-fold.
---
 bbdb-com.el | 86 +++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 49 insertions(+), 37 deletions(-)

diff --git a/bbdb-com.el b/bbdb-com.el
index 7396557..d4cd581 100644
--- a/bbdb-com.el
+++ b/bbdb-com.el
@@ -202,11 +202,16 @@ matching the regexps RE:
 Each of these keywords may appear multiple times.
 Other keywords:
 
-:bool BOOL        Combine the search for multiple fields using BOOL.
-                  BOOL may be either `or' (match either field)
-                  or `and' (match all fields) with default `or'.
+:bool FUN         Combine the search for multiple fields using FUN.
+                  FUN must be a function that takes as many arguments
+                  as there are search keywords in SPEC, for example
+                  `or' (match either field, the default)
+                  or `and' (match all fields).
+:invert VAL       Invert the search if VAL is non-nil.
+                  The default is the return value of `bbdb-search-invert-p'.
+:case-fold VAL    Searches ignore case if VAL is non-nil.
+                  The default is the value of `bbdb-case-fold-search'.
 
-To reverse the search, bind `bbdb-search-invert' to t.
 See also `bbdb-message-search' for fast searches using `bbdb-hashtable'
 but not allowing for regexps.
 
@@ -228,16 +233,18 @@ This usage is discouraged."
             (push (list key val) newspec)))
       (setq spec (apply #'append newspec))))
 
-  (let* ((count 0)
-         (sym-list (mapcar (lambda (_)
-                             (make-symbol
-                              (format "bbdb-re-%d" (setq count (1+ count)))))
-                           spec))
-         (bool (make-symbol "bool"))
-         (not-invert (make-symbol "not-invert"))
-         (matches (make-symbol "matches"))
-         keyw re-list clauses)
-    (set bool ''or) ; default
+  ;; The following defaults are motivated historically by the use
+  ;; of `bbdb-search' in interactive commands.
+  ;; Non-interactively these defaults may not always be useful.
+  (let ((bool 'or) ; default
+        (case-fold 'bbdb-case-fold-search) ; default
+        (invert '(bbdb-search-invert-p)) ; default
+        (sym-list (let ((count 0))
+                    (mapcar (lambda (_)
+                              (make-symbol
+                               (format "bbdb-re-%d" (setq count (1+ count)))))
+                            spec)))
+        keyw re-list clauses)
 
     ;; Check keys.
     (while (keywordp (setq keyw (car spec)))
@@ -336,7 +343,7 @@ This usage is discouraged."
          (let ((sym (pop sym-list)))
            (push `(,sym ,(pop spec)) re-list)
            (push `(let ((mails (bbdb-record-mail record))
-                        (bbdb-case-fold-search t) ; there is no case for mails
+                        (case-fold-search t) ; there is no case for mails
                         m done)
                     (if mails
                         (while (and (setq m (pop mails)) (not done))
@@ -383,31 +390,36 @@ This usage is discouraged."
                  clauses)))
 
         (`:bool
-         (set bool (pop spec)))
+         (setq bool (pop spec)))
+
+        (`:invert
+         (setq invert (pop spec)))
+
+        (`:case-fold
+         (setq case-fold (pop spec)))
 
         ;; Do we need other keywords?
 
-        (_ (error "Keyword `%s' undefines" keyw))))
-
-    `(let ((case-fold-search bbdb-case-fold-search)
-           (,not-invert (not (bbdb-search-invert-p)))
-           ,@re-list ,matches)
-       ;; Are there any use cases for `bbdb-search' where BOOL is only
-       ;; known at run time?  A smart byte compiler will hopefully
-       ;; simplify the code below if we know BOOL already at compile time.
-       ;; Alternatively, BOOL could also be a user function that
-       ;; defines more complicated boolian expressions.  Yet then we loose
-       ;; the efficiency of `and' and `or' that evaluate its arguments
-       ;; as needed.  We would need instead boolian macros that the compiler
-       ;; can analyze at compile time.
-       (if (eq 'and ,(symbol-value bool))
-           (dolist (record ,records)
-             (unless (eq ,not-invert (not (and ,@clauses)))
-                 (push record ,matches)))
+        (_ (error "Keyword `%s' undefined" keyw))))
+
+    ;; The clauses have the same order as the keywords.
+    (setq clauses (nreverse clauses))
+
+    ;; Silly me!  For the keyword :bool, we used to use double-quoted
+    ;; arguments like ":bool 'or".  Strip off one quote to preserve
+    ;; backward compatibility.
+    (if (eq 'quote (car-safe bool))
+        (setq bool (cadr bool)))
+
+    (let ((not-invert (make-symbol "not-invert"))
+          (matches (make-symbol "matches")))
+      `(let ((case-fold-search ,case-fold)
+             (,not-invert (not ,invert))
+             ,@re-list ,matches)
          (dolist (record ,records)
-           (unless (eq ,not-invert (not (or ,@clauses)))
-               (push record ,matches))))
-       (nreverse ,matches))))
+           (unless (eq ,not-invert (not (,bool ,@clauses)))
+             (push record ,matches)))
+         (nreverse ,matches)))))
 
 (defun bbdb-search-read (&optional field)
   "Read regexp to search FIELD values of records.
@@ -432,7 +444,7 @@ in either the name(s), organization, address, phone, mail, 
or xfields."
   (let ((records (bbdb-search (bbdb-records) :all-names regexp
                               :organization regexp :mail regexp
                               :xfield (cons '* regexp)
-                              :phone regexp :address regexp :bool 'or)))
+                              :phone regexp :address regexp :bool or)))
     (if records
         (bbdb-display-records records layout nil t)
       (message "No records matching '%s'" regexp))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]