summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrégoire Jadi <gregoire.jadi@gmail.com>2013-02-14 16:35:29 (GMT)
committer Grégoire Jadi <gregoire.jadi@gmail.com>2013-02-14 20:21:44 (GMT)
commit5800920c992839216134add11f44ed234f093209 (patch)
treee60974eb9e632db04e7300bb5e56f2a5e6c8260c
parent8768fd125fea6d814e12612e76ddcd79005d92d0 (diff)
downloadorg-mode-5800920c992839216134add11f44ed234f093209.zip
org-mode-5800920c992839216134add11f44ed234f093209.tar.gz
Add caching mecanism
* contrib/lisp/org-contacts.el: Add a caching mecanism around `org-contacts-filter'.
-rw-r--r--contrib/lisp/org-contacts.el74
1 files changed, 50 insertions, 24 deletions
diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el
index 49bf489..7af8c35 100644
--- a/contrib/lisp/org-contacts.el
+++ b/contrib/lisp/org-contacts.el
@@ -139,38 +139,64 @@ This overrides `org-email-link-description-format' if set."
map)
"The keymap used in `org-contacts' result list.")
+(defvar org-contacts-db nil
+ "Org Contacts database.")
+
+(defvar org-contacts-last-update nil
+ "Last time the Org Contacts database has been updated.")
+
(defun org-contacts-files ()
"Return list of Org files to use for contact management."
(or org-contacts-files (org-agenda-files t 'ifmode)))
-(defun org-contacts-filter (&optional name-match tags-match)
- "Search for a contact maching NAME-MATCH and TAGS-MATCH.
-If both match values are nil, return all contacts."
+(defun org-contacts-db ()
+ "Return the latest Org Contacts Database"
(let* (todo-only
- (tags-matcher
- (if tags-match
- (cdr (org-make-tags-matcher tags-match))
- t))
- (name-matcher
- (if name-match
- '(org-string-match-p name-match (org-get-heading t))
- t))
(contacts-matcher
(cdr (org-make-tags-matcher org-contacts-matcher)))
+ (need-update?
+ (or (null org-contacts-last-update)
+ (some (lambda (file)
+ (time-less-p org-contacts-last-update
+ (elt (file-attributes file) 5)))
+ (org-contacts-files))))
markers result)
- (dolist (file (org-contacts-files))
- (org-check-agenda-file file)
- (with-current-buffer (org-get-agenda-file-buffer file)
- (unless (eq major-mode 'org-mode)
- (error "File %s is no in `org-mode'" file))
- (org-scan-tags
- '(add-to-list 'markers (set-marker (make-marker) (point)))
- `(and ,contacts-matcher ,tags-matcher ,name-matcher)
- todo-only)))
- (dolist (marker markers result)
- (org-with-point-at marker
- (add-to-list 'result
- (list (org-get-heading t) marker (org-entry-properties marker 'all)))))))
+ (when need-update?
+ (message "Update Org Contacts Database")
+ (dolist (file (org-contacts-files))
+ (org-check-agenda-file file)
+ (with-current-buffer (org-get-agenda-file-buffer file)
+ (unless (eq major-mode 'org-mode)
+ (error "File %s is no in `org-mode'" file))
+ (org-scan-tags
+ '(add-to-list 'markers (set-marker (make-marker) (point)))
+ contacts-matcher
+ todo-only)))
+ (dolist (marker markers result)
+ (org-with-point-at marker
+ (add-to-list 'result
+ (list (org-get-heading t) marker (org-entry-properties marker 'all)))))
+ (setf org-contacts-db result
+ org-contacts-last-update (current-time)))
+ org-contacts-db))
+
+(defun org-contacts-filter (&optional name-match tags-match)
+ "Search for a contact maching NAME-MATCH and TAGS-MATCH.
+If both match values are nil, return all contacts."
+ (if (and (null name-match)
+ (null tags-match))
+ (org-contacts-db)
+ (loop for contact in (org-contacts-db)
+ if (or
+ (and name-match
+ (org-string-match-p name-match
+ (first contact)))
+ (and tags-match
+ (some (lambda (tag)
+ (org-string-match-p tags-match tag))
+ (org-split-string
+ (or (cdr (assoc-string "ALLTAGS" (caddr contact))) "") ":"))))
+ collect contact)))
(when (not (fboundp 'completion-table-case-fold))
;; That function is new in Emacs 24...