Source

bbdb / lisp / bbdb-sc.el

Full commit
;;; -*- Mode:Emacs-Lisp -*-

;;; This file is an addition to the Insidious Big Brother Database
;;; (aka BBDB), copyright (c) 1991, 1992 Jamie Zawinski
;;; <jwz@jwz.org>.
;;; 
;;; The Insidious Big Brother Database is free software; you can redistribute
;;; it and/or modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 1, or (at your
;;; option) any later version.
;;;
;;; BBDB is distributed in the hope that it will be useful, but WITHOUT ANY
;;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
;;; details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Emacs; see the file COPYING.  If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.


;;; This file was written by Martin Sjolin <marsj@ida.liu.se>
;;; based the original code by Tom Tromey <tromey@busco.lanl.gov>.
;;;
;;; Thanks to Richard Stanton <stanton@haas.berkeley.edu> for ideas
;;; for improvements and to Michael D. Carney  <carney@ltx-tr.com>
;;; for testing and feedback.
 
;;; 1998/04/11 07:18:18 by simmonmt
;;; 1.10

;;; This file adds the ability to define attributions for Supercite in
;;; a BBDB, enables you to retrieve your standard attribution from
;;; BBDB. If the from header in the mail to which you are replying
;;; only contains the e-mail address, the personal name is lookup in
;;; BBDB. You need Supercite to make this code work. The attribution
;;; os is stored under the key `attribution' (unless you've changed
;;; bbdb/sc-attribution-field).

;;; To use enable this code you will have to the "sc-consult" to your
;;; sc-preferred-attribution-list. This file sets variable if it is not
;;; set and isues an warning message if "sc-consult" is not included.
;;;
;;;   (setq sc-preferred-attribution-list
;;;     '("sc-lastchoice" "x-attribution" "sc-consult" 
;;;       "initials" "firstname" "lastname"))
;;;
;;;
;;; We also set the sc-attrib-selection-list below if is not bound, if
;;; you have your own special sc-attrib-selection-list, please add
;;; an expression as below:
;;;
;;;   (setq sc-attrib-selection-list
;;;        '(("sc-from-address" ((".*" . (bbdb/sc-consult-attr
;;;				       (sc-mail-field "sc-from-address")))))))
;;;
;;; And finally we set the sc-mail-glom-frame to enable the
;;; fetching of the name of person when there is only an e-mail
;;; address in the original mail:
;;; 
;;;  (setq sc-mail-glom-frame
;;;    '((begin                        (setq sc-mail-headers-start (point)))
;;;      ("^x-attribution:[ \t]+.*$"   (sc-mail-fetch-field t) nil t)
;;;      ("^\\S +:.*$"                 (sc-mail-fetch-field) nil t)
;;;      ("^$"                         (progn (bbdb/sc-default)
;;;  					 (list 'abort '(step . 0))))
;;;      ("^[ \t]+"                    (sc-mail-append-field))
;;;      (sc-mail-warn-if-non-rfc822-p (sc-mail-error-in-mail-field))
;;;      (end                          (setq sc-mail-headers-end (point)))))
;;;
;;;

;;;
; bbdb-sc.el,v
; Revision 1.10  1998/04/11 07:18:18  simmonmt
; Colin Rafferty's patch adding autoload cookies back
;
; Revision 1.9  1998/02/23 07:22:00  simmonmt
; Fixed intro comments.  Use add-hook, not bbdb-add-hook
;
; Revision 1.8  1998/01/06 06:12:32  simmonmt
; Customized variables, removed autoloads, and added provide of bbdb-sc
;
; Revision 1.7  1997/11/02 07:46:44  simmonmt
; Welcome to the family.  Moved the automatically running code into
; functions.  Generalized attribution field.
;
; Revision 1.6  1995/03/28  12:11:01  marsj
; Added original source and thanks
;
; Revision 1.5  1995/03/28  11:38:20  marsj
; Moved the defvar before the require for bbdb and sc
;
; Revision 1.4  1995/03/27  16:13:40  marsj
; If setup variables are not bound, set them using defvar.
;
; Revision 1.3  1995/03/26  18:58:59  marsj
; *** empty log message ***
;
; Revision 1.2  1995/03/25  15:05:02  marsj
; Added require and insertion of hooks
;
; Revision 1.1  1995/03/25  15:00:56  marsj
; Initial revision
;;;

;;; packages
(require 'bbdb)
(require 'supercite)

;;; User variable(s)
(defcustom bbdb/sc-replace-attr-p t
 "t if you like to create a new BBDB entry when 
entering a non-default attribution, 'ask if the user
should be asked before creation and NIL if we never create a new entry."
 :group 'bbdb-utilities-supercite
 :type '(choice (const "Create a new BBDB entry" t)
		(const "Confirm new record creation" ask)
		(const "Don't create a new entry" nil)))

(defcustom bbdb/sc-attribution-field 'attribution
  "The BBDB field used for Supercite attribution information."
  :group 'bbdb-utilities-supercite
  :type '(symbol :tag "Field name"))

;;; Code starts 
(defcustom bbdb/sc-last-attribution ""
 "Default attribution return by the SuperCite citation engine,
used to compare against citation selected by the user."
 :group 'bbdb-utilities-supercite
 :type '(string :tag "Default citation" ""))

(defun bbdb/sc-consult-attr (from)
  "Extract citing information from BBDB using sc-consult where
FROM is user e-mail address to look for in BBDB."
    ;; if logged in user sent this, use recipients.
    (let ((check (if (or (null from)
			 (string-match (bbdb-user-mail-names) from))
		     (car (cdr (mail-extract-address-components 
				(or (sc-mail-field "to") from))))
		   from)))
      (if from
	  (let ((record (bbdb-search-simple nil from)))
	    (and record (bbdb-record-getprop record bbdb/sc-attribution-field))))))

(defun bbdb/sc-set-attr ()
  "Add attribute to BBDB."
  (let ((from (sc-mail-field "from"))
	(address (sc-mail-field "sc-from-address"))
	(attr (sc-mail-field "sc-attribution")))
    (if (and from attr bbdb/sc-replace-attr-p
	    (not (string-equal attr bbdb/sc-last-attribution))
	    (not (string-match (bbdb-user-mail-names) address)))
	(let* ((bbdb-notice-hook nil)
	       ;; avoid noticing any headers in the reply message
	       (record (bbdb-annotate-message-sender 
		       from t
		       (bbdb-invoke-hook-for-value 
			bbdb/mail-auto-create-p) t)))
	  (if record
	      (let ((old (bbdb-record-getprop record 'attribution)))
		;; ignore if we have an value and same value
		(if (and (not (and old (string-equal old attr)))
			 (or (not (eq bbdb/sc-replace-attr-p 'ask))
			     (y-or-n-p (concat "Change attribution " attr))))
		    (progn (bbdb-record-putprop record
						bbdb/sc-attribution-field attr)
			   (bbdb-change-record record nil)))))))))

(defun bbdb/sc-default ()
  "If the current \"from\" field in sc-mail-info alist 
contains only an e-mail address, lookup e-mail address in
BBDB, and prepend a new \"from\" field to sc-mail-info."
  (let* ((from   (sc-mail-field "from"))
	 (pair   (and from (mail-extract-address-components from))))
    (if (and pair (not (car pair)))
	(let* ((record (bbdb-search-simple nil (car (cdr pair))))
	       (name   (and record (bbdb-record-name record))))
	  (if name	  
	      (setq sc-mail-info 
		    (cons (cons "from" 
				(format "%s (%s)" (car (cdr pair)) name))
			  sc-mail-info)))))))

;;; setup the default setting of the variables
(defun bbdb/sc-setup-variables ()
  "Set up the various Supercite variables for the BBDB.
`sc-preferred-attribution-list', `sc-attrib-selection-list', and
`sc-mail-glom-frame' are set, but only if they have not previously
been defined.  It is strongly suggested that you not call this
function directly, but that you use this function (specifically the
settings contained herein) as an example.  In other words, set these
variables yourself, either in your Emacs configuration file or using
Custom."

  ;; check for sc-consult in sc-preferred-attribution-list
  (if (boundp 'sc-preferred-attribution-list)
      (or (member '"sc-consult" sc-preferred-attribution-list)
	  (bbdb-warn (concat "\"sc-consult\" not included in "
			     "sc-preferred-attribution-list.  Attributions cannot"
			     "be gathered from the BBDB without \"sc-consult\""
			     "in sc-preferred-attribution-list")))
    (defvar sc-preferred-attribution-list
      '("sc-lastchoice" "x-attribution" "sc-consult" 
        "initials" "firstname" "lastname")))
  
  ;; check sc-attrib-selection-list
  (defvar sc-attrib-selection-list
    '(("sc-from-address" 
       ((".*" . (bbdb/sc-consult-attr 
		 (sc-mail-field "sc-from-address")))))))
  
  ;; set sc-mail-glom-frame
  (defvar sc-mail-glom-frame
    '((begin                        (setq sc-mail-headers-start (point)))
      ("^x-attribution:[ \t]+.*$"   (sc-mail-fetch-field t) nil t)
      ("^\\S +:.*$"                 (sc-mail-fetch-field) nil t)
      ("^$"                         (progn (bbdb/sc-default)
					   (list 'abort '(step . 0))))
      ("^[ \t]+"                    (sc-mail-append-field))
      (sc-mail-warn-if-non-rfc822-p (sc-mail-error-in-mail-field))
      (end                          (setq sc-mail-headers-end (point))))))

;; insert our hooks - call me from your Emacs initialization file
;;;###autoload
(defun bbdb-insinuate-sc ()
  "Call this function to hook BBDB into Supercite."
  
  (add-hook 'sc-post-hook 'bbdb/sc-set-attr)
  (add-hook 'sc-attribs-postselect-hook 
		 (function (lambda()
			     (setq bbdb/sc-last-attribution 
				   (if sc-downcase-p 
				       (downcase attribution) attribution))))))

(provide 'bbdb-sc)
;;; end of bbdb-sc.el