summaryrefslogtreecommitdiff
path: root/lisp/org/org-bbdb.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/org/org-bbdb.el')
-rw-r--r--lisp/org/org-bbdb.el125
1 files changed, 87 insertions, 38 deletions
diff --git a/lisp/org/org-bbdb.el b/lisp/org/org-bbdb.el
index b32899e5727..4dd6b2332c4 100644
--- a/lisp/org/org-bbdb.el
+++ b/lisp/org/org-bbdb.el
@@ -6,7 +6,7 @@
;; Thomas Baumann <thomas dot baumann at ch dot tum dot de>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
-;; Version: 6.02b
+;; Version: 6.05a
;;
;; This file is part of GNU Emacs.
;;
@@ -30,7 +30,6 @@
;; Org-mode loads this module by default - if this is not what you want,
;; configure the variable `org-modules'.
-
;; It also implements an interface (based on Ivar Rummelhoff's
;; bbdb-anniv.el) for those org-mode users, who do not use the diary
;; but who do want to include the anniversaries stored in the BBDB
@@ -77,7 +76,10 @@
;; 1973-06-22
;; 20??-??-?? wedding
;; 1998-03-12 %s created bbdb-anniv.el %d years ago
-
+;;
+;; From Org's agenda, you can use `C-c C-o' to jump to the BBDB
+;; link from which the entry at point originates.
+;;
;;; Code:
(require 'org)
@@ -100,7 +102,7 @@
(declare-function calendar-leap-year-p "calendar" (year))
(declare-function diary-ordinal-suffix "diary-lib" (n))
-(defvar date)
+(defvar date) ;; dynamically scoped from Org
;; Customization
@@ -115,8 +117,16 @@
:require 'bbdb)
(defcustom org-bbdb-anniversary-format-alist
- '( ("birthday" . "Birthday: %s (%d%s)")
- ("wedding" . "%s's %d%s wedding anniversary") )
+ '(("birthday" lambda
+ (name years suffix)
+ (concat "Birthday: [[bbdb:" name "][" name " ("
+ (number-to-string years)
+ suffix ")]]"))
+ ("wedding" lambda
+ (name years suffix)
+ (concat "[[bbdb:" name "][" name "'s "
+ (number-to-string years)
+ suffix " wedding anniversary]]")))
"How different types of anniversaries should be formatted.
An alist of elements (STRING . FORMAT) where STRING is the name of an
anniversary class and format is either:
@@ -227,17 +237,19 @@ Argument STR is the anniversary field in BBDB."
(bbdb-string-trim (substring str pos)))
(list str nil))))
+(defvar org-bbdb-anniv-hash nil
+ "A hash holding anniversaries extracted from BBDB.
+The hash table is created on first use.")
-;;;###autoload
-(defun org-bbdb-anniversaries ()
- "Extract anniversaries from BBDB for display in the agenda."
- (require 'diary-lib)
- (let ((dates (list (cons (cons (car date) ; month
- (nth 1 date)) ; day
- (nth 2 date)))) ; year
- (text ())
- annivs date years
- split class form)
+(defvar org-bbdb-updated-p t
+ "This is non-nil if BBDB has been updated since we last built the hash.")
+
+(defun org-bbdb-make-anniv-hash ()
+ "Create a hash with anniversaries extracted from BBDB, for fast access.
+The anniversaries are assumed to be stored `org-bbdb-anniversary-field'."
+
+ (let (split tmp annivs)
+ (clrhash org-bbdb-anniv-hash)
(dolist (rec (bbdb-records))
(when (setq annivs (bbdb-record-getprop
rec org-bbdb-anniversary-field))
@@ -246,33 +258,70 @@ Argument STR is the anniversary field in BBDB."
(setq split (org-bbdb-anniv-split (pop annivs)))
(multiple-value-bind (m d y)
(funcall org-bbdb-extract-date-fun (car split))
+ (setq tmp (gethash (list m d) org-bbdb-anniv-hash))
+ (puthash (list m d) (cons (list y
+ (bbdb-record-name rec)
+ (cadr split))
+ tmp)
+ org-bbdb-anniv-hash))))))
+ (setq org-bbdb-updated-p nil))
+
+(defun org-bbdb-updated (rec)
+ "Record the fact that BBDB has been updated.
+This is used by Org to re-create the anniversary hash table."
+ (setq org-bbdb-updated-p t))
- (when (and (or (setq date (assoc (cons m d) dates))
- (and (= d 29)
- (= m 2)
- (setq date (assoc '(3 . 1) dates))
- (not (calendar-leap-year-p (cdr date)))))
- (< 0 (setq years (- (cdr date) y))))
- (let* ((class (or (cadr split)
- org-bbdb-default-anniversary-format))
- (form (or (cdr (assoc class
- org-bbdb-anniversary-format-alist))
- class)) ; (as format string)
- (name (bbdb-record-name rec))
- (suffix (diary-ordinal-suffix years))
- (tmp (cond
- ((functionp form)
- (funcall form name years suffix))
- ((listp form) (eval form))
- (t (format form name years suffix)))))
- (if text
- (setq text (append text (list tmp)))
- (setq text (list tmp))))
- )))))
+(add-hook 'bbdb-after-change-hook 'org-bbdb-updated)
+
+;;;###autoload
+(defun org-bbdb-anniversaries()
+ "Extract anniversaries from BBDB for display in the agenda."
+ (require 'diary-lib)
+ (unless (hash-table-p org-bbdb-anniv-hash)
+ (setq org-bbdb-anniv-hash
+ (make-hash-table :test 'equal :size 366)))
+
+ (when (or org-bbdb-updated-p
+ (= 0 (hash-table-count org-bbdb-anniv-hash)))
+ (org-bbdb-make-anniv-hash))
+
+ (let* ((m (car date)) ; month
+ (d (nth 1 date)) ; day
+ (y (nth 2 date)) ; year
+ (annivs (gethash (list m d) org-bbdb-anniv-hash))
+ (text ())
+ split class form rec)
+
+ ;; we don't want to miss people born on Feb. 29th
+ (when (and (= m 3) (= d 1) (not (calendar-leap-year-p y)))
+ (setq annivs (cons annivs (gethash (list 2 29) org-bbdb-anniv-hash))))
+
+ (when annivs
+ (while (setq rec (pop annivs))
+ (when rec
+ (let* ((class (or (nth 2 rec)
+ org-bbdb-default-anniversary-format))
+ (form (or (cdr (assoc class
+ org-bbdb-anniversary-format-alist))
+ class)) ; (as format string)
+ (name (nth 1 rec))
+ (years (- y (car rec)))
+ (suffix (diary-ordinal-suffix years))
+ (tmp (cond
+ ((functionp form)
+ (funcall form name years suffix))
+ ((listp form) (eval form))
+ (t (format form name years suffix)))))
+ (org-add-props tmp nil 'org-bbdb-name name)
+ (if text
+ (setq text (append text (list tmp)))
+ (setq text (list tmp)))))
+ ))
(when text
(mapconcat 'identity text "; "))))
(provide 'org-bbdb)
;; arch-tag: 9e4f275d-d080-48c1-b040-62247f66b5c2
+
;;; org-bbdb.el ends here