Mercurial > emacs
comparison lisp/mh-e/mh-alias.el @ 50702:7dd3d5eae9c7
Upgraded to MH-E version 7.3.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
author | Bill Wohler <wohler@newt.com> |
---|---|
date | Fri, 25 Apr 2003 05:52:00 +0000 |
parents | 0d8b17d428b5 |
children | 695cf19ef79e |
comparison
equal
deleted
inserted
replaced
50701:cb5f0a5d5b36 | 50702:7dd3d5eae9c7 |
---|---|
1 ;;; mh-alias.el --- MH-E mail alias completion and expansion | 1 ;;; mh-alias.el --- MH-E mail alias completion and expansion |
2 ;; | 2 ;; |
3 ;; Copyright (C) 1994, 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1994, 95, 96, 1997, |
4 ;; 2001, 02, 2003 Free Software Foundation, Inc. | |
4 | 5 |
5 ;; Author: Peter S. Galbraith <psg@debian.org> | 6 ;; Author: Peter S. Galbraith <psg@debian.org> |
6 ;; Maintainer: Bill Wohler <wohler@newt.com> | 7 ;; Maintainer: Bill Wohler <wohler@newt.com> |
7 ;; Keywords: mail | 8 ;; Keywords: mail |
8 ;; See: mh-e.el | 9 ;; See: mh-e.el |
91 ;; `mh-alias-insert-file'). In particular, there is a tool-bar icon to grab | 92 ;; `mh-alias-insert-file'). In particular, there is a tool-bar icon to grab |
92 ;; an alias from the From line of the current message. | 93 ;; an alias from the From line of the current message. |
93 | 94 |
94 ;;; Change Log: | 95 ;;; Change Log: |
95 | 96 |
96 ;; $Id: mh-alias.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ | |
97 | |
98 ;;; Code: | 97 ;;; Code: |
99 | 98 |
100 (require 'mh-e) | 99 (require 'mh-e) |
101 (load "cmr" t t) ; Non-fatal dependency for | 100 (load "cmr" t t) ; Non-fatal dependency for |
102 ; completing-read-multiple. | 101 ; completing-read-multiple. |
103 (eval-when-compile (defvar mail-abbrev-syntax-table)) | 102 (eval-when-compile (defvar mail-abbrev-syntax-table)) |
104 | 103 |
105 ;;; Autoloads | 104 ;;; Autoloads |
106 (autoload 'mail-abbrev-complete-alias "mailabbrev") | 105 (eval-when (compile load eval) |
107 (autoload 'multi-prompt "multi-prompt") | 106 (ignore-errors |
108 | 107 (require 'mailabbrev) |
109 (defvar mh-alias-alist nil | 108 (require 'multi-prompt))) |
109 | |
110 (defvar mh-alias-alist 'not-read | |
110 "Alist of MH aliases.") | 111 "Alist of MH aliases.") |
111 (defvar mh-alias-blind-alist nil | 112 (defvar mh-alias-blind-alist nil |
112 "Alist of MH aliases that are blind lists.") | 113 "Alist of MH aliases that are blind lists.") |
113 (defvar mh-alias-passwd-alist nil | 114 (defvar mh-alias-passwd-alist nil |
114 "Alist of aliases extracted from passwd file and their expansions.") | 115 "Alist of aliases extracted from passwd file and their expansions.") |
178 ((eq mh-alias-local-users t) | 179 ((eq mh-alias-local-users t) |
179 (if (file-readable-p "/etc/passwd") | 180 (if (file-readable-p "/etc/passwd") |
180 (insert-file-contents "/etc/passwd"))) | 181 (insert-file-contents "/etc/passwd"))) |
181 ((stringp mh-alias-local-users) | 182 ((stringp mh-alias-local-users) |
182 (insert mh-alias-local-users "\n") | 183 (insert mh-alias-local-users "\n") |
183 (shell-command-on-region (point-min)(point-max) mh-alias-local-users t) | 184 (shell-command-on-region (point-min) (point-max) mh-alias-local-users t) |
184 (goto-char (point-min)))) | 185 (goto-char (point-min)))) |
185 (while (< (point) (point-max)) | 186 (while (< (point) (point-max)) |
186 (cond | 187 (cond |
187 ((looking-at "\\([^:]*\\):[^:]*:\\([^:]*\\):[^:]*:\\([^:,]*\\)[:,]") | 188 ((looking-at "\\([^:]*\\):[^:]*:\\([^:]*\\):[^:]*:\\([^:,]*\\)[:,]") |
188 (when (> (string-to-int (match-string 2)) 200) | 189 (when (> (string-to-int (match-string 2)) 200) |
239 (setq local-users (cdr local-users))))) | 240 (setq local-users (cdr local-users))))) |
240 (message "Loading MH aliases...done")) | 241 (message "Loading MH aliases...done")) |
241 | 242 |
242 (defun mh-alias-reload-maybe () | 243 (defun mh-alias-reload-maybe () |
243 "Load new MH aliases." | 244 "Load new MH aliases." |
244 (if (or (not mh-alias-alist) ; Doesn't exist, so create it. | 245 (if (or (eq mh-alias-alist 'not-read) ; Doesn't exist, so create it. |
245 (mh-alias-tstamp nil)) ; Out of date, so recreate it. | 246 (mh-alias-tstamp nil)) ; Out of date, so recreate it. |
246 (mh-alias-reload))) | 247 (mh-alias-reload))) |
247 | 248 |
248 | 249 |
249 ;;; Alias Expansion | 250 ;;; Alias Expansion |
251 (defun mh-alias-ali (alias &optional user) | 252 (defun mh-alias-ali (alias &optional user) |
252 "Return ali expansion for ALIAS. | 253 "Return ali expansion for ALIAS. |
253 ALIAS must be a string for a single alias. | 254 ALIAS must be a string for a single alias. |
254 If USER is t, then assume ALIAS is an address and call ali -user. | 255 If USER is t, then assume ALIAS is an address and call ali -user. |
255 ali returns the string unchanged if not defined. The same is done here." | 256 ali returns the string unchanged if not defined. The same is done here." |
256 (save-excursion | 257 (condition-case err |
257 (let ((user-arg (if user "-user" "-nouser"))) | 258 (save-excursion |
258 (mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias)) | 259 (let ((user-arg (if user "-user" "-nouser"))) |
259 (goto-char (point-max)) | 260 (mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias)) |
260 (if (looking-at "^$") (delete-backward-char 1)) | 261 (goto-char (point-max)) |
261 (buffer-substring (point-min)(point-max)))) | 262 (if (looking-at "^$") (delete-backward-char 1)) |
263 (buffer-substring (point-min)(point-max))) | |
264 (error (progn | |
265 (message (error-message-string err)) | |
266 alias)))) | |
262 | 267 |
263 (defun mh-alias-expand (alias) | 268 (defun mh-alias-expand (alias) |
264 "Return expansion for ALIAS. | 269 "Return expansion for ALIAS. |
265 Blind aliases or users from /etc/passwd are not expanded." | 270 Blind aliases or users from /etc/passwd are not expanded." |
266 (cond | 271 (cond |
278 (if (not mh-alias-alist) ; If still no aliases, just prompt | 283 (if (not mh-alias-alist) ; If still no aliases, just prompt |
279 (read-string prompt) | 284 (read-string prompt) |
280 (let* ((minibuffer-local-completion-map mh-alias-read-address-map) | 285 (let* ((minibuffer-local-completion-map mh-alias-read-address-map) |
281 (completion-ignore-case mh-alias-completion-ignore-case-flag) | 286 (completion-ignore-case mh-alias-completion-ignore-case-flag) |
282 (the-answer | 287 (the-answer |
283 (or (cond | 288 (cond ((fboundp 'completing-read-multiple) |
284 ((fboundp 'completing-read-multiple) | 289 (mh-funcall-if-exists |
285 (completing-read-multiple prompt mh-alias-alist nil nil)) | 290 completing-read-multiple prompt mh-alias-alist nil nil)) |
286 ((featurep 'multi-prompt) | 291 ((featurep 'multi-prompt) |
287 (multi-prompt "," nil prompt mh-alias-alist nil nil)) | 292 (mh-funcall-if-exists |
288 (t | 293 multi-prompt "," nil prompt mh-alias-alist nil nil)) |
289 (split-string | 294 (t (split-string |
290 (completing-read prompt mh-alias-alist nil nil) | 295 (completing-read prompt mh-alias-alist nil nil) ","))))) |
291 ",")))))) | |
292 (if (not mh-alias-expand-aliases-flag) | 296 (if (not mh-alias-expand-aliases-flag) |
293 (mapconcat 'identity the-answer ", ") | 297 (mapconcat 'identity the-answer ", ") |
294 ;; Loop over all elements, checking if in passwd aliast or blind first | 298 ;; Loop over all elements, checking if in passwd aliast or blind first |
295 (mapconcat 'mh-alias-expand the-answer ",\n "))))) | 299 (mapconcat 'mh-alias-expand the-answer ",\n "))))) |
296 | 300 |
323 (if (and (equal mh-alias-flash-on-comma 1) | 327 (if (and (equal mh-alias-flash-on-comma 1) |
324 (not (string-match " " the-name))) | 328 (not (string-match " " the-name))) |
325 (message "No alias for %s" the-name)))))) | 329 (message "No alias for %s" the-name)))))) |
326 (self-insert-command 1)) | 330 (self-insert-command 1)) |
327 | 331 |
332 (mh-do-in-xemacs (defvar mail-abbrevs)) | |
333 | |
328 ;;;###mh-autoload | 334 ;;;###mh-autoload |
329 (defun mh-alias-letter-expand-alias () | 335 (defun mh-alias-letter-expand-alias () |
330 "Expand mail alias before point." | 336 "Expand mail alias before point." |
331 (mh-alias-reload-maybe) | 337 (mh-alias-reload-maybe) |
332 (let ((mail-abbrevs mh-alias-alist)) | 338 (let ((mail-abbrevs mh-alias-alist)) |
333 (mail-abbrev-complete-alias)) | 339 (mh-funcall-if-exists mail-abbrev-complete-alias)) |
334 (when mh-alias-expand-aliases-flag | 340 (when mh-alias-expand-aliases-flag |
335 (let* ((end (point)) | 341 (let* ((end (point)) |
336 (syntax-table (syntax-table)) | 342 (syntax-table (syntax-table)) |
337 (beg (unwind-protect | 343 (beg (unwind-protect |
338 (save-excursion | 344 (save-excursion |
348 ;;; Adding addresses to alias file. | 354 ;;; Adding addresses to alias file. |
349 | 355 |
350 (defun mh-alias-suggest-alias (string) | 356 (defun mh-alias-suggest-alias (string) |
351 "Suggest an alias for STRING." | 357 "Suggest an alias for STRING." |
352 (cond | 358 (cond |
359 ((string-match "^<\\(.*\\)>$" string) | |
360 ;; <somename@foo.bar> -> recurse, stripping brackets. | |
361 (mh-alias-suggest-alias (match-string 1 string))) | |
353 ((string-match "^\\sw+$" string) | 362 ((string-match "^\\sw+$" string) |
354 ;; One word -> downcase it. | 363 ;; One word -> downcase it. |
355 (downcase string)) | 364 (downcase string)) |
356 ((string-match "^\\(\\sw+\\)\\s-+\\(\\sw+\\)$" string) | 365 ((string-match "^\\(\\sw+\\)\\s-+\\(\\sw+\\)$" string) |
357 ;; Two words -> first.last | 366 ;; Two words -> first.last |
387 ;; Reverse order of comma-separated fields | 396 ;; Reverse order of comma-separated fields |
388 (mh-alias-suggest-alias | 397 (mh-alias-suggest-alias |
389 (format "%s %s" (match-string 2 string) (match-string 1 string)))) | 398 (format "%s %s" (match-string 2 string) (match-string 1 string)))) |
390 (t | 399 (t |
391 ;; Output string, with spaces replaced by dots. | 400 ;; Output string, with spaces replaced by dots. |
392 (downcase (replace-regexp-in-string | 401 (mh-alias-canonicalize-suggestion string)))) |
393 "\\.\\.+" "." | 402 |
394 (replace-regexp-in-string " +" "." string)))))) | 403 (defun mh-alias-canonicalize-suggestion (string) |
404 "Process STRING to replace spacess by periods. | |
405 First all spaces are replaced by periods. Then every run of consecutive periods | |
406 are replaced with a single period. Finally the string is converted to lower | |
407 case." | |
408 (with-temp-buffer | |
409 (insert string) | |
410 ;; Replace spaces with periods | |
411 (goto-char (point-min)) | |
412 (replace-regexp " +" ".") | |
413 ;; Replace consecutive periods with a single period | |
414 (goto-char (point-min)) | |
415 (replace-regexp "\\.\\.+" ".") | |
416 ;; Convert to lower case | |
417 (downcase-region (point-min) (point-max)) | |
418 ;; Whew! all done... | |
419 (buffer-string))) | |
395 | 420 |
396 (defun mh-alias-which-file-has-alias (alias file-list) | 421 (defun mh-alias-which-file-has-alias (alias file-list) |
397 "Return the name of writable file which defines ALIAS from list FILE-LIST." | 422 "Return the name of writable file which defines ALIAS from list FILE-LIST." |
398 (save-excursion | 423 (save-excursion |
399 (set-buffer (get-buffer-create mh-temp-buffer)) | 424 (set-buffer (get-buffer-create mh-temp-buffer)) |
401 (found)) | 426 (found)) |
402 (while the-list | 427 (while the-list |
403 (erase-buffer) | 428 (erase-buffer) |
404 (when (file-writable-p (car file-list)) | 429 (when (file-writable-p (car file-list)) |
405 (insert-file-contents (car file-list)) | 430 (insert-file-contents (car file-list)) |
406 (if (re-search-forward (concat "^" (regexp-quote alias) ":")) | 431 (if (re-search-forward (concat "^" (regexp-quote alias) ":") nil t) |
407 (setq found (car file-list) | 432 (setq found (car file-list) |
408 the-list nil) | 433 the-list nil) |
409 (setq the-list (cdr the-list))))) | 434 (setq the-list (cdr the-list))))) |
410 found))) | 435 found))) |
411 | 436 |
468 alias)))) | 493 alias)))) |
469 (split-string aliases ", +"))))))) | 494 (split-string aliases ", +"))))))) |
470 | 495 |
471 ;;;###mh-autoload | 496 ;;;###mh-autoload |
472 (defun mh-alias-from-has-no-alias-p () | 497 (defun mh-alias-from-has-no-alias-p () |
473 "Return t is From has no current alias set." | 498 "Return t is From has no current alias set. |
499 In the exceptional situation where there isn't a From header in the message the | |
500 function returns nil." | |
474 (mh-alias-reload-maybe) | 501 (mh-alias-reload-maybe) |
475 (save-excursion | 502 (save-excursion |
476 (if (not (mh-folder-line-matches-show-buffer-p)) | 503 (if (not (mh-folder-line-matches-show-buffer-p)) |
477 nil ;No corresponding show buffer | 504 nil ;No corresponding show buffer |
478 (if (eq major-mode 'mh-folder-mode) | 505 (if (eq major-mode 'mh-folder-mode) |
479 (set-buffer mh-show-buffer)) | 506 (set-buffer mh-show-buffer)) |
480 (not (mh-alias-address-to-alias (mh-extract-from-header-value)))))) | 507 (let ((from-header (mh-extract-from-header-value))) |
508 (and from-header | |
509 (not (mh-alias-address-to-alias from-header))))))) | |
481 | 510 |
482 (defun mh-alias-add-alias-to-file (alias address &optional file) | 511 (defun mh-alias-add-alias-to-file (alias address &optional file) |
483 "Add ALIAS for ADDRESS in alias FILE without alias check or prompts. | 512 "Add ALIAS for ADDRESS in alias FILE without alias check or prompts. |
484 Prompt for alias file if not provided and there is more than one candidate. | 513 Prompt for alias file if not provided and there is more than one candidate. |
485 If ALIAS matches exactly, prompt to [i]nsert before old value or [a]ppend | 514 If ALIAS matches exactly, prompt to [i]nsert before old value or [a]ppend |
489 (save-excursion | 518 (save-excursion |
490 (set-buffer (find-file-noselect file)) | 519 (set-buffer (find-file-noselect file)) |
491 (goto-char (point-min)) | 520 (goto-char (point-min)) |
492 (let ((alias-search (concat alias ":")) | 521 (let ((alias-search (concat alias ":")) |
493 (letter) | 522 (letter) |
494 (here (point)) | |
495 (case-fold-search t)) | 523 (case-fold-search t)) |
496 (cond | 524 (cond |
497 ;; Search for exact match (if we had the same alias before) | 525 ;; Search for exact match (if we had the same alias before) |
498 ((re-search-forward | 526 ((re-search-forward |
499 (concat "^" (regexp-quote alias-search) " *\\(.*\\)") nil t) | 527 (concat "^" (regexp-quote alias-search) " *\\(.*\\)") nil t) |
536 Prompts for confirmation if the address already has an alias. | 564 Prompts for confirmation if the address already has an alias. |
537 If the alias is already is use, `mh-alias-add-alias-to-file' will prompt." | 565 If the alias is already is use, `mh-alias-add-alias-to-file' will prompt." |
538 (interactive "P\nP") | 566 (interactive "P\nP") |
539 (mh-alias-reload-maybe) | 567 (mh-alias-reload-maybe) |
540 (setq alias (completing-read "Alias: " mh-alias-alist nil nil alias)) | 568 (setq alias (completing-read "Alias: " mh-alias-alist nil nil alias)) |
569 (if (and address (string-match "^<\\(.*\\)>$" address)) | |
570 (setq address (match-string 1 address))) | |
541 (setq address (read-string "Address: " address)) | 571 (setq address (read-string "Address: " address)) |
572 (if (string-match "^<\\(.*\\)>$" address) | |
573 (setq address (match-string 1 address))) | |
542 (let ((address-alias (mh-alias-address-to-alias address)) | 574 (let ((address-alias (mh-alias-address-to-alias address)) |
543 (alias-address (mh-alias-expand alias))) | 575 (alias-address (mh-alias-expand alias))) |
544 (if (string-equal alias-address alias) | 576 (if (string-equal alias-address alias) |
545 (setq alias-address nil)) | 577 (setq alias-address nil)) |
546 (cond | 578 (cond |
569 (mh-get-msg-num nil)) | 601 (mh-get-msg-num nil)) |
570 (set-buffer (get-buffer-create mh-temp-buffer)) | 602 (set-buffer (get-buffer-create mh-temp-buffer)) |
571 (insert-file-contents (mh-msg-filename (mh-get-msg-num t)))) | 603 (insert-file-contents (mh-msg-filename (mh-get-msg-num t)))) |
572 ((eq major-mode 'mh-folder-mode) | 604 ((eq major-mode 'mh-folder-mode) |
573 (error "Cursor not pointing to a message"))) | 605 (error "Cursor not pointing to a message"))) |
574 (let* ((address (mh-extract-from-header-value)) | 606 (let* ((address (or (mh-extract-from-header-value) |
607 (error "Message has no From: header"))) | |
575 (alias (mh-alias-suggest-alias address))) | 608 (alias (mh-alias-suggest-alias address))) |
576 (mh-alias-add-alias alias address)))) | 609 (mh-alias-add-alias alias address)))) |
577 | 610 |
578 ;;;###mh-autoload | 611 ;;;###mh-autoload |
579 (defun mh-alias-add-address-under-point () | 612 (defun mh-alias-add-address-under-point () |