From: Glenn Morris Date: Tue, 10 Sep 2013 20:38:52 +0000 (-0400) Subject: Treat interpreter-mode-alist as alist of regexps, not literals X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1662^2~52 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1af4c2203ce7954c089133234ba80e6272ce9458;p=emacs.git Treat interpreter-mode-alist as alist of regexps, not literals Cf http://lists.gnu.org/archive/html/emacs-devel/2005-08/msg00472.html * lisp/files.el (interpreter-mode-alist): Convert to regexps. (set-auto-mode): Adapt for this. * lisp/progmodes/cperl-mode.el (cperl-clobber-mode-lists): Comment out unused variable. * lisp/progmodes/cc-mode.el (interpreter-mode-alist): * lisp/progmodes/python.el (interpreter-mode-alist): * lisp/progmodes/ruby-mode.el (interpreter-mode-alist): Convert to regexps. * lisp/progmodes/sh-script.el (sh-set-shell): No longer use interpreter-mode-alist to get list of shells. * etc/NEWS: Mention this. Fixes: debbugs:15306 --- diff --git a/etc/NEWS b/etc/NEWS index 9914da31859..78f99dbc621 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -614,6 +614,14 @@ file using `set-file-extended-attributes'. ** `visited-file-modtime' now returns -1 for nonexistent files. Formerly it returned a list (-1 LOW USEC PSEC), but this was ambiguous in the presence of files with negative time stamps. + +** The cars of the elements in `interpreter-mode-alist' are now treated +as regexps rather than literal strings. For the time being, any +element whose car does not start with "\\" is still treated as a +literal string, so this change should not cause any incompatibilities +if you have code that just adds elements to the list, only if you are +actually using interpreter-mode-alist for something. + * Lisp Changes in Emacs 24.4 diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 9282aa16a2d..32ea5e72efd 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,15 @@ 2013-09-10 Glenn Morris + * files.el (interpreter-mode-alist): Convert to regexps. + (set-auto-mode): Adapt for this. (Bug#15306) + * progmodes/cperl-mode.el (cperl-clobber-mode-lists): + Comment out unused variable. + * progmodes/cc-mode.el (interpreter-mode-alist): + * progmodes/python.el (interpreter-mode-alist): + * progmodes/ruby-mode.el (interpreter-mode-alist): Convert to regexps. + * progmodes/sh-script.el (sh-set-shell): + No longer use interpreter-mode-alist to get list of shells. + * progmodes/cc-mode.el (awk-mode): Remove duplicate autoload. 2013-09-10 Stefan Monnier diff --git a/lisp/files.el b/lisp/files.el index f9ff3c936bd..2315448c549 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2447,48 +2447,43 @@ and `magic-mode-alist', which determines modes based on file contents.") (mapcar (lambda (l) (cons (purecopy (car l)) (cdr l))) - '(("perl" . perl-mode) - ("perl5" . perl-mode) - ("miniperl" . perl-mode) - ("wish" . tcl-mode) - ("wishx" . tcl-mode) - ("tcl" . tcl-mode) - ("tclsh" . tcl-mode) - ("expect" . tcl-mode) - ("scm" . scheme-mode) - ("ash" . sh-mode) - ("bash" . sh-mode) - ("bash2" . sh-mode) - ("csh" . sh-mode) - ("dtksh" . sh-mode) - ("es" . sh-mode) - ("itcsh" . sh-mode) - ("jsh" . sh-mode) - ("ksh" . sh-mode) - ("oash" . sh-mode) - ("pdksh" . sh-mode) - ("rbash" . sh-mode) - ("rc" . sh-mode) - ("rpm" . sh-mode) - ("sh" . sh-mode) - ("sh5" . sh-mode) - ("tcsh" . sh-mode) - ("wksh" . sh-mode) - ("wsh" . sh-mode) - ("zsh" . sh-mode) - ("tail" . text-mode) - ("more" . text-mode) - ("less" . text-mode) - ("pg" . text-mode) - ("make" . makefile-gmake-mode) ; Debian uses this - ("guile" . scheme-mode) - ("clisp" . lisp-mode) - ("emacs" . emacs-lisp-mode))) + '(("\\`\\(mini\\)?perl5?\\'" . perl-mode) + ("\\`wishx?\\'" . tcl-mode) + ("\\`tcl\\(sh\\)?\\'" . tcl-mode) + ("\\`expect\\'" . tcl-mode) + ("\\`scm\\'" . scheme-mode) + ("\\`[acjkwz]sh\\'" . sh-mode) + ("\\`bash2?\\'" . sh-mode) + ("\\`dtksh\\'" . sh-mode) + ("\\`es\\'" . sh-mode) + ("\\`itcsh\\'" . sh-mode) + ("\\`oash\\'" . sh-mode) + ("\\`pdksh\\'" . sh-mode) + ("\\`rbash\\'" . sh-mode) + ("\\`rc\\'" . sh-mode) + ("\\`rpm\\'" . sh-mode) + ("\\`sh5?\\'" . sh-mode) + ("\\`tcsh\\'" . sh-mode) + ("\\`wksh\\'" . sh-mode) + ("\\`tail\\'" . text-mode) + ("\\`more\\'" . text-mode) + ("\\`less\\'" . text-mode) + ("\\`pg\\'" . text-mode) + ("\\`make\\'" . makefile-gmake-mode) ; Debian uses this + ("\\`guile\\'" . scheme-mode) + ("\\`clisp\\'" . lisp-mode) + ("\\`emacs\\'" . emacs-lisp-mode))) "Alist mapping interpreter names to major modes. This is used for files whose first lines match `auto-mode-interpreter-regexp'. -Each element looks like (INTERPRETER . MODE). -If INTERPRETER matches the name of the interpreter specified in the first line -of a script, mode MODE is enabled. +Each element looks like (REGEXP . MODE). +If REGEXP matches the name (minus any directory part) of the interpreter +specified in the first line of a script, enable major mode MODE. + +Emacs versions earlier than 24.4 treat the car of each element as a +literal string that must match the entire name, rather than a regexp. +For backwards compatibility, any REGEXP that does not begin with \"\\\\\" +continues to be treated in this way. This behavior may be removed in +future and should not be relied upon. See also `auto-mode-alist'.") @@ -2683,19 +2678,27 @@ we don't actually set it to the same mode the buffer already has." ;; 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 - (setq mode (save-excursion - (goto-char (point-min)) - (if (looking-at auto-mode-interpreter-regexp) - (match-string 2) - "")) - ;; Map interpreter name to a mode, signaling 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))) + (and (not done) + (setq mode (save-excursion + (goto-char (point-min)) + (if (looking-at auto-mode-interpreter-regexp) + (match-string 2)))) + ;; Map interpreter name to a mode, signaling we're done at the + ;; same time. + (setq done (assoc-default + (file-name-nondirectory mode) + ;; Backwards compat: if car of i-m-alist does not start + ;; with "\\", treat as literal string. + (mapcar (lambda (e) + (if (string-match-p "\\`\\\\" (car e)) + e + (cons + (format "\\`%s\\'" (regexp-quote (car e))) + (cdr e)))) + interpreter-mode-alist) + #'string-match-p)) + ;; If we found an interpreter mode to use, invoke it now. + (set-auto-mode-0 done keep-mode-if-same)) ;; Next try matching the buffer beginning against magic-mode-alist. (unless done (if (setq done (save-excursion diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index e977a415d62..bffc5b95d25 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1555,7 +1555,7 @@ Key bindings: (cons "Pike" (c-lang-const c-mode-menu pike))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("pike" . pike-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("\\`pike\\'" . pike-mode)) ;;;###autoload (define-derived-mode pike-mode prog-mode "Pike" @@ -1589,10 +1589,7 @@ Key bindings: ;; Support for AWK ;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("\\`[gmn]?awk\\'" . awk-mode)) (c-define-abbrev-table 'awk-mode-abbrev-table '(("else" "else" c-electric-continued-statement 0) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 770e78bb3b1..1eea6972707 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -412,15 +412,15 @@ Affects: `cperl-font-lock', `cperl-electric-lbrace-space', "use cperl-vc-rcs-header or cperl-vc-sccs-header instead." "22.1") -(defcustom cperl-clobber-mode-lists - (not - (and - (boundp 'interpreter-mode-alist) - (assoc "miniperl" interpreter-mode-alist) - (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist))) - "*Whether to install us into `interpreter-' and `extension' mode lists." - :type 'boolean - :group 'cperl) +;;; (defcustom cperl-clobber-mode-lists +;;; (not +;;; (and +;;; (boundp 'interpreter-mode-alist) +;;; (assoc "miniperl" interpreter-mode-alist) +;;; (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist))) +;;; "*Whether to install us into `interpreter-' and `extension' mode lists." +;;; :type 'boolean +;;; :group 'cperl) (defcustom cperl-info-on-command-no-prompt nil "*Not-nil (and non-null) means not to prompt on C-h f. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 05d707acf43..bba4453cce8 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -225,7 +225,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) ;;;###autoload -(add-to-list 'interpreter-mode-alist (cons (purecopy "python") 'python-mode)) +(add-to-list 'interpreter-mode-alist (cons (purecopy "\\`python[23.]*\\'") 'python-mode)) (defgroup python nil "Python Language's flying circus support for Emacs." diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 0f868255589..9dc2c4fb6c9 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -1968,8 +1968,7 @@ The variable `ruby-indent-level' controls the amount of indentation. "\\)\\'")) 'ruby-mode)) ;;;###autoload -(dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) - (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'ruby-mode))) +(add-to-list 'interpreter-mode-alist (cons (purecopy "\\`\\(rbx\\|j?ruby\\(1\\.[89]\\)?\\)\\'") 'ruby-mode)) (provide 'ruby-mode) diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 292bc2369a6..3ea2afb6fc3 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -2170,11 +2170,18 @@ the visited file executable, and NO-QUERY-FLAG (the second argument) controls whether to query about making the visited file executable. Calls the value of `sh-set-shell-hook' if set." - (interactive (list (completing-read (format "Shell \(default %s\): " - sh-shell-file) - interpreter-mode-alist - (lambda (x) (eq (cdr x) 'sh-mode)) - nil nil nil sh-shell-file) + (interactive (list (completing-read + (format "Shell \(default %s\): " + sh-shell-file) + ;; This used to use interpreter-mode-alist, but that is + ;; no longer appropriate now that uses regexps. + ;; Maybe there could be a separate variable that lists + ;; the shells, used here and to construct i-mode-alist. + ;; But the following is probably good enough: + (append (mapcar (lambda (e) (symbol-name (car e))) + sh-ancestor-alist) + '("csh" "rc" "sh")) + nil nil nil nil sh-shell-file) (eq executable-query 'function) t)) (if (string-match "\\.exe\\'" shell)