]> git.eshelyaron.com Git - emacs.git/commitdiff
File-local-variable support for sh-script; add mksh support
authorDaniel Colascione <dancol@dancol.org>
Wed, 21 May 2014 01:54:33 +0000 (18:54 -0700)
committerDaniel Colascione <dancol@dancol.org>
Wed, 21 May 2014 01:54:33 +0000 (18:54 -0700)
* lisp/files.el (interpreter-mode-alist): Add mksh.

* lisp/progmodes/sh-script.el (sh-ancestor-alist): Add mksh, a pdksh
derivative.
(sh-alias-alist): Alias /system/bin/sh (Android's system shell) to
mksh. Improve custom spec; allow regular expressions.
(sh-shell): Delegate name splitting to `sh-canonicalize-shell'.
(sh-after-hack-local-variables): New function.
(sh-mode): Use it; respect file-local `sh-shell' variable.
(sh-set-shell): Use `sh-canonicalize-shell' instead of open-coding
the normalization.
(sh-canonicalize-shell): Rewrite to support regexes.

Fixes: debbugs:17333
lisp/ChangeLog
lisp/files.el
lisp/progmodes/sh-script.el

index 733d060f453233bcd763a9184b6a3347c1ba5c2d..cfa4625969022c1a90fe7c2d1582c1f7ce436ffd 100644 (file)
@@ -1,3 +1,18 @@
+2014-05-21  Daniel Colascione  <dancol@dancol.org>
+
+       * files.el (interpreter-mode-alist): Add mksh.
+
+       * progmodes/sh-script.el (sh-ancestor-alist): Add mksh, a pdksh
+       derivative.
+       (sh-alias-alist): Alias /system/bin/sh (Android's system shell) to
+       mksh. Improve custom spec; allow regular expressions.
+       (sh-shell): Delegate name splitting to `sh-canonicalize-shell'.
+       (sh-after-hack-local-variables): New function.
+       (sh-mode): Use it; respect file-local `sh-shell' variable. (bug#17333)
+       (sh-set-shell): Use `sh-canonicalize-shell' instead of open-coding
+       the normalization.
+       (sh-canonicalize-shell): Rewrite to support regexes.
+
 2014-05-19  Leo Liu  <sdl.web@gmail.com>
 
        * emacs-lisp/cl-lib.el (cl-endp): Conform to CL's semantics.
index 666316a23538c99813bb923d43cf4df0257f89c8..c153a11b24358a6a12f71e856b783f3ff21e4346 100644 (file)
@@ -2501,6 +2501,7 @@ and `magic-mode-alist', which determines modes based on file contents.")
      ("[acjkwz]sh" . sh-mode)
      ("r?bash2?" . sh-mode)
      ("dash" . sh-mode)
+     ("mksh" . sh-mode)
      ("\\(dt\\|pd\\|w\\)ksh" . sh-mode)
      ("es" . sh-mode)
      ("i?tcsh" . sh-mode)
index 3ff4f57b88721a8f29ace71e83000e2f8f3eaf25..6d7179c0447ff0908be1329c249cc05f6d29d226 100644 (file)
     (ksh88 . jsh)
     (oash . sh)
     (pdksh . ksh88)
+    (mksh . pdksh)
     (posix . sh)
     (tcsh . csh)
     (wksh . ksh88)
@@ -262,6 +263,7 @@ sh          Bourne Shell
       ksh      Korn Shell '93
        dtksh   CDE Desktop Korn Shell
       pdksh    Public Domain Korn Shell
+        mksh    MirOS BSD Korn Shell
       wksh     Window Korn Shell
       zsh      Z Shell
   oash         SCO OA (curses) Shell
@@ -271,7 +273,6 @@ sh          Bourne Shell
   :version "24.4"                       ; added dash
   :group 'sh-script)
 
-
 (defcustom sh-alias-alist
   (append (if (eq system-type 'gnu/linux)
             '((csh . tcsh)
@@ -279,11 +280,20 @@ sh                Bourne Shell
         ;; for the time being
         '((ksh . ksh88)
            (bash2 . bash)
-          (sh5 . sh)))
+          (sh5 . sh)
+           ;; Android's system shell
+           ("^/system/bin/sh$" . mksh)))
   "Alist for transforming shell names to what they really are.
-Use this where the name of the executable doesn't correspond to the type of
-shell it really is."
-  :type '(repeat (cons symbol symbol))
+Use this where the name of the executable doesn't correspond to
+the type of shell it really is.  Keys are regular expressions
+matched against the full path of the interpreter.  (For backward
+compatibility, keys may also be symbols, which are matched
+against the interpreter's basename.  The values are symbols
+naming the shell."
+  :type '(repeat (cons (radio
+                        (regexp :tag "Regular expression")
+                        (symbol :tag "Basename"))
+                       (symbol :tag "Shell")))
   :group 'sh-script)
 
 
@@ -387,15 +397,20 @@ the car and cdr are the same symbol.")
   "Non-nil if `sh-shell-variables' is initialized.")
 
 (defun sh-canonicalize-shell (shell)
-  "Convert a shell name SHELL to the one we should handle it as."
-  (if (string-match "\\.exe\\'" shell)
-      (setq shell (substring shell 0 (match-beginning 0))))
-  (or (symbolp shell)
-      (setq shell (intern shell)))
-  (or (cdr (assq shell sh-alias-alist))
-      shell))
-
-(defvar sh-shell (sh-canonicalize-shell (file-name-nondirectory sh-shell-file))
+  "Convert a shell name SHELL to the one we should handle it as.
+SHELL is a full path to the shell interpreter; return a shell
+name symbol."
+  (cl-loop
+     with shell = (cond ((string-match "\\.exe\\'" shell)
+                         (substring shell 0 (match-beginning 0)))
+                        (t shell))
+     with shell-base = (intern (file-name-nondirectory shell))
+     for (key . value) in sh-alias-alist
+     if (and (stringp key) (string-match key shell)) return value
+     if (eq key shell-base) return value
+     finally return shell-base))
+
+(defvar sh-shell (sh-canonicalize-shell sh-shell-file)
   "The shell being programmed.  This is set by \\[sh-set-shell].")
 ;;;###autoload(put 'sh-shell 'safe-local-variable 'symbolp)
 
@@ -1533,6 +1548,12 @@ When the region is active, send the region instead."
 \f
 ;; mode-command and utility functions
 
+(defun sh-after-hack-local-variables ()
+  (when (assq 'sh-shell file-local-variables-alist)
+    (sh-set-shell (if (symbolp sh-shell)
+                      (symbol-name sh-shell)
+                    sh-shell))))
+
 ;;;###autoload
 (define-derived-mode sh-mode prog-mode "Shell-script"
   "Major mode for editing shell scripts.
@@ -1643,7 +1664,9 @@ with your script for an edit-interpret-debug cycle."
          ((string-match "[.]csh\\>"    buffer-file-name) "csh")
         ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
          (t sh-shell-file))
-   nil nil))
+   nil nil)
+  (add-hook 'hack-local-variables-hook
+    #'sh-after-hack-local-variables nil t))
 
 ;;;###autoload
 (defalias 'shell-script-mode 'sh-mode)
@@ -2253,9 +2276,7 @@ Calls the value of `sh-set-shell-hook' if set."
                     t))
   (if (string-match "\\.exe\\'" shell)
       (setq shell (substring shell 0 (match-beginning 0))))
-  (setq sh-shell (intern (file-name-nondirectory shell))
-       sh-shell (or (cdr (assq sh-shell sh-alias-alist))
-                    sh-shell))
+  (setq sh-shell (sh-canonicalize-shell shell))
   (if insert-flag
       (setq sh-shell-file
            (executable-set-magic shell (sh-feature sh-shell-arg)