[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/ebdb 80ef19d 108/350: Make ebdb-search-read and ebdb-se
From: |
Eric Abrahamsen |
Subject: |
[elpa] externals/ebdb 80ef19d 108/350: Make ebdb-search-read and ebdb-search-field into generics |
Date: |
Mon, 14 Aug 2017 11:46:16 -0400 (EDT) |
branch: externals/ebdb
commit 80ef19d0ad612cfbe13d456c2069821bc7d129f6
Author: Eric Abrahamsen <address@hidden>
Commit: Eric Abrahamsen <address@hidden>
Make ebdb-search-read and ebdb-search-field into generics
* ebdb.el (ebdb-search-read): Each field class has the potential to
prompt the user for its own search criteria, which are then fed back
to its own implementation of `ebdb-search-field'.
(ebdb-record-search): Fix the 'user implementation of this method,
now works with record labels again.
* ebdb-com.el: Change interactive calls to `ebdb-search-read' to use
the field class instead of string prompt, where appropriate.
* ebdb-org.el: Provide `ebdb-search-read' and `ebdb-field-search'
methods for the org tags class.
---
ebdb-com.el | 14 ++--
ebdb-org.el | 15 ++++
ebdb.el | 223 +++++++++++++++++++++++++++++++++---------------------------
3 files changed, 146 insertions(+), 106 deletions(-)
diff --git a/ebdb-com.el b/ebdb-com.el
index db8c2ed..496bbcc 100644
--- a/ebdb-com.el
+++ b/ebdb-com.el
@@ -1910,7 +1910,7 @@ not necessarily. FMT is the optional formatter to use."
"Display all records in the EBDB matching REGEXP
in either the name(s), organization, address, phone, mail, or xfields."
(interactive (list (ebdb-search-style)
- (ebdb-search-read)
+ (ebdb-search-read 'all)
(ebdb-formatter-prefix)))
(ebdb-search-display style `((name ,regexp)
(organization ,regexp)
@@ -1942,7 +1942,7 @@ in either the name(s), organization, address, phone,
mail, or xfields."
(defun ebdb-search-address (style regexp &optional fmt)
"Display all records in the EBDB matching REGEXP in the address fields."
(interactive (list (ebdb-search-style)
- (ebdb-search-read "address")
+ (ebdb-search-read ebdb-default-address-class)
(ebdb-formatter-prefix)))
(ebdb-search-display style `((address ,regexp)) fmt))
@@ -1950,7 +1950,7 @@ in either the name(s), organization, address, phone,
mail, or xfields."
(defun ebdb-search-mail (style regexp &optional fmt)
"Display all records in the EBDB matching REGEXP in the mail address."
(interactive (list (ebdb-search-style)
- (ebdb-search-read "mail address")
+ (ebdb-search-read ebdb-default-mail-class)
(ebdb-formatter-prefix)))
(ebdb-search-display style `((mail ,regexp)) fmt))
@@ -1958,7 +1958,7 @@ in either the name(s), organization, address, phone,
mail, or xfields."
(defun ebdb-search-phone (style regexp &optional fmt)
"Display all records in the EBDB matching REGEXP in the phones field."
(interactive (list (ebdb-search-style)
- (ebdb-search-read "phone")
+ (ebdb-search-read ebdb-default-phone-class)
(ebdb-formatter-prefix)))
(ebdb-search-display style `((phone ,regexp)) fmt))
@@ -1966,7 +1966,7 @@ in either the name(s), organization, address, phone,
mail, or xfields."
(defun ebdb-search-notes (style regexp &optional fmt)
"Display all records in the EBDB matching REGEXP in the phones field."
(interactive (list (ebdb-search-style)
- (ebdb-search-read "notes")
+ (ebdb-search-read ebdb-default-notes-class)
(ebdb-formatter-prefix)))
(ebdb-search-display style `((notes ,regexp)) fmt))
@@ -1996,9 +1996,9 @@ in either the name(s), organization, address, phone,
mail, or xfields."
(if (null field) '* field)
(ebdb-search-read (if (null field)
"any user field"
- (car field)))
+ (cdr field)))
(ebdb-formatter-prefix))))
- (ebdb-search-display style `((user ,(cons field regexp))) fmt))
+ (ebdb-search-display style `((user ,(list field regexp))) fmt))
;;;###autoload
(defun ebdb-search-changed (&optional fmt)
diff --git a/ebdb-org.el b/ebdb-org.el
index 411e93c..761094e 100644
--- a/ebdb-org.el
+++ b/ebdb-org.el
@@ -142,6 +142,21 @@ potential tags for completion.")
(when obj (ebdb-string obj)))))
(cl-call-next-method field (plist-put slots :tags val))))
+(cl-defmethod ebdb-search-read ((class (subclass ebdb-org-field-tags)))
+ (let ((crm-separator (cadr (assq 'ebdb-org-field-tags
ebdb-separator-alist))))
+ (completing-read-multiple
+ "Search for tags: "
+ (append (org-global-tags-completion-table)
+ (when ebdb-org-tags
+ (mapcar #'list ebdb-org-tags)))
+ nil nil)))
+
+(cl-defmethod ebdb-field-search ((field ebdb-org-field-tags) (tag-list list))
+ (catch 'found
+ (dolist (tag (slot-value field 'tags) nil)
+ (when (member tag tag-list)
+ (throw 'found t)))))
+
(cl-defmethod ebdb-init-field ((field ebdb-org-field-tags) _record)
(let ((tags (slot-value field 'tags)))
(dolist (tag tags)
diff --git a/ebdb.el b/ebdb.el
index 5c171dc..6620a91 100644
--- a/ebdb.el
+++ b/ebdb.el
@@ -607,11 +607,6 @@ MESSAGE-HEADERS is a list of all the headers of the
incoming
message."
nil)
-(cl-defmethod ebdb-field-search ((field ebdb-field) (regex string))
- (condition-case nil
- (string-match-p regex (ebdb-string field))
- (cl-no-applicable-method nil)))
-
;;; The UUID field.
;; This was originally just a string-value slot, but it was such a
@@ -904,13 +899,6 @@ first one."
(cl-call-next-method class slots obj))
(ebdb-parse class (ebdb-read-string "Name: " (when obj (ebdb-string obj)))
slots)))
-(cl-defmethod ebdb-field-search ((_field ebdb-field-name-complex) _regex)
- "Short-circuit the plain field search for names.
-
-The record itself performs more complex searches on cached name
-values, by default the search is not handed to the name field itself."
- nil)
-
(cl-defmethod ebdb-parse ((class (subclass ebdb-field-name-complex)) str
&optional slots)
(let ((bits (ebdb-divide-name str)))
(unless (plist-get slots :given-names)
@@ -1969,57 +1957,6 @@ only return fields that are suitable for user editing.")
;; Implement this later.
t)
-(cl-defmethod ebdb-record-search ((record ebdb-record)
- (_type (eql name))
- (regexp string))
- (or (string-match-p regexp (or (ebdb-record-name record) ""))
- (seq-find
- (lambda (n)
- (string-match-p regexp n))
- (ebdb-record-alt-names record))
- (ebdb-field-search (slot-value record 'name) regexp)))
-
-(cl-defmethod ebdb-record-search ((record ebdb-record)
- (_type (eql notes))
- (regexp string))
- (if-let (notes (slot-value record 'notes))
- (string-match-p regexp (ebdb-string notes))))
-
-(cl-defmethod ebdb-record-search ((record ebdb-record)
- (_type (eql user))
- search-clause)
- (pcase search-clause
- (`(* . ,(and regexp (pred stringp)))
- ;; check all user fields
- (catch 'found
- (dolist (f (ebdb-record-user-fields record))
- (when (or (string-match-p regexp (ebdb-string f))
- (and (slot-exists-p f 'object-name)
- (string-match-p regexp (slot-value f 'object-name))))
- (throw 'found t)))
- ;; so that "^$" can be used to find records that
- ;; have no notes
- (when (string-match-p regexp "")
- (throw 'found t))))
- (`((,(and field-string (pred stringp)) . ,(and class (pred symbolp))) .
,(and regexp (pred stringp))) ; check one field
- (catch 'found
- (if (eql class 'ebdb-field-class-simple)
- (when (string-match-p
- regexp (ebdb-string
- (ebdb-record-user-field record field-string)))
- (throw 'found t))
- (dolist (f (ebdb-record-user-fields record))
- ;; If it's not a `ebdb-field-class-simple', the
- ;; "field-string" is always going to be the same. Just
- ;; check if the regexp matches either the label, if there
- ;; is one, or the value.
- (when (and (object-of-class-p f class)
- (or (and (slot-exists-p f 'object-name)
- (string-match-p regexp (slot-value f
'object-name)))
- (string-match-p regexp (ebdb-string f))))
- (throw 'found t))))))
- (_ nil)))
-
;; TODO: rename this to `ebdb-record-name-string', it's confusing.
(cl-defmethod ebdb-record-name ((record ebdb-record))
"Get or set-and-get the cached name string of RECORD."
@@ -2203,39 +2140,6 @@ priority."
(let ((mails (ebdb-record-mail record t)))
(object-assoc 'primary 'priority mails)))
-(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
- (_type (eql phone))
- (regexp string))
- (let ((phones (ebdb-record-phone record)))
- (if phones
- (catch 'found
- (dolist (ph phones)
- (when (ebdb-field-search ph regexp)
- (throw 'found t))))
- (string-match-p regexp ""))))
-
-(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
- (_type (eql address))
- (regexp string))
- (let ((adds (ebdb-record-address record)))
- (if adds
- (catch 'found
- (dolist (a adds)
- (when (ebdb-field-search a regexp)
- (throw 'found t))))
- (string-match-p regexp ""))))
-
-(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
- (_type (eql mail))
- (regexp string))
- (let ((mails (ebdb-record-mail record t nil t)))
- (if mails
- (catch 'found
- (dolist (m mails)
- (when (ebdb-field-search m regexp)
- (throw 'found t))))
- (string-match-p regexp ""))))
-
;; This needs to be a :before method so that the 'address slot is
;; filled by the time we call `ebdb-init-field'.
(cl-defmethod ebdb-record-insert-field :before ((record ebdb-record-entity)
@@ -4595,10 +4499,131 @@ interpreted as t, ie the record passes."
(_ t))))))
records)))
-(defun ebdb-search-read (&optional field)
+(cl-defgeneric ebdb-field-search (field criterion)
+ "Return t if search CRITERION somehow matches the value of
+ FIELD.")
+
+(cl-defgeneric ebdb-record-search (record type criterion)
+ "Return t if CRITERION matches RECORD, given STYLE.")
+
+(cl-defmethod ebdb-field-search ((field ebdb-field) (regex string))
+ (condition-case nil
+ (string-match-p regex (ebdb-string field))
+ (cl-no-applicable-method nil)))
+
+(cl-defmethod ebdb-field-search ((field ebdb-field-labeled) (pair cons))
+ (let ((label (car pair))
+ (value (cdr pair)))
+ (and (or (null label)
+ (string-empty-p label)
+ (string-match-p label (slot-value field 'object-name)))
+ (or (null value)
+ (string-empty-p value)
+ (ebdb-field-search field value)))))
+
+(cl-defmethod ebdb-field-search ((_field ebdb-field-name-complex) _regex)
+ "Short-circuit the plain field search for names.
+
+The record itself performs more complex searches on cached name
+values, by default the search is not handed to the name field itself."
+ nil)
+
+(cl-defmethod ebdb-record-search ((record ebdb-record)
+ (_type (eql name))
+ (regexp string))
+ (or (string-match-p regexp (or (ebdb-record-name record) ""))
+ (seq-find
+ (lambda (n)
+ (string-match-p regexp n))
+ (ebdb-record-alt-names record))
+ (ebdb-field-search (slot-value record 'name) regexp)))
+
+(cl-defmethod ebdb-record-search ((record ebdb-record)
+ (_type (eql notes))
+ (regexp string))
+ (if-let (notes (slot-value record 'notes))
+ (string-match-p regexp (ebdb-string notes))))
+
+(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
+ (_type (eql phone))
+ (regexp string))
+ (let ((phones (ebdb-record-phone record)))
+ (if phones
+ (catch 'found
+ (dolist (ph phones)
+ (when (ebdb-field-search ph regexp)
+ (throw 'found t))))
+ (string-match-p regexp ""))))
+
+(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
+ (_type (eql address))
+ (regexp string))
+ (let ((adds (ebdb-record-address record)))
+ (if adds
+ (catch 'found
+ (dolist (a adds)
+ (when (ebdb-field-search a regexp)
+ (throw 'found t))))
+ (string-match-p regexp ""))))
+
+(cl-defmethod ebdb-record-search ((record ebdb-record-entity)
+ (_type (eql mail))
+ (regexp string))
+ (let ((mails (ebdb-record-mail record t nil t)))
+ (if mails
+ (catch 'found
+ (dolist (m mails)
+ (when (ebdb-field-search m regexp)
+ (throw 'found t))))
+ (string-match-p regexp ""))))
+
+(cl-defmethod ebdb-record-search ((record ebdb-record)
+ (_type (eql user))
+ search-clause)
+ (catch 'found
+ (pcase search-clause
+ (`(* ,(and regexp (pred stringp)))
+ ;; check all user fields
+ (dolist (f (ebdb-record-user-fields record))
+ (when (ebdb-field-search f regexp)
+ (throw 'found t)))
+ ;; so that "^$" can be used to find records that
+ ;; have no notes
+ (when (string-match-p regexp "")
+ (throw 'found t)))
+ (`((,(and label (pred stringp)) . ,'ebdb-field-user-simple) ,(and regexp
(pred stringp)))
+ (dolist (f (ebdb-record-user-fields record))
+ (when (and (object-of-class-p f ebdb-field-user-simple)
+ (ebdb-field-search f (cons label regexp)))
+ (throw 'found t))))
+ (`((,(and field-string (pred stringp)) . ,(and class (pred symbolp)))
,criterion) ; check one field
+ (dolist (f (ebdb-record-user-fields record))
+ (when (and (object-of-class-p f class)
+ (ebdb-field-search f criterion))
+ (throw 'found t))))
+ (_ nil))))
+
+(cl-defgeneric ebdb-search-read (field-class)
+ "Prompt the user for a search string to match against instances
+ of FIELD-CLASS.
+
+In most cases this is a simple regexp, but field classes can
+prompt users for more complex search criteria, if necessary.")
+
+(cl-defmethod ebdb-search-read ((cls (subclass ebdb-field)))
+ (read-string (format "Search records with %s %smatching regexp: "
+ (ebdb-field-readable-name cls)
+ (if ebdb-search-invert "not " ""))))
+
+(cl-defmethod ebdb-search-read ((field string))
"Read regexp to search FIELD values of records."
- (read-string (format "Search records%s %smatching regexp: "
- (if field (concat " with " field) "")
+ (read-string (format "Search records with %s %smatching regexp: "
+ field
+ (if ebdb-search-invert "not " ""))))
+
+(cl-defmethod ebdb-search-read ((_all symbol))
+ "Read regexp to search across all records."
+ (read-string (format "Search records %smatching regexp: "
(if ebdb-search-invert "not " ""))))
;; Create autoload statements for fields defined in other files.
- [elpa] externals/ebdb 5ec40d5 102/350: Add sections on searching and record marking to manual, (continued)
- [elpa] externals/ebdb 5ec40d5 102/350: Add sections on searching and record marking to manual, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 7da77f4 089/350: Expand ebdb-with-record-edits, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 8312ea4 109/350: Allow company-ebdb to work in notmuch-message-mode as well, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb dcb7dbc 104/350: Change default keybindings in Gnus, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 9ac0f0f 111/350: Searching on empty strings should happen in field-search method, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb c43e39b 097/350: Another round of compiler-inspired fixes, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 40df5bc 114/350: Remove ebdb-new-mails-primary, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 825c4cc 112/350: Simplify the structure of ebdb-org-hashtable, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb c0979b0 135/350: Typo in ebdb-mua-check-header, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 1219b93 100/350: Rework *EBDB* buffer searching, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 80ef19d 108/350: Make ebdb-search-read and ebdb-search-field into generics,
Eric Abrahamsen <=
- [elpa] externals/ebdb 6c85728 116/350: Manual and README additions, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 4688493 125/350: Wrap ebdb-parse in save-match-data, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 587ebbc 129/350: Use ebdb-prompt-for-record in org link completion, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 8f82b0f 121/350: Complete changes from ed3e270, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 9edc54f 120/350: Merge snarf branch, basic framework of snarfing in place, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 61b533c 127/350: Simplify ebdb-record-field for strings, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb b610b96 138/350: ebdb-record-search can accept symbols for search type, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb b9da0f4 142/350: Check Organization headers and display/update organization records, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 6fe34b0 145/350: Fix bugs in ebdb-annotate-message, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb f0b0a32 093/350: Fix organization name matching in migration, Eric Abrahamsen, 2017/08/14