From: mic@cs.ubc.ca (Michelangelo Grigni)
Subject: Re: RMAIL and dired
Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
Distribution: gnu
Date: Thu, 16 Apr 92 19:53:27 GMT

In article <1992Apr15.191739.24678@cs.ubc.ca> I wrote:
> Here is a more generic solution, which applies whenever you find-file
> an rmail file. The basic idea is to make default-major-mode [bogus bogus]

I am embarrassed to say the previous elegant solution was totally
wrong.  In fact it has lived in my .emacs for a while, but is
worthless since at the time default-major-mode is called, the buffer
is still empty.

Thanks to 
	<Keith.Hobley@prg.ox.ac.uk>, 
	Ethan Bradford <ethanb@ptolemy.astro.washington.edu>
for complaining.

In fact I was getting the desired behavior (automatically put rmail
files in rmail mode), but from another source: Ashwin Ram's "infer"
package picked up from gnu.emacs.bug a while ago.  This works via
find-file-hooks.

So here is what to do:

1) put (require 'infer) in your .emacs,
2) put these files "infer.el" and "add-hook.el" on your path:

------ infer.el ------
;; 11/8/91: modified by Mic Grigni
(provide 'infer)
(require 'add-hook)
(add-hook 'find-file-hooks 'infer-file-mode)

;; From: mike-w@cs.AUkuni.ac.NZ (Mike Williams)
;; Newsgroups: gnu.emacs.bug
;; Subject: Re: -*- doesn't work for scripts
;; Date: 18 Sep 91 13:14:29 GMT

;;=== Infer file mode based on contents ===
;; Ashwin Ram, 11/5/88.
;; 
;; add to find-file-hooks

(defvar infer-mode-alist 
  '(
    ;;("^\\\\documentstyle" . latex-mode)
    ("^\\\\chapter" . latex-mode)
    ;;("^\\\\\\(sub\\)*section *{" . latex-mode)
    ("\\`BABYL OPTIONS:$" . rmail-magic)
    ;;("\\`#! */bin/t?csh\\>" . csh-mode)
    ;;("\\`:  *#" . fundamental-mode)
    ;;("\\`#! */bin/sh\\>" . fundamental-mode)
    ("\\`#!.*/perl\\>" . perl-mode)
    )
  "Alist of file content patterns vs corresponding major mode functions.
Each element looks like (REGEXP . FUNCTION).
Visiting a file whose which contains REGEXP within the first infer-mode-limit
characters causes FUNCTION to be called.")

(defvar infer-mode-limit 1000
   "Number of characters to search when inferring mode based on file contents.
Nil means search entire buffer.  See infer-mode-alist.")

(defun infer-file-mode ()
   "Infer mode of file based on its contents.
To use, add this function to find-file-hooks.
To customize, see the variable infer-mode-alist."
   (let ((mode-alist infer-mode-alist))
     (catch 'found
       (while mode-alist
	 (if (save-excursion
	       (goto-char (point-min))
	       (re-search-forward (car (car mode-alist)) 
				  infer-mode-limit t))
	     (throw 'found t)
	   (setq mode-alist (cdr mode-alist)))))
     (if mode-alist
	 (funcall (cdr (car mode-alist))))))


;; Helper functions:
(defun rmail-magic nil (rmail (buffer-file-name)))

------ add-hook.el ------
;;; A little package, to add a hook to a hook-list.
;;; Compatible with a function of the same name in comint-ipc.el

(or (fboundp 'member)
    ;; "ought" to be in standard emacs.
    ;; This version based on comint-mem of comint.el
    (defun member (item list &optional elt=) "\
Returns non-nil if ITEM is equal to an element of LIST.  
The value is actually the tail of LIST whose car equals ELT.
Optional comparison function ELT= defaults to equal."
      (let ((elt= (or elt= (function equal)))
	    (done nil))
	(while (and list (not done))
	  (if (funcall elt= item (car list))
	      (setq done list)
	      (setq list (cdr list))))
	done)))

;; See ~/el files for many more "file hooks"

(provide 'add-hook)

(defun add-hook (hook-var hook-fun &optional end)
  "Append HOOK-FUN to list named by hook variable HOOK-VAR (a symbol).
Does nothing if HOOK-FUN is equal to a hook already listed by HOOK-VAR.
HOOK-FUN may be anything that may be funcall'ed with no arguments.
If optional END argument is non-nil, add HOOK-FUN at end of the list.

Several reasonable cases are handled (see run-hooks):
 * HOOK-VAR may be currently unbound
 * HOOK-VAR may be bound to a single symbol or lambda expression
 * HOOK-VAR may be bound to a list of such single hooks"
  (set hook-var
       (let ((old-hooks (and (boundp hook-var) (symbol-value hook-var))))
	 ;; convert a single hook to a list if necessary
	 (if (and old-hooks (or (not (consp old-hooks))
				(eq (car old-hooks) 'lambda)))
	     (setq old-hooks (list old-hooks)))
	 (if (member hook-fun old-hooks)
	     old-hooks ;; do nothing if already there
	     (if end ;; add new hook
		 (nconc old-hooks (list hook-fun))
		 (cons hook-fun old-hooks))))))

;; end of file