Gnus development mailing list
 help / color / mirror / Atom feed
* incorporating MH Aliases
@ 1996-06-15  6:56 Erik Selberg
  1996-06-15  7:20 ` Lars Magne Ingebrigtsen
  0 siblings, 1 reply; 2+ messages in thread
From: Erik Selberg @ 1996-06-15  6:56 UTC (permalink / raw)


Hi,

I finally figured out how to incorporate MH aliases for those of you
who use them. Lars --- can these please be incorporated into
message.el? I've done some preliminary work in terms of an easy
interface. 

(defvar message-use-mh-aliases nil
  "If non-nil, use mh-aliases (as specified in .mhprofile) file
instead of .mailrc for mail aliases. Requires e-mh-alias.el")

;; needs e-mh-alias by Peter Galbraith; perhaps it can be
;; distributed with gnus as I don't believe it's part of emacs? it
;; does have the gnu license, so this should be OK

(require 'e-mh-alias) ;; included at bottom of this message

;; convenience; if non-nil reads the /etc/password file and does
;; the right thing. Usually pointless with things like yppasswd though
(setq e-mh-alias-local-users nil)

;; first, learn the mh-aliases. 
(e-mh-learn-aliases) ;; sets e-mh-alias-lowercase-alist

;; then, insert them into the mail-abbrev table, and you're all set
(mapcar (lambda (x) (define-mail-abbrev (car x) (cdr x)))
	(mapcar
	 (lambda (y)
	   (cons (car y)
		 (mapconcat 
		  (function (lambda (x) (format "%s" x)))
		  (cdr y) ",\n "
		  )))
	 e-mh-alias-lowercase-alist))

----------------------------------------------------------------------

For those who don't, MH aliases are like normail aliases in .mailrc
except:

they're in the format
joebob:	joebob@some.dom

and you can specify files as distribution lists, as in
buddies: <~/dl/buddies.dl

gnus message system doesn't incorporate them.

----------------------------------------------------------------------

;; e-mh-alias.el - MH mail alias expansion and substitution.
;;
;; Copyright (C) 1995 Peter S. Galbraith
 
;; Author:    Peter S. Galbraith <rhogee@bathybius.meteo.mcgill.ca>
;; Created:   16 June 1994.
;; Version:   2.04 (29 Sep 95)
;; Keywords:  mh-e, mail, alias, emacs, xemacs

;; Everyone is granted permission to copy, modify and redistribute this
;; file provided:
;;   1. All copies contain this copyright notice.
;;   2. All modified copies shall carry a prominant notice stating who
;;      made modifications and the date of such modifications.
;;   3. The name of the modified file be changed.
;;   4. No charge is made for this software or works derived from it.
;;      This clause shall not be construed as constraining other software
;;      distributed on the same medium as this software, nor is a
;;      distribution fee considered a charge.

;; LCD Archive Entry:
;; e-mh-alias|Peter Galbraith|galbraith@mixing.qc.dfo.ca|
;; MH mail alias expansion and substitution.|
;; 29-Sep-1995|2.04|~/misc/e-mh-alias.el
;; ----------------------------------------------------------------------------
;;; Commentary:

;; New versions of this package (if they exist) may be found at:
;;  ftp://mixing.qc.dfo.ca/pub/elisp/e-mh-alias.el
;;  ftp://bathybius.meteo.mcgill.ca/pub/users/rhogee/elisp/e-mh-alias.el

;; Description:
;;
;;  This packages makes [TAB] do completion in minibuffer To: and CC:
;;  prompts on mail aliases (and optionally local usernames) and will
;;  substitute these aliases in the MH-letter buffer.  You may enter
;;  multiple addressees by separating them with a comma, which (by default)
;;  will flash the alias translation of the previous address.
;;
;;  This package also makes [C-c C-f TAB] and Meta-[TAB] (aka M-\t) do
;;  completion in the letter header itself.  The Meta-[TAB] binding only
;;  works for emacs version 19.29 (and above), because I use text-properties 
;;  to set a local keymap for a range of text (namely the mail header) 
;;  because M-\t is useful as ispell-complete-word in the rest of the letter 
;;  buffer.  This feature is useful when you want to add an addressee as an 
;;  afterthought while editing a letter, or add an addresse to a reply.
;;
;; Installation instructions:
;;
;;  All you need to do is add this line to your .emacs file
;;   (require 'e-mh-alias)
;;
;;  By default, completion is case insensitive.  Should you want to change 
;;  this, you can set the following variable:
;;   (defvar e-mh-alias-completion-ignore-case nil)
;;  This is useful, for example, if you set all people aliases to lowercase
;;  like 
;;    p.galbraith: Peter Galbraith <galbraith@mixing.qc.dfo.ca>
;;  and lists in uppercase, like: 
;;    MH-E: mh-e mailing list <mh-e@x.org>
;;  Note that this variable affects minibuffer completion only.  If you
;;  have an alias for P.Galbraith and type in p.galbraith at the prompt, it
;;  will still be substituted in the letter buffer because these are
;;  identical aliases as far as MH and e-mh-alias are concerned.
;;
;;  By default, when you press the [comma] key at the To: or Cc: prompts,
;;  the previous mail alias translation is flashed.  To inhibit this, add
;;  the following to your ~/.emacs file *before* you load e-mh-alias.
;;
;;   (setq e-mh-alias-flash-on-comma nil)
;;
;;  Completion and substitutions are also done on usernames extracted from
;;  your /etcd/passwd file.  This can be a handy tool on a machine where
;;  you and co-workers exchange messages, but should probably be disabled
;;  on a system with 100 users whom you don't know.  This feature is
;;  disabled by adding the following to your ~/.emacs file:
;;
;;   (setq e-mh-alias-local-users nil)
;;
;;  If you do use this feature, check that the variable e-mh-hostname is set
;;  to a string containing @ followed by your hostname for better results 
;;  (e.g. C-h v e-mh-hostname).  This should be set correctly after e-mh-alias
;;  is loaded, but if it isn't do it in your ~/.emacs file using, for example
;;
;;   (setq e-mh-hostname "@mixing.qc.dfo.ca")
;;
;;  To do minibuffer completion on many comma-separated aliases, I use the
;;  package `complete.el'.  This affects minibuffer completion in everyday
;;  use, and you might not like it.  If you find that you can do without
;;  completion on multiple aliases, you may then set the following variable
;;  to nil, like so
;;
;;   (setq e-mh-alias-use-complete nil)
;;
;;  It is set to nil by default in xemacs, because it ddoesn't have the
;;  `complete.el' package.
;; ----------------------------------------------------------------------------
;;; Change log:
;; V1.00 16Jun94 Peter S Galbraith - Created as mh-aliases.el
;; V2.00 20Jul95 PSG - new version called mh-alias.el 
;;  - get aliases from MH's ali command.
;;  - allow for comma separated list.
;;  - optionally flash aliases when [comma] is pressed.
;;  - [C-c C-f \t] or [M-\t] in MH-Letter header expands/substitutes aliases
;; V2.01 24Jul95 PSG - Added e-mh-alias-completion-ignore-case
;; V2.02 24Jul95 PSG - 
;;  - called e-mh-alias.el because mh- prefix reserved for mh-e packages.
;;  - e-mh-alias-flash-on-comma may be unset after package loaded and can take 
;;    values nil, 1 or t. (Eric Ding <ericding@San-Jose.ate.slb.com>)
;;  - initialize e-mh-hostname (Stephen Gildea <gildea@x.org>)
;;  - shows completions buffer immediately on \M-\t in MH-Letter-buffer
;; V2.03 27Jul95 PSG - Made truly case insensitive for substitution. 
;;    Thanks to Christopher Lott <lott@informatik.uni-kl.de> for bug reports.
;; V2.04 29Sep95 PSG - Added e-mh-alias-use-complete for xemacs compatibility.
;; ----------------------------------------------------------------------------
;;; Code:

(defvar e-mh-alias-completion-ignore-case t
  "Non-nil means don't consider case significant in MH alias completion.
This is the default in plain MH, so it is the default here as well.
But you can change it usefully if, for example, you use lowercase aliases
for people and uppercase for lists.")

(defvar e-mh-alias-flash-on-comma t 
  "Determines if alias translation displayed when [comma] pressed in mh queries
t   flash alias translation but don't warn if there is no translation. 
1   flash alias translation and warn if there is no translation.
nil don't flash alias translation or warn if there is no translation.")

(defvar e-mh-alias-local-users t 
  "If t, local users (with UID >= 200 from /etc/passwd) will be completed to
and expanded by MH To: and Cc: prompts.")

(defvar e-mh-alias-use-complete 
  (not (string-match "XEmacs\\|Lucid" emacs-version))
  "Non-nil means to use complete.el package.  This will affect minibuffer
completion in everyday emacs usage, and so is optional.  You cannot use
minibuffer completion for comma-separated aliases in e-mh-alias if you
do not use complete.el")

(defvar e-mh-hostname 
  (concat "@"
          (or (and (boundp 'mail-host-address)
                   mail-host-address)
              (system-name)))
  "String to append to local usernames from /etc/passwd to make addresses.
This should be \"@\" your fully qualified hostname (e.g. \"@mixing.qc.dfo.ca\")
See variable e-mh-alias-local-users.")

;; If you use the ffap package, then load e-mh-alias *before* ffap because the 
;; complete package will interfere with ffap if loaded afterward ffap.
;; Using complete.el is overkill, but it allows me to taylor prompting. 
(if e-mh-alias-use-complete
    (require 'complete))

;; load mh-comp because I redefine mh-read-address. 
(require 'mh-comp)

(defvar e-mh-alias-alist nil "Alist of MH mailaliases.")
(defvar e-mh-alias-lowercase-alist nil "Alist of lowercased MH mailaliases.")

(defvar e-mh-read-address-map nil)
(if e-mh-read-address-map
    ()
  (setq e-mh-read-address-map (copy-keymap minibuffer-local-completion-map))
  (if (featurep 'complete)
      (define-key e-mh-read-address-map "\t" 'e-mh-complete-address))
  (if e-mh-alias-flash-on-comma
      (define-key e-mh-read-address-map "," 'e-mh-minibuffer-confirm-address))
  (define-key e-mh-read-address-map " " 'self-insert-command))


(defun mh-read-address (prompt &optional initial-address)
  ;; Read a To: or Cc: address, prompting in the minibuffer with PROMPT.
  (if (not (or e-mh-alias-alist
               (e-mh-learn-aliases)))
      (read-string prompt)
    (let* ((minibuffer-local-completion-map e-mh-read-address-map)
           (completion-ignore-case e-mh-alias-completion-ignore-case)
           ;; initial-address is nil with minibuffer To: and CC: prompts
           ;;                 maybe "" in MH-letter-mode
           (unread-command-char (cond ((or (not initial-address)
                                           (string-equal "" initial-address)) 
                                       -1)
                                      (t
                                       ??)))
           (the-answer (or (completing-read 
                            prompt e-mh-alias-alist nil nil initial-address)
                           "")))
      ;; Here I find all comma-whitespace-delimited words to test as aliases.
      (let ((the-aliases))
        (while (and the-answer
                    ;; Catches comma-delimited address with trailing whitespace
                    (string-match "^[ \t,]*\\([^,]+\\)" the-answer))
          (let* ((the-index (match-end 0))
                 (the-match (substring the-answer 
                                       (match-beginning 1)(match-end 1)))
                 ;; Now trim off trailing whitespace
                 (trim-match (substring the-match 0 
                                        (string-match "[ \t]*$" the-match))))
            (setq the-aliases
                  (concat 
                   the-aliases ",\n "
                   (if (assoc (downcase trim-match) 
                              e-mh-alias-lowercase-alist) ;Translates to alias?
                       (mapconcat 
                        (function (lambda (x) (format "%s" x)))
                        (cdr (assoc (downcase trim-match) 
                                    e-mh-alias-lowercase-alist))
                        ",\n ")
                     trim-match)))      ; Does not translate 
            (setq the-answer (substring the-answer the-index))))
        ;; remove leading comma
        (if the-aliases
            (substring the-aliases 3)
          "")))))

(defun e-mh-complete-address ()
  "Called by pressing [TAB] while in mh TO: or CC: prompts."
  (interactive)
  (PC-do-completion nil (save-excursion (skip-chars-backward "^ \t,")(point))))

(defun e-mh-minibuffer-confirm-address ()
  "Called by pressing [comma] if e-mh-alias-flash-on-comma is t." 
  (interactive)
  (if (not e-mh-alias-flash-on-comma)
      ()
    (save-excursion
      (let ((the-name (buffer-substring
                       (progn (skip-chars-backward " \t")(point))
                       ;; This moves over to previous comma, if any
                       (progn (or (and (not (= 0 (skip-chars-backward "^,")))
                                       ;; the skips over leading whitespace
                                       (skip-chars-forward " "))
                                  ;; no comma, then to beginning of word
                                  (skip-chars-backward "^ \t"))
                              (point)))))
        (if (assoc (downcase the-name) e-mh-alias-lowercase-alist)
            (message "%s -> %s" the-name
                     (mapconcat (function (lambda (x) (format "%s" x)))
                                (cdr (assoc (downcase the-name) 
                                            e-mh-alias-lowercase-alist))
                                ", "))
          ;; Check if if was a single word likely to be an alias
          (if (and (equal e-mh-alias-flash-on-comma 1)
                   (not (string-match " " the-name)))
              (message "No alias for %s" the-name))))))
    (self-insert-command 1))

(defun e-mh-learn-aliases ()
  "Learn MH aliases, building an alist to complete with, and substitute with.
This can be called interactively to rebuild from updated files."
;;; Could be done using an obarray and `intern' to create it.
;;; elisp info doesn't say if completing-read is more efficient with alists
;;;  or obarrays.
  (interactive)
  (let ((mailalias-buffer (get-buffer-create " *e-mh-ali-command*")))
    (save-excursion
      (set-buffer mailalias-buffer)
      (erase-buffer)
      (insert (expand-file-name "ali" mh-progs) " -list\n")
      (write-region (point-min) (point-max) "/tmp/e-mh-ali-command" nil nil)
      (message "building list of MH mail aliases...")
      (erase-buffer)
      (call-process "/bin/sh" "/tmp/e-mh-ali-command" t nil)
      (delete-file "/tmp/e-mh-ali-command")
      (setq e-mh-alias-alist nil
            e-mh-alias-lowercase-alist nil)
      (goto-char (point-min))
      (let ((zero 0))
        (while (= zero 0)
          (cond
           ((looking-at "\\(.*\\): *\\(.*\\)$") ; A new MH alias
            (setq e-mh-alias-alist
                  (cons 
                   (list (buffer-substring (match-beginning 1)(match-end 1)))
                    e-mh-alias-alist))
            (setq e-mh-alias-lowercase-alist
                  (cons 
                   (list (downcase
                          (buffer-substring (match-beginning 1)(match-end 1)))
                         (buffer-substring (match-beginning 2)(match-end 2)))
                    e-mh-alias-lowercase-alist)))
           ((looking-at "[ ]+\\(.*\\)$") ; A alias continued
            (let ((the-first (car e-mh-alias-lowercase-alist)) 
                  ;;^^The previous alias list entered ("NEW" "schneider@awi")
                  (the-rest (cdr e-mh-alias-lowercase-alist)) 
                  ;;^^The others before
                  (the-new (buffer-substring(match-beginning 1)(match-end 1))))
              (setq e-mh-alias-lowercase-alist
                    (cons
                     (append            ;  ("NEW" "budeus@awi" "schneider@awi")
                      (list (car the-first)) ; ("NEW")
                      (list the-new)    ;      ("budeus@awi")
                      (cdr the-first))  ;      ("schneider@awi")
                     the-rest)))))
          (setq zero (forward-line 1)))))
    (kill-buffer mailalias-buffer))
  (if e-mh-alias-local-users
      (e-mh-learn-local-users))
  (message "building list of MH mail aliases... done."))

(defun e-mh-learn-local-users ()
  "Add local users from /etc/passwd to e-mh-alias-alist"
  (let ((mailalias-buffer (get-buffer-create " *mailalias*")))
    (save-excursion
      (set-buffer mailalias-buffer)
      (if (file-readable-p "/etc/passwd")
          (insert-file-contents "/etc/passwd"))
      (let ((zero 0))
        (while (= zero 0)
          (cond
           ((looking-at "\\([^:]*\\):[^:]*:\\([^:]*\\):[^:]*:\\([^:]*\\):")
            (if (> (string-to-int 
                    (buffer-substring (match-beginning 2)(match-end 2)))
                   200)
                (let ((username 
                       (buffer-substring (match-beginning 1)(match-end 1)))
                      (realname
                       (buffer-substring (match-beginning 3)(match-end 3))))
                  (setq e-mh-alias-lowercase-alist
                        (cons (list 
                               username 
                               (if (string-equal "" realname)
                                   (concat "<" username e-mh-hostname ">")
                                 (concat realname 
                                         " <" username e-mh-hostname ">")))
                              e-mh-alias-lowercase-alist))
                  (setq e-mh-alias-alist
                        (cons (list username) e-mh-alias-alist))))))
          (setq zero (forward-line 1)))))
    (kill-buffer mailalias-buffer)))

;;; --------------------------------------------------------------------------
;;; This part of e-mh-alias adds [M-TAB] expansion/substitution in letter head

(define-key mh-letter-mode-map "\C-c\C-f\t" 'e-mh-letter-expand-alias)

(cond
 ((string< "19.28.9" emacs-version)
  ;; wanted also to test (emacs-type) but this is unbound in -batch mode !
  (setq e-mh-expand-alias-map (copy-keymap mh-letter-mode-map))
  (define-key e-mh-expand-alias-map "\M-\t" 'e-mh-letter-expand-alias)

  (defun e-mh-letter-mode-expand-alias-hook ()
    "Make M-[TAB] expand mail alias within letter header"
    (save-excursion
      ;; Take extra precautions to not return errors if regexp not found.
      (add-text-properties (progn (goto-char (point-min))(point))
                           (progn (re-search-forward "^---" nil t)(point))
                           (list 'local-map e-mh-expand-alias-map))))

  (add-hook 'mh-letter-mode-hook 'e-mh-letter-mode-expand-alias-hook)))

(defun e-mh-letter-expand-alias ()
  "expand/convert mail alias before/under point."
  (interactive)
  (save-excursion
    (skip-chars-backward "^ ,:")
    (let ((the-match)(init-address "")(the-address))
      (if (looking-at "[^ ,;\n]+")
          (setq the-match (match-data)
                init-address 
                (or (and (string< "19.28.9" emacs-version)
                         (buffer-substring-no-properties 
                          (match-beginning 0)(match-end 0)))
                    (buffer-substring (match-beginning 0)(match-end 0)))))
      (if (assoc (try-completion (downcase init-address) 
                                 e-mh-alias-lowercase-alist) 
                 e-mh-alias-lowercase-alist)
          ;; init-address is "p.gal" which has unique completion to 
          ;; "p.galbraith", then substitute its alias, possibly multi-line.
          (setq the-address
                (mapconcat 
                 (function (lambda (x) (format "%s" x)))
                 (cdr (assoc (try-completion (downcase init-address) 
                                             e-mh-alias-lowercase-alist) 
                             e-mh-alias-lowercase-alist))
                 ",\n "))
        (setq the-address (mh-read-address "Address: " init-address)))
      (if (string-equal "" the-address)
          ()
        (if (not the-match)
            (insert the-address)
          (set-match-data the-match)
          (replace-match the-address t t))))))

(provide 'e-mh-alias)
;;; e-mh-alias.el ends here


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: incorporating MH Aliases
  1996-06-15  6:56 incorporating MH Aliases Erik Selberg
@ 1996-06-15  7:20 ` Lars Magne Ingebrigtsen
  0 siblings, 0 replies; 2+ messages in thread
From: Lars Magne Ingebrigtsen @ 1996-06-15  7:20 UTC (permalink / raw)


Erik Selberg <selberg@cs.washington.edu> writes:

> I finally figured out how to incorporate MH aliases for those of you
> who use them. Lars --- can these please be incorporated into
> message.el? 

Nope:

> ;; Everyone is granted permission to copy, modify and redistribute this
> ;; file provided:
> ;;   1. All copies contain this copyright notice.
> ;;   2. All modified copies shall carry a prominant notice stating who
> ;;      made modifications and the date of such modifications.
> ;;   3. The name of the modified file be changed.
> ;;   4. No charge is made for this software or works derived from it.
> ;;      This clause shall not be construed as constraining other software
> ;;      distributed on the same medium as this software, nor is a
> ;;      distribution fee considered a charge.

It's not free.  (As in "GPL'd".)

Anyways, this isn't something that should be incorporated into
message.el, although Message could certainly use something like this. 

-- 
(domestic pets only, the antidote for overdose, milk.)
  larsi@ifi.uio.no * Lars Ingebrigtsen


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1996-06-15  7:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-06-15  6:56 incorporating MH Aliases Erik Selberg
1996-06-15  7:20 ` Lars Magne Ingebrigtsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).