diff lisp/files.el @ 90843:d7172f202ab8

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 726-750) - Update from CVS - Merge from emacs--rel--22 - Merge from gnus--rel--5.10 * emacs--rel--22 (patch 6-17) - Update from CVS - Update from CVS: src/xterm.c (XTread_socket): Revert last change. * gnus--rel--5.10 (patch 218-221) - Merge from emacs--devo--0, emacs--rel--22 - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-205
author Miles Bader <miles@gnu.org>
date Tue, 15 May 2007 07:17:13 +0000
parents e6fdae9180d4 b823102d5f40
children 31beec9ee600
line wrap: on
line diff
--- a/lisp/files.el	Mon May 14 11:56:47 2007 +0000
+++ b/lisp/files.el	Tue May 15 07:17:13 2007 +0000
@@ -287,7 +287,7 @@
 A value of `visit' means do this right after the file is visited.
 A value of `visit-save' means do it at both of those times.
 Any other non-nil value means ask user whether to add a newline, when saving.
-nil means don't add newlines.
+A value of nil means don't add newlines.
 
 Certain major modes set this locally to the value obtained
 from `mode-require-final-newline'."
@@ -309,10 +309,10 @@
 A value of `visit-save' means do it at both of those times.
 Any other non-nil value means ask user whether to add a newline, when saving.
 
-nil means do not add newlines.  That is a risky choice in this variable
-since this value is used for modes for files that ought to have final newlines.
-So if you set this to nil, you must explicitly check and add
-a final newline, whenever you save a file that really needs one."
+A value of nil means do not add newlines.  That is a risky choice in this
+variable since this value is used for modes for files that ought to have
+final newlines.  So if you set this to nil, you must explicitly check and
+add a final newline, whenever you save a file that really needs one."
   :type '(choice (const :tag "When visiting" visit)
 		 (const :tag "When saving" t)
 		 (const :tag "When visiting or saving" visit-save)
@@ -459,7 +459,7 @@
 :safe means set the safe variables, and ignore the rest.
 :all means set all variables, whether safe or not.
  (Don't set it permanently to :all.)
-nil means always ignore the file local variables.
+A value of nil means always ignore the file local variables.
 
 Any other value means always query you once whether to set them all.
 \(When you say yes to certain values, they are remembered as safe, but
@@ -491,7 +491,7 @@
   "Control processing of the \"variable\" `eval' in a file's local variables.
 The value can be t, nil or something else.
 A value of t means obey `eval' variables;
-nil means ignore them; anything else means query."
+A value of nil means ignore them; anything else means query."
   :type '(choice (const :tag "Obey" t)
 		 (const :tag "Ignore" nil)
 		 (other :tag "Query" other))
@@ -2151,8 +2151,21 @@
 \"allow `auto-mode-alist' to decide for these files.\")")
 (put 'magic-mode-alist 'risky-local-variable t)
 
+(defvar file-start-mode-alist
+  nil
+  "Like `magic-mode-alist' but has lower priority than `auto-mode-alist'.
+Each element looks like (REGEXP . FUNCTION) or (MATCH-FUNCTION . FUNCTION).
+After visiting a file, if REGEXP matches the text at the beginning of the
+buffer, or calling MATCH-FUNCTION returns non-nil, `normal-mode' will
+call FUNCTION, provided that `magic-mode-alist' and `auto-mode-alist'
+have not specified a mode for this file.
+
+If FUNCTION is nil, then it is not called.")
+(put 'file-start-mode-alist 'risky-local-variable t)
+
 (defvar magic-mode-regexp-match-limit 4000
-  "Upper limit on `magic-mode-alist' regexp matches.")
+  "Upper limit on `magic-mode-alist' regexp matches.
+Also applies to `file-start-mode-alist'.")
 
 (defun set-auto-mode (&optional keep-mode-if-same)
   "Select major mode appropriate for current buffer.
@@ -2207,10 +2220,10 @@
 	      (or (set-auto-mode-0 mode keep-mode-if-same)
 		  ;; continuing would call minor modes again, toggling them off
 		  (throw 'nop nil))))))
+    ;; If we didn't, look for an interpreter specified in the first line.
+    ;; As a special case, allow for things like "#!/bin/env perl", which
+    ;; finds the interpreter anywhere in $PATH.
     (unless done
-      ;; If we didn't, look for an interpreter specified in the first line.
-      ;; As a special case, allow for things like "#!/bin/env perl", which
-      ;; finds the interpreter anywhere in $PATH.
       (setq mode (save-excursion
 		   (goto-char (point-min))
 		   (if (looking-at auto-mode-interpreter-regexp)
@@ -2223,7 +2236,7 @@
       ;; If we found an interpreter mode to use, invoke it now.
       (if done
 	  (set-auto-mode-0 (cdr done) keep-mode-if-same)))
-    ;; If we didn't, match the buffer beginning against magic-mode-alist.
+    ;; Next try matching the buffer beginning against magic-mode-alist.
     (unless done
       (if (setq done (save-excursion
 		       (goto-char (point-min))
@@ -2236,39 +2249,55 @@
 					  (if (functionp re)
 					      (funcall re)
 					    (looking-at re)))))))
-	  (set-auto-mode-0 done keep-mode-if-same)
-	;; Compare the filename against the entries in auto-mode-alist.
-	(if buffer-file-name
-	    (let ((name buffer-file-name))
-	      ;; Remove backup-suffixes from file name.
-	      (setq name (file-name-sans-versions name))
-	      (while name
-		;; Find first matching alist entry.
-		(setq mode
-		      (if (memq system-type '(vax-vms windows-nt cygwin))
-			  ;; System is case-insensitive.
-			  (let ((case-fold-search t))
-			    (assoc-default name auto-mode-alist
-					   'string-match))
-			;; System is case-sensitive.
-			(or
-			 ;; First match case-sensitively.
-			 (let ((case-fold-search nil))
-			   (assoc-default name auto-mode-alist
-					  'string-match))
-			 ;; Fallback to case-insensitive match.
-			 (and auto-mode-case-fold
-			      (let ((case-fold-search t))
-				(assoc-default name auto-mode-alist
-					       'string-match))))))
-		(if (and mode
-			 (consp mode)
-			 (cadr mode))
-		    (setq mode (car mode)
-			  name (substring name 0 (match-beginning 0)))
-		  (setq name))
-		(when mode
-		  (set-auto-mode-0 mode keep-mode-if-same)))))))))
+	  (set-auto-mode-0 done keep-mode-if-same)))
+    ;; Next compare the filename against the entries in auto-mode-alist.
+    (unless done
+      (if buffer-file-name
+	  (let ((name buffer-file-name))
+	    ;; Remove backup-suffixes from file name.
+	    (setq name (file-name-sans-versions name))
+	    (while name
+	      ;; Find first matching alist entry.
+	      (setq mode
+		    (if (memq system-type '(vax-vms windows-nt cygwin))
+			;; System is case-insensitive.
+			(let ((case-fold-search t))
+			  (assoc-default name auto-mode-alist
+					 'string-match))
+		      ;; System is case-sensitive.
+		      (or
+		       ;; First match case-sensitively.
+		       (let ((case-fold-search nil))
+			 (assoc-default name auto-mode-alist
+					'string-match))
+		       ;; Fallback to case-insensitive match.
+		       (and auto-mode-case-fold
+			    (let ((case-fold-search t))
+			      (assoc-default name auto-mode-alist
+					     'string-match))))))
+	      (if (and mode
+		       (consp mode)
+		       (cadr mode))
+		  (setq mode (car mode)
+			name (substring name 0 (match-beginning 0)))
+		(setq name))
+	      (when mode
+		(set-auto-mode-0 mode keep-mode-if-same)
+		(setq done t))))))
+    ;; Next try matching the buffer beginning against file-start-mode-alist.
+    (unless done
+      (if (setq done (save-excursion
+		       (goto-char (point-min))
+		       (save-restriction
+			 (narrow-to-region (point-min)
+					   (min (point-max)
+						(+ (point-min) magic-mode-regexp-match-limit)))
+			 (assoc-default nil file-start-mode-alist
+					(lambda (re dummy)
+					  (if (functionp re)
+					      (funcall re)
+					    (looking-at re)))))))
+	  (set-auto-mode-0 done keep-mode-if-same)))))
 
 ;; When `keep-mode-if-same' is set, we are working on behalf of
 ;; set-visited-file-name.  In that case, if the major mode specified is the