Recognize shebang lines that pass '-S/--split-string' to 'env'
* etc/NEWS: announce the change. * lisp/files.el (auto-mode-interpreter-regexp): Add optional '-S' switch to the ignored group capturing the env invocation. Allow multiple spaces between #!, interpreter and first argument: empirically, Linux's 'execve' accepts that. (Bug#66902) * test/lisp/files-tests.el (files-tests--check-shebang): New helper to generate a temporary file with a given interpreter line, and assert that the mode picked by 'set-auto-mode' is derived from an expected mode. Write the 'should' form so that failure reports include useful context; for example: (ert-test-failed ((should (equal (list shebang actual-mode) (list shebang expected-mode))) :form (equal ("#!/usr/bin/env -S make -f" fundamental-mode) ("#!/usr/bin/env -S make -f" makefile-mode)) :value nil :explanation (list-elt 1 (different-atoms fundamental-mode makefile-mode)))) * test/lisp/files-tests.el (files-tests-auto-mode-interpreter): New test; exercise some aspects of 'interpreter-mode-alist'.
This commit is contained in:
parent
779e669bbc
commit
53bd2d57f3
3 changed files with 41 additions and 2 deletions
6
etc/NEWS
6
etc/NEWS
|
@ -233,6 +233,12 @@ to enter the file you want to modify.
|
|||
It can be used to customize the look of the appointment notification
|
||||
displayed on the mode line when 'appt-display-mode-line' is non-nil.
|
||||
|
||||
---
|
||||
*** Emacs now recognizes shebang lines that pass -S/--split-string to env.
|
||||
When visiting a script that invokes 'env -S INTERPRETER ARGS...' in
|
||||
its shebang line, Emacs will now skip over 'env -S' and deduce the
|
||||
major mode based on the interpreter.
|
||||
|
||||
** Emacs Server and Client
|
||||
|
||||
---
|
||||
|
|
|
@ -3245,8 +3245,16 @@ and `inhibit-local-variables-suffixes'. If
|
|||
temp))
|
||||
|
||||
(defvar auto-mode-interpreter-regexp
|
||||
(purecopy "#![ \t]?\\([^ \t\n]*\
|
||||
/bin/env[ \t]\\)?\\([^ \t\n]+\\)")
|
||||
(purecopy
|
||||
(concat
|
||||
"#![ \t]*"
|
||||
;; Optional group 1: env(1) invocation.
|
||||
"\\("
|
||||
"[^ \t\n]*/bin/env[ \t]*"
|
||||
"\\(?:-S[ \t]*\\|--split-string\\(?:=\\|[ \t]*\\)\\)?"
|
||||
"\\)?"
|
||||
;; Group 2: interpreter.
|
||||
"\\([^ \t\n]+\\)"))
|
||||
"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
|
||||
|
|
|
@ -1656,6 +1656,31 @@ The door of all subtleties!
|
|||
(should (equal (file-name-base "foo") "foo"))
|
||||
(should (equal (file-name-base "foo/bar") "bar")))
|
||||
|
||||
(defun files-tests--check-shebang (shebang expected-mode)
|
||||
"Assert that mode for SHEBANG derives from EXPECTED-MODE."
|
||||
(let ((actual-mode
|
||||
(ert-with-temp-file script-file
|
||||
:text shebang
|
||||
(find-file script-file)
|
||||
(if (derived-mode-p expected-mode)
|
||||
expected-mode
|
||||
major-mode))))
|
||||
;; Tuck all the information we need in the `should' form: input
|
||||
;; shebang, expected mode vs actual.
|
||||
(should
|
||||
(equal (list shebang actual-mode)
|
||||
(list shebang expected-mode)))))
|
||||
|
||||
(ert-deftest files-tests-auto-mode-interpreter ()
|
||||
"Test that `set-auto-mode' deduces correct modes from shebangs."
|
||||
(files-tests--check-shebang "#!/bin/bash" 'sh-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/env bash" 'sh-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/env python" 'python-base-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/env python3" 'python-base-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/env -S awk -v FS=\"\\t\" -v OFS=\"\\t\" -f" 'awk-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/env -S make -f" 'makefile-mode)
|
||||
(files-tests--check-shebang "#!/usr/bin/make -f" 'makefile-mode))
|
||||
|
||||
(ert-deftest files-test-dir-locals-auto-mode-alist ()
|
||||
"Test an `auto-mode-alist' entry in `.dir-locals.el'"
|
||||
(find-file (ert-resource-file "whatever.quux"))
|
||||
|
|
Loading…
Add table
Reference in a new issue