changeset 17660:473ee9294c31

(set-auto-mode): New arg JUST-FROM-FILE-NAME. (hack-local-variables): New arg MODE-ONLY. (set-visited-file-name): Alter the major mode based on new file name. (change-major-mode-with-file-name): New variable.
author Richard M. Stallman <rms@gnu.org>
date Mon, 05 May 1997 04:38:26 +0000
parents a62b21f702b0
children e9949b093b46
files lisp/files.el
diffstat 1 files changed, 111 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/files.el	Mon May 05 04:24:01 1997 +0000
+++ b/lisp/files.el	Mon May 05 04:38:26 1997 +0000
@@ -1135,7 +1135,7 @@
   "" ; set by command-line
   "File name including directory of user's initialization file.")
 
-(defun set-auto-mode ()
+(defun set-auto-mode (&optional just-from-file-name)
   "Select major mode appropriate for current buffer.
 This checks for a -*- mode tag in the buffer's text,
 compares the filename against the entries in `auto-mode-alist',
@@ -1146,7 +1146,11 @@
 Local Variables section of the file; for that, use `hack-local-variables'.
 
 If `enable-local-variables' is nil, this function does not check for a
--*- mode tag."
+-*- mode tag.
+
+If the optional argument JUST-FROM-FILE-NAME is non-nil,
+then we do not set anything but the major mode,
+and we don't even do that unless it would come from the file name."
   ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
   (let (beg end done modes)
     (save-excursion
@@ -1211,8 +1215,9 @@
     ;; If we found modes to use, invoke them now,
     ;; outside the save-excursion.
     (if modes
-	(progn (mapcar 'funcall (nreverse modes))
-	       (setq done t)))
+	(unless just-from-file-name
+	  (mapcar 'funcall (nreverse modes))
+	  (setq done t)))
     ;; If we didn't find a mode from a -*- line, try using the file name.
     (if (and (not done) buffer-file-name)
 	(let ((name buffer-file-name)
@@ -1254,8 +1259,9 @@
 		  ;; Map interpreter name to a mode.
 		  (setq elt (assoc (file-name-nondirectory interpreter)
 				   interpreter-mode-alist))
-		  (if elt
-		      (funcall (cdr elt)))))))))))
+		  (unless just-from-file-name
+		    (if elt
+			(funcall (cdr elt))))))))))))
 
 (defun hack-local-variables-prop-line ()
   ;; Set local variables specified in the -*- line.
@@ -1327,78 +1333,89 @@
 Major modes can use this to examine user-specified local variables
 in order to initialize other data structure based on them.")
 
-(defun hack-local-variables ()
-  "Parse and put into effect this buffer's local variables spec."
-  (hack-local-variables-prop-line)
+(defun hack-local-variables (&optional mode-only)
+  "Parse and put into effect this buffer's local variables spec.
+If MODE-ONLY is non-nil, all we do is check whether the major mode
+is specified, returning t if it is specified."
+  (unless mode-only
+    (hack-local-variables-prop-line))
   ;; Look for "Local variables:" line in last page.
-  (save-excursion
-    (goto-char (point-max))
-    (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
-    (if (let ((case-fold-search t))
-	  (and (search-forward "Local Variables:" nil t)
-	       (or (eq enable-local-variables t)
-		   (and enable-local-variables
-			(save-window-excursion
-			  (switch-to-buffer (current-buffer))
-			  (save-excursion
-			    (beginning-of-line)
-			    (set-window-start (selected-window) (point)))
-			  (y-or-n-p (format "Set local variables as specified at end of %s? "
- 					    (if buffer-file-name
- 						(file-name-nondirectory
- 						 buffer-file-name)
- 					      (concat "buffer "
- 						      (buffer-name))))))))))
-	(let ((continue t)
-	      prefix prefixlen suffix beg
-	      (enable-local-eval enable-local-eval))
-	  ;; The prefix is what comes before "local variables:" in its line.
-	  ;; The suffix is what comes after "local variables:" in its line.
-	  (skip-chars-forward " \t")
-	  (or (eolp)
-	      (setq suffix (buffer-substring (point)
-					     (progn (end-of-line) (point)))))
-	  (goto-char (match-beginning 0))
-	  (or (bolp)
-	      (setq prefix
-		    (buffer-substring (point)
-				      (progn (beginning-of-line) (point)))))
+  (let (mode-specified)
+    (save-excursion
+      (goto-char (point-max))
+      (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+      (if (let ((case-fold-search t))
+	    (and (search-forward "Local Variables:" nil t)
+		 (or (eq enable-local-variables t)
+		     mode-only
+		     (and enable-local-variables
+			  (save-window-excursion
+			    (switch-to-buffer (current-buffer))
+			    (save-excursion
+			      (beginning-of-line)
+			      (set-window-start (selected-window) (point)))
+			    (y-or-n-p (format "Set local variables as specified at end of %s? "
+					      (if buffer-file-name
+						  (file-name-nondirectory
+						   buffer-file-name)
+						(concat "buffer "
+							(buffer-name))))))))))
+	  (let ((continue t)
+		prefix prefixlen suffix beg
+		mode-specified
+		(enable-local-eval enable-local-eval))
+	    ;; The prefix is what comes before "local variables:" in its line.
+	    ;; The suffix is what comes after "local variables:" in its line.
+	    (skip-chars-forward " \t")
+	    (or (eolp)
+		(setq suffix (buffer-substring (point)
+					       (progn (end-of-line) (point)))))
+	    (goto-char (match-beginning 0))
+	    (or (bolp)
+		(setq prefix
+		      (buffer-substring (point)
+					(progn (beginning-of-line) (point)))))
 
-	  (if prefix (setq prefixlen (length prefix)
-			   prefix (regexp-quote prefix)))
-	  (if suffix (setq suffix (concat (regexp-quote suffix) "$")))
-	  (while continue
-	    ;; Look at next local variable spec.
-	    (if selective-display (re-search-forward "[\n\C-m]")
-	      (forward-line 1))
-	    ;; Skip the prefix, if any.
-	    (if prefix
-		(if (looking-at prefix)
-		    (forward-char prefixlen)
-		  (error "Local variables entry is missing the prefix")))
-	    ;; Find the variable name; strip whitespace.
-	    (skip-chars-forward " \t")
-	    (setq beg (point))
-	    (skip-chars-forward "^:\n")
-	    (if (eolp) (error "Missing colon in local variables entry"))
-	    (skip-chars-backward " \t")
-	    (let* ((str (buffer-substring beg (point)))
-		   (var (read str))
-		  val)
-	      ;; Setting variable named "end" means end of list.
-	      (if (string-equal (downcase str) "end")
-		  (setq continue nil)
-		;; Otherwise read the variable value.
-		(skip-chars-forward "^:")
-		(forward-char 1)
-		(setq val (read (current-buffer)))
-		(skip-chars-backward "\n")
-		(skip-chars-forward " \t")
-		(or (if suffix (looking-at suffix) (eolp))
-		    (error "Local variables entry is terminated incorrectly"))
-		;; Set the variable.  "Variables" mode and eval are funny.
-		(hack-one-local-variable var val)))))))
-  (run-hooks 'hack-local-variables-hook))
+	    (if prefix (setq prefixlen (length prefix)
+			     prefix (regexp-quote prefix)))
+	    (if suffix (setq suffix (concat (regexp-quote suffix) "$")))
+	    (while continue
+	      ;; Look at next local variable spec.
+	      (if selective-display (re-search-forward "[\n\C-m]")
+		(forward-line 1))
+	      ;; Skip the prefix, if any.
+	      (if prefix
+		  (if (looking-at prefix)
+		      (forward-char prefixlen)
+		    (error "Local variables entry is missing the prefix")))
+	      ;; Find the variable name; strip whitespace.
+	      (skip-chars-forward " \t")
+	      (setq beg (point))
+	      (skip-chars-forward "^:\n")
+	      (if (eolp) (error "Missing colon in local variables entry"))
+	      (skip-chars-backward " \t")
+	      (let* ((str (buffer-substring beg (point)))
+		     (var (read str))
+		    val)
+		;; Setting variable named "end" means end of list.
+		(if (string-equal (downcase str) "end")
+		    (setq continue nil)
+		  ;; Otherwise read the variable value.
+		  (skip-chars-forward "^:")
+		  (forward-char 1)
+		  (setq val (read (current-buffer)))
+		  (skip-chars-backward "\n")
+		  (skip-chars-forward " \t")
+		  (or (if suffix (looking-at suffix) (eolp))
+		      (error "Local variables entry is terminated incorrectly"))
+		  (if mode-only
+		      (if (eq var 'mode)
+			  (setq mode-specified t))
+		    ;; Set the variable.  "Variables" mode and eval are funny.
+		    (hack-one-local-variable var val))))))))
+    (unless mode-only
+      (run-hooks 'hack-local-variables-hook))
+    mode-specified))
 
 (defvar ignored-local-variables
   '(enable-local-eval)
@@ -1481,6 +1498,14 @@
 	   (set var val))))
 
 
+(defvar change-major-mode-with-file-name t
+  "*Non-nil means \\[write-file] should set the major mode from the file name.
+However, the mode will not be changed if
+\(1) a local variables list or the `-*-' line specifies a major mode, or
+\(2) the current major mode is a \"special\" mode,
+     not suitable for ordinary files, or
+\(3) the new file name does not particularly specify any mode.")
+
 (defun set-visited-file-name (filename &optional no-query along-with-file)
   "Change name of file visited in current buffer to FILENAME.
 The next time the buffer is saved it will go in the newly specified file.
@@ -1576,7 +1601,16 @@
 	 (rename-file oauto buffer-auto-save-file-name t)))
   (and buffer-file-name
        (not along-with-file)
-       (set-buffer-modified-p t)))
+       (set-buffer-modified-p t))
+  ;; Update the major mode, if the file name determines it.
+  (condition-case nil
+      ;; Don't change the mode if it is special.
+      (or (not change-major-mode-with-file-name)
+	  (get major-mode 'mode-class)
+	  ;; Don't change the mode if the local variable list specifies it.
+	  (hack-local-variables t)
+	  (set-auto-mode t))
+    (error nil)))
 
 (defun write-file (filename &optional confirm coding-system)
   "Write current buffer into file FILENAME.