- ;; If we found modes to use, invoke them now,
- ;; outside the save-excursion.
- (unless just-from-file-name
- (dolist (mode (nreverse modes))
- (if (not (functionp mode))
- (message "Ignoring unknown mode `%s'" mode)
- (setq done t)
- (funcall mode))))
- ;; 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)
- (keep-going t))
- ;; Remove backup-suffixes from file name.
- (setq name (file-name-sans-versions name))
- (while keep-going
- (setq keep-going nil)
- (let ((alist auto-mode-alist)
- (mode nil))
- ;; Find first matching alist entry.
- (let ((case-fold-search
- (memq system-type '(vax-vms windows-nt cygwin))))
- (while (and (not mode) alist)
- (if (string-match (car (car alist)) name)
- (if (and (consp (cdr (car alist)))
- (nth 2 (car alist)))
- (setq mode (car (cdr (car alist)))
- name (substring name 0 (match-beginning 0))
- keep-going t)
- (setq mode (cdr (car alist))
- keep-going nil)))
- (setq alist (cdr alist))))
- (if mode
- ;; When JUST-FROM-FILE-NAME is set,
- ;; we are working on behalf of set-visited-file-name.
- ;; In that case, if the major mode specified is the
- ;; same one we already have, don't actually reset it.
- ;; We don't want to lose minor modes such as Font Lock.
- (unless (and just-from-file-name (eq mode major-mode))
- (funcall mode))
- ;; If we can't deduce a mode from the file name,
- ;; 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.
- (let ((interpreter
- (save-excursion
- (goto-char (point-min))
- (if (looking-at auto-mode-interpreter-regexp)
- (match-string 2)
- "")))
- elt)
- ;; Map interpreter name to a mode.
- (setq elt (assoc (file-name-nondirectory interpreter)
- interpreter-mode-alist))
- (unless just-from-file-name
- (if elt
- (funcall (cdr elt))))))))))))
-
+ ;; If we found modes to use, invoke them now, outside the save-excursion.
+ (if modes
+ (catch 'nop
+ (dolist (mode (nreverse modes))
+ (if (not (functionp mode))
+ (message "Ignoring unknown mode `%s'" mode)
+ (setq done t)
+ (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.
+ (setq mode (save-excursion
+ (goto-char (point-min))
+ (if (looking-at auto-mode-interpreter-regexp)
+ (match-string 2)
+ ""))
+ ;; Map interpreter name to a mode, signalling we're done at the
+ ;; same time.
+ done (assoc (file-name-nondirectory mode)
+ interpreter-mode-alist))
+ ;; 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.
+ (unless done
+ (if (setq done (save-excursion
+ (goto-char (point-min))
+ (assoc-default nil magic-mode-alist
+ (lambda (re dummy)
+ (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.
+ (let ((case-fold-search
+ (memq system-type '(vax-vms windows-nt cygwin))))
+ (if (and (setq mode (assoc-default name auto-mode-alist
+ 'string-match))
+ (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)))))))))
+
+;; 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
+;; same one we already have, don't actually reset it. We don't want to lose
+;; minor modes such as Font Lock.
+(defun set-auto-mode-0 (mode &optional keep-mode-if-same)
+ "Apply MODE and return it.
+If optional arg KEEP-MODE-IF-SAME is non-nil, MODE is chased of
+any aliases and compared to current major mode. If they are the
+same, do nothing and return nil."
+ (when keep-mode-if-same
+ (while (symbolp (symbol-function mode))
+ (setq mode (symbol-function mode)))
+ (if (eq mode major-mode)
+ (setq mode nil)))
+ (when mode
+ (funcall mode)
+ mode))