Apologies if this has been asked before (I couldn't find an answer to this.)

Frequently, when I open an existing file or create a new file with emacs, the mode is determined correctly based on the file extension (text following the last "." in the file name). However, this doesn't work when I create a script that has a "shebang" ("#!") on the first line. For example,

#!/usr/bin/env python

Emacs doesn't put the buffer into python mode unless I save the file (save-file) and open it again (find-file). Is there a way to rescan the buffer to determine the mode without saving the file?

Another scenario where this would come in handy is when the buffer has:

; -*- <MODE> -*-

on the first line.

3 Answers 3


I believe the command you want is normal-mode.

  • That does the trick! Thanks @Omar!
    – beevis
    Commented Aug 11, 2020 at 21:30

normal-mode (cited by @Omar in the alternative answer) calls, in part, set-auto-mode. The non-interactive function set-auto-mode, which can be evaluated by typing M-: and then (set-auto-mode), or by typing M-x eval-expression RET (set-auto-mode) RET, places the buffer in the proper major-mode based upon the shebang line provided that said line matches the expected format ... (infra). normal-mode; however, is interactive and contains some additional goodies such as killing all local variables, running certain hooks, etc.

The variable auto-mode-interpreter-regexp, defined in files.el has a default value of:

 "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"

We note that there is no space between the # and the ! symbol, whereas the O.P. is using a space between the aforementioned symbols; i.e., # !/usr/bin/env python. Emacs is unable to match the shebang line of the O.P. against the default regexp because of the aforementioned unexpected space between the # and ! symbols at the outset of said shebang line.

The doc-string for the above-mentioned variable provides as follows:

Regexp matching interpreters, for file mode determination.
This regular expression is matched against the first line of a file
to determine the file’s mode in ‘set-auto-mode’.  If it matches, the file
is assumed to be interpreted by the interpreter matched by the second group
of the regular expression.  The mode is then determined as the mode
associated with that interpreter in `interpreter-mode-alist`.
  • What you say is absolutely right, but it does not address the question: if I create a new file (without giving emacs any hint about its mode - e.g. no filename suffix) and I start typing, it will be in fundamental mode until the file is closed/reopeneed or I call normal-mode or I set the mode explicitly -- even if the shebang is correct. The shebang line will be matched only when you reopen the file.
    – NickD
    Commented Aug 10, 2020 at 21:30
  • @NickD -- Thank you for having a look at this particular answer answer. The doc-string cited in the answer states in relevant part: "...This regular expression is matched against the first line of a file to determine the file’s mode in set-auto-mode...." Therefore, the O.P. can use the correct/expected format for the shebang line and evaluate (set-auto-mode), which will automatically put the buffer in python-mode given the proposed shebang line of #!/usr/bin/env python -- without the space between # and !.
    – lawlist
    Commented Aug 10, 2020 at 21:35
  • You are right - I didn't read the doc string carefully enough, but I suspect I won't be the only one: I think you should make it more explicit.
    – NickD
    Commented Aug 10, 2020 at 22:00
  • @NickD -- thank you for the helpful suggestion. I have updated the answer accordingly.
    – lawlist
    Commented Aug 10, 2020 at 22:16
  • Thank you! It helped.
    – NickD
    Commented Aug 10, 2020 at 23:48

M-x revert-buffer works too as it calls normal-mode internally, though normal-mode does exactly what you want.

  • right that would work but you'd want to C-x C-s first :-). And revert-buffer prompts. I think I like normal-mode better.
    – beevis
    Commented Aug 11, 2020 at 22:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.