Navigation: Table of Contents, Index, next: .emacs file by Alex, prev: Emacs BBDB Elisp Code Overview: * Unmigrating from file format 4 * Writing a .mailrc from BBDB * Writing a Pine addressbook from BBDB, by Matt McClure * Editing and formatting addresses with the country patch o A new address editing function o Adding a new formatting function + The identifying function + The formatting function + Print formatting of addresses Unmigrating from file format 4 (defun bbdb-unmigrate-stuff (&optional new-version) "Create a buffer with unmigrated BBDB data. Usefull if you fooled around with BBDB file format 4 by Alex and want to start using the official BBDB 2.00.06 again. In order to do that, you have to save your .bbdb in BBDB file format 3 instead of the file format 4 introduced by Alex. This function will create a *BBDB Version 3* buffer for you, which you can examine and save as your new .bbdb. The unmigration will strip the country fields of all entries in your BBDB as such a field did not exist in the BBDB file format 3 used in BBDB 2.00.06." (interactive "nUnmigrate to version (I recommend version 3): ") (if (null new-version) (setq new-version 3)) (if (>= new-version bbdb-file-format) (error "Current BBDB file format is version %d" bbdb-file-format) (let* ((records (bbdb-records)) (propnames (bbdb-with-db-buffer bbdb-propnames)) (rec) (bbdb-file-format-migration (cons bbdb-file-format new-version)) (buf (get-buffer-create (format "*BBDB Version %d*" (cdr bbdb-file-format-migration))))) (message "Unconverting the BBDB database...") (set-buffer buf) (erase-buffer) (insert (format (concat ";;; file-version: %d\n" ";;; user-fields: %S\n") new-version (mapcar (function (lambda (x) (intern (car x)))) propnames))) (while records (setq rec (copy-sequence (car records))) (bbdb-unmigrate-record rec) (aset rec 8 nil) (insert (format "%S\n" rec)) (setq records (cdr records))) (pop-to-buffer buf) (message "Unconverting the BBDB database...done")))) Writing a .mailrc from BBDB The following will export a very primitive version of your BBDB information into a .mailrc file which is used for normal mail(1) and Emacs Rmail. Usually the main problem when exporting BBDB to other formats is the creation of an ALIAS name. In my example below I just use LASTNAME. The following function tries to write your BBDB into a .mailrc file, like this: alias LASTNAME "FULL_NAME " mail-groups defined via the mail-alias field are not supported, but see Matt McClure's code further down the page for an example on how to do this. I used the same code as bbdb-print for the file-name. Unfortunately this very simple code must have a bug somewhere. It only occurs if you test it a lot: When you are prompted for a file-name, "~/bbdb.tex" or "~/.mailrc" is the default. Press RET. Sometimes this will find-file the correct file, and sometimes you will overwrite your selected buffer instead. I haven't looked into this, however. :( (defvar bbdb-mailrc-file-name ".mailrc" "Filename to write mail aliases to.") (defun bbdb-write-mailrc (visible-records to-file) (interactive (list (bbdb-do-all-records-p) (read-file-name "Export To File: " bbdb-mailrc-file-name))) (setq bbdb-mailrc-file-name (expand-file-name to-file)) ;; `good' are people with netaddresses, `bad' are people without. The ;; people are taken of the list records and put on either the good or ;; the bad list. (let ((good '()) (bad '()) (records (if (not visible-records) (bbdb-records) (set-buffer bbdb-buffer-name) (mapcar 'car bbdb-records)))) ;; Open .mailrc file (find-file bbdb-mailrc-file-name) (widen) (erase-buffer) ;; Loop through records to print. (while records (if (bbdb-record-net (car records)) (setq good (cons (car records) good)) (setq bad (cons (car records) bad))) (setq records (cdr records))) ;; write all net-addresses into .mailrc (insert (mapconcat (function (lambda (x) (let ((name (bbdb-dwim-net-address x)) (alias (bbdb-record-lastname x))) (concat "alias " alias " \"" (if (string-match "\"\\(.*\\)\"\\(.*\\)" name) (format "%s%s" (match-string 1 name) (match-string 2 name)) name) "\"")))) (nreverse good) "\n")) ;; Mail groups ;; not implemented, yet ;; Feedback on the output quality. (if bad (message "There were %d people with bad or missing net addresses." (length bad)) (message "Done.")))) Writing a Pine addressbook from BBDB, by Matt McClure From: Matt McClure Subject: Re: conversion to pine addressbook? Date: Wed, 25 Aug 1999 10:12:50 -0400 (EDT) It isn't pretty, but this will create a pine addressbook. It also supports the mail-alias field (inefficiently, but it works). I don't think it should be too difficult to modify to create mailrc files instead. Thanks to Alex for the start. Matt ;;;;; (defvar bbdb-mailrc-file-name "~/.addressbook" "Filename to write mail aliases to.") (defun bbdb-write-dot-addressbook (to-file) (interactive (list (read-file-name "Export To File: " "" nil nil bbdb-mailrc-file-name))) (setq bbdb-mailrc-file-name (expand-file-name to-file)) ;; `good' are people with netaddresses, `bad' are people without. The ;; people are taken of the list records and put on either the good or ;; the bad list. (let ((good '()) (bad '()) (records (bbdb-records)) (grouped-good '()) (grouped-bad '()) (grouped-records (bbdb-records)) (mail-groups-alist '())) ;; Open .mailrc file (find-file bbdb-mailrc-file-name) (widen) (erase-buffer) ;; Loop through records to print. (while records (if (bbdb-record-net (car records)) (setq good (cons (car records) good)) (setq bad (cons (car records) bad))) (setq records (cdr records))) ;; write all net-addresses into .mailrc (insert (mapconcat (function (lambda (x) (let ((alias (concat (bbdb-record-firstname x) " " (bbdb-record-lastname x))) (name (concat (bbdb-record-lastname x) ", " (bbdb-record-firstname x))) (email (car (bbdb-record-net x))) ) (concat alias "\t" name "\t" email ) ))) (nreverse good) "\n")) ;; Mail groups ;; get the mail-aliases (while grouped-records (if (and (bbdb-record-net (car grouped-records)) (assoc 'mail-alias (bbdb-record-raw-notes (car grouped-records)))) (setq grouped-good (cons (car grouped-records) grouped-good)) (setq grouped-bad (cons (car grouped-records) grouped-bad))) (setq grouped-records (cdr grouped-records))) (while grouped-good (let ((aliases (split-string (cdr (assoc 'mail-alias (bbdb-record-raw-notes (car grouped-good)))) "[, \f\t\n\r\v]+"))) (while aliases ;; store the name associated with alias somehow (setq mail-groups-alist (cons (cons (car aliases) (concat "\"" (bbdb-record-firstname (car grouped-good)) " " (bbdb-record-lastname (car grouped-good)) "\"")) mail-groups-alist)) (setq aliases (cdr aliases)))) (setq grouped-good (cdr grouped-good))) (setq mail-groups-alist (sort mail-groups-alist (lambda (x y) (string< (car x) (car y))))) ;; put each name from mail-groups-alist into the appropriate mail aliases (setq assn '("" . "")) (while mail-groups-alist (let ((assn-new (car mail-groups-alist))) (if (string= (car assn) "") (insert (concat "\n" (car assn-new) "\t\t(")) (if (not (string= (car assn) (car assn-new))) (insert (concat ")\n" (car assn-new) "\t\t(")))) (insert (concat (cdr assn-new) ",")) (setq mail-groups-alist (cdr mail-groups-alist)) (setq assn assn-new))) (if (not (string= (car assn) "")) (insert ")\n")) ;; Feedback on the output quality. (if bad (message "There were %d people with bad or missing net addresses." (length bad)) (message "Done.")))) Editing and formatting addresses with the country patch If you are using my country patch to BBDB, you might want to use a different address editing function or add new address formating functions. The following shows you how to go about doing that. A new address editing function You can only have one active input function at the time. The name of the active input function is stored in the variable `bbdb-address-editing-function'. Therefore, you will have to write a new address editing function and you will have to set `bbdb-address-editing-function'. The easiest way to go about this, is using paste and copy: use `bbdb-address-edit-default' as a starting point. (defun bbdb-address-edit-continental-german (addr) "Function to use for address editing. The sub-fields are queried using the continental order and using German prompts. This is an alternate value for `bbdb-address-editing-function'. It is used by German speaking users. The sub-fields and the prompts used are: Strasse, Zeile 1: street1 Strasse, Zeile 2: street2 Strasse, Zeile 3: street3 PLZ: zip Stadt: city Region/Staat: state Land: country" (let* ((st1 (bbdb-read-string "Strasse, Zeile 1: " (bbdb-address-street1 addr))) (st2 (if (string= st1 "") "" (bbdb-read-string "Strasse, Zeile 2: " (bbdb-address-street2 addr)))) (st3 (if (string= st2 "") "" (bbdb-read-string "Strasse, Zeile 3: " (bbdb-address-street3 addr)))) (zip (bbdb-error-retry (bbdb-parse-zip-string (bbdb-read-string "PLZ: " (bbdb-address-zip-string addr))))) (cty (bbdb-read-string "Stadt: " (bbdb-address-city addr))) (ste (bbdb-read-string "Region/Staat: " (bbdb-address-state addr))) (country (bbdb-read-string "Land: " (bbdb-address-country addr)))) (bbdb-address-set-street1 addr st1) (bbdb-address-set-street2 addr st2) (bbdb-address-set-street3 addr st3) (bbdb-address-set-city addr cty) (bbdb-address-set-state addr ste) (bbdb-address-set-zip addr zip) (bbdb-address-set-country addr country) nil)) (setq bbdb-address-editing-function 'bbdb-address-edit-continental-german) Adding a new formatting function You will have to add a new entry to `bbdb-address-formatting-alist'. The new entry must be a cons cell consisting of an identifying function and a formatting function. I'll use a Japanese format as an example. Please note that I don't really know how Japanese mail is formatted in Japan. The following reflects international standards for mail from outside Japan being sent to a Japanese address. First we'll start by adding the identifying function and the formatting function to `bbdb-address-formatting-alist'. This will controll address formatting in the *BBDB* buffer. (add-to-list 'bbdb-address-formatting-alist '(bbdb-address-is-japanese . bbdb-format-address-japanese)) The identifying function The function can do any testing it likes with the address received. In this case we just test for the country name "Japan". (defun bbdb-address-is-japanese (addr) "Return non-nil if the address ADDR is a japanese address. This is a possible identifying function for `bbdb-address-formatting-alist' and `bbdb-address-print-formatting-alist'." (and (string= (upcase (bbdb-address-country addr)) "JAPAN"))) The formatting function Another paste and copy event: use `bbdb-format-address-default' as a starting point. (defun bbdb-format-address-japanese (addr) "Insert formated Japanese address ADDR in current buffer. This is what it looks like: location: street1 street2 street3 city state zip country" (insert (format " %14s: " (bbdb-address-location addr))) (bbdb-format-streets addr) (let ((c (bbdb-address-city addr)) (s (bbdb-address-state addr)) (z (bbdb-address-zip-string addr)) (y (bbdb-address-country addr))) (if (or (> (length c) 0) (> (length s) 0) (> (length z) 0) (> (length y) 0)) (progn (if (> (length c) 0) (progn (indent-to 17) (insert c "\n"))) (if (> (length s) 0) (progn (indent-to 17) (insert s "\n"))) (if (or (> (length z) 0) (> (length y) 0)) (progn (indent-to 17) (if (> (length z) 0) (insert z (if (> (length y) 0) " " ""))) (if (> (length y) 0) (insert y)) (insert "\n" ""))))))) Print formatting of addresses This works just like the example above. Instead of adding the identifying and formatting functions to `bbdb-address-formatting-alist', you add the two functions to `bbdb-address-print-formatting-alist'. You can use the same identifying function that you used in `bbdb-address-formatting-alist'. The only thing you will have to code up is a print formatting function. It will be very similar to the normal formatting function. Use `bbdb-print-format-address-default' as a starting point. The details are left as an exercise to the reader. ---------------------------------------------------------------------------- Navigation: Top, Table of Contents, Index, next: .emacs file by Alex, prev: Emacs ---------------------------------------------------------------------------- http://hammer.prohosting.com/~gumbart/bbdb-funcs.html / Alex Schroeder / updated: 2000-03-10 / significant changes: 2000-02-11 ----------------------------------------------------------------------------