]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/sh-script.el
from trunk
[gnu-emacs] / lisp / progmodes / sh-script.el
index f7f5b99219a02921fee6cc3c39412e156c8080c4..ca0971bf675f753c29a700be19056314f0d9112d 100644 (file)
@@ -1,7 +1,7 @@
 ;;; sh-script.el --- shell-script editing commands for Emacs
 
-;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2001, 2002,
-;;  2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2001, 2002, 2003,
+;;  2004, 2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Version: 2.0f
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,9 +21,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -246,12 +244,12 @@ By default we have the following three hierarchies:
 
 csh            C Shell
   jcsh         C Shell with Job Control
-  tcsh         Turbo C Shell
-    itcsh      ? Turbo C Shell
+  tcsh         TENEX C Shell
+    itcsh      Ian's TENEX C Shell
 rc             Plan 9 Shell
   es           Extensible Shell
 sh             Bourne Shell
-  ash          ? Shell
+  ash          Almquist Shell
   jsh          Bourne Shell with Job Control
     bash       GNU Bourne Again Shell
     ksh88      Korn Shell '88
@@ -446,7 +444,7 @@ This is buffer-local in every such buffer.")
 
 (defvar sh-mode-map
   (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "Insert")))
+       (menu-map (make-sparse-keymap)))
     (define-key map "\C-c(" 'sh-function)
     (define-key map "\C-c\C-w" 'sh-while)
     (define-key map "\C-c\C-u" 'sh-until)
@@ -477,23 +475,83 @@ This is buffer-local in every such buffer.")
     (define-key map "\"" 'skeleton-pair-insert-maybe)
 
     (define-key map [remap complete-tag] 'comint-dynamic-complete)
-    (define-key map [remap newline-and-indent] 'sh-newline-and-indent)
     (define-key map [remap delete-backward-char]
       'backward-delete-char-untabify)
     (define-key map "\C-c:" 'sh-set-shell)
     (define-key map [remap backward-sentence] 'sh-beginning-of-command)
     (define-key map [remap forward-sentence] 'sh-end-of-command)
-    (define-key map [menu-bar insert] (cons "Insert" menu-map))
-    (define-key menu-map [sh-while]    '("While Loop" . sh-while))
-    (define-key menu-map [sh-until]    '("Until Loop" . sh-until))
-    (define-key menu-map [sh-tmp-file] '("Temporary File" . sh-tmp-file))
-    (define-key menu-map [sh-select]   '("Select Statement" . sh-select))
-    (define-key menu-map [sh-repeat]   '("Repeat Loop" . sh-repeat))
-    (define-key menu-map [sh-getopts]  '("Options Loop" . sh-while-getopts))
-    (define-key menu-map [sh-indexed-loop] '("Indexed Loop" . sh-indexed-loop))
-    (define-key menu-map [sh-if]       '("If Statement" . sh-if))
-    (define-key menu-map [sh-for]      '("For Loop" . sh-for))
-    (define-key menu-map [sh-case]     '("Case Statement" . sh-case))
+    (define-key map [menu-bar sh-script] (cons "Sh-Script" menu-map))
+    (define-key menu-map [sh-learn-buffer-indent]
+      '(menu-item "Learn buffer indentation" sh-learn-buffer-indent
+                 :help "Learn how to indent the buffer the way it currently is."))
+    (define-key menu-map [sh-learn-line-indent]
+      '(menu-item "Learn line indentation" sh-learn-line-indent
+                 :help "Learn how to indent a line as it currently is indented"))
+    (define-key menu-map [sh-show-indent]
+      '(menu-item "Show indentation" sh-show-indent
+                 :help "Show the how the current line would be indented"))
+    (define-key menu-map [sh-set-indent]
+      '(menu-item "Set indentation" sh-set-indent
+                 :help "Set the indentation for the current line"))
+
+    (define-key menu-map [sh-pair]
+      '(menu-item "Insert braces and quotes in pairs"
+                 (lambda ()
+                   (interactive)
+                   (require 'skeleton)
+                   (setq skeleton-pair (not skeleton-pair)))
+                 :button (:toggle . (and (boundp 'skeleton-pair)
+                                         skeleton-pair))
+                 :help "Inserting a brace or quote automatically inserts the matching pair"))
+
+    (define-key menu-map [sh-s0] '("--"))
+    ;; Insert
+    (define-key menu-map [sh-function]
+      '(menu-item "Function..." sh-function
+                 :help "Insert a function definition"))
+    (define-key menu-map [sh-add]
+      '(menu-item "Addition..." sh-add
+                 :help "Insert an addition of VAR and prefix DELTA for Bourne (type) shell"))
+    (define-key menu-map [sh-until]
+      '(menu-item "Until Loop" sh-until
+                 :help "Insert an until loop"))
+    (define-key menu-map [sh-repeat]
+      '(menu-item "Repeat Loop" sh-repeat
+                 :help "Insert a repeat loop definition"))
+    (define-key menu-map [sh-while]
+      '(menu-item "While Loop" sh-while
+                 :help "Insert a while loop"))
+    (define-key menu-map [sh-getopts]
+      '(menu-item "Options Loop" sh-while-getopts
+                 :help "Insert a while getopts loop."))
+    (define-key menu-map [sh-indexed-loop]
+      '(menu-item "Indexed Loop" sh-indexed-loop
+                 :help "Insert an indexed loop from 1 to n."))
+    (define-key menu-map [sh-select]
+      '(menu-item "Select Statement" sh-select
+                 :help "Insert a select statement "))
+    (define-key menu-map [sh-if]
+      '(menu-item "If Statement" sh-if
+                 :help "Insert an if statement"))
+    (define-key menu-map [sh-for]
+      '(menu-item "For Loop" sh-for
+                 :help "Insert a for loop"))
+    (define-key menu-map [sh-case]
+      '(menu-item "Case Statement" sh-case
+                 :help "Insert a case/switch statement"))
+    (define-key menu-map [sh-s1] '("--"))
+    (define-key menu-map [sh-exec]
+      '(menu-item "Execute region" sh-execute-region
+                 :help "Pass optional header and region to a subshell for noninteractive execution"))
+    (define-key menu-map [sh-exec-interpret]
+      '(menu-item "Execute script..." executable-interpret
+                 :help "Run script with user-specified args, and collect output in a buffer"))
+    (define-key menu-map [sh-set-shell]
+      '(menu-item "Set shell type..." sh-set-shell
+                 :help "Set this buffer's shell to SHELL (a string)"))
+    (define-key menu-map [sh-backslash-region]
+      '(menu-item "Backslash region" sh-backslash-region
+                 :help "Insert, align, or delete end-of-line backslashes on the lines in the region."))
     map)
   "Keymap used in Shell-Script mode.")
 
@@ -815,13 +873,13 @@ See `sh-feature'.")
      (:foreground "yellow" :weight bold))
     (((class color)
       (background light))
-     (:foreground "tan" ))
+     (:foreground "tan1" ))
     (t
      (:weight bold)))
   "Face to show a here-document"
   :group 'sh-indentation)
 
-;; These colours are probably icky.  It's just a placeholder though.
+;; These colors are probably icky.  It's just a placeholder though.
 (defface sh-quoted-exec
   '((((class color) (background dark))
      (:foreground "salmon"))
@@ -831,9 +889,7 @@ See `sh-feature'.")
      (:weight bold)))
   "Face to show quoted execs like ``"
   :group 'sh-indentation)
-
-;; backward-compatibility alias
-(put 'sh-heredoc-face 'face-alias 'sh-heredoc)
+(define-obsolete-face-alias 'sh-heredoc-face 'sh-heredoc "22.1")
 (defvar sh-heredoc-face 'sh-heredoc)
 
 (defface sh-escaped-newline '((t :inherit font-lock-string-face))
@@ -950,7 +1006,7 @@ If non-nil INDENTED indicates that the EOF was indented."
 (defun sh-font-lock-open-heredoc (start string)
   "Determine the syntax of the \\n after a <<EOF.
 START is the position of <<.
-STRING is the actual word used as delimiter (f.ex. \"EOF\").
+STRING is the actual word used as delimiter (e.g. \"EOF\").
 INDENTED is non-nil if the here document's content (and the EOF mark) can
 be indented (i.e. a <<- was used rather than just <<).
 Point is at the beginning of the next line."
@@ -1001,11 +1057,13 @@ subshells can nest."
           (state (if (eq (char-before) ?`) 'backquote 'code))
           ;; Stacked states in the context.
           (states '(double-quote)))
-      (while (and state (progn (skip-chars-forward "^'\\\"`$()" limit)
+      (while (and state (progn (skip-chars-forward "^'\\\\\"`$()" limit)
                                (< (point) limit)))
         ;; unescape " inside a $( ... ) construct.
         (case (char-after)
-          (?\' (skip-chars-forward "^'" limit))
+          (?\' (case state
+                 (double-quote nil)
+                 (t (forward-char 1) (skip-chars-forward "^'" limit))))
           (?\\ (forward-char 1))
           (?\" (case state
                  (double-quote (setq state (pop states)))
@@ -1051,6 +1109,9 @@ subshells can nest."
                  (when (memq (char-before) '(?\" ?\'))
                    (condition-case nil (progn (backward-sexp 1) t)
                      (error nil)))))
+         ;; Patterns can be preceded by an open-paren (Bug#1320).
+         (if (eq (char-before (point)) ?\()
+             (backward-char 1))
           (while (progn
                    (forward-comment (- (point-max)))
                    ;; Maybe we've bumped into an escaped newline.
@@ -1116,7 +1177,7 @@ subshells can nest."
 (defun sh-font-lock-syntactic-face-function (state)
   (let ((q (nth 3 state)))
     (if q
-        (if (char-valid-p q)
+        (if (characterp q)
             (if (eq q ?\`) 'sh-quoted-exec font-lock-string-face)
           sh-heredoc-face)
       font-lock-comment-face)))
@@ -1456,7 +1517,7 @@ buffer indents as it currently is indented.
 
 
 \\[backward-delete-char-untabify]       Delete backward one position, even if it was a tab.
-\\[sh-newline-and-indent]       Delete unquoted space and indent new line same as this one.
+\\[newline-and-indent]  Delete unquoted space and indent new line same as this one.
 \\[sh-end-of-command]   Go to end of successive commands.
 \\[sh-beginning-of-command]     Go to beginning of successive commands.
 \\[sh-set-shell]        Set this buffer's shell, and maybe its magic number.
@@ -2538,7 +2599,7 @@ If AND-MOVE is non-nil then move to end of word."
        (goto-char where))
     (prog1
        (buffer-substring (point)
-                         (progn (skip-chars-forward "^ \t\n;&|()")(point)))
+                         (progn (skip-chars-forward "^ \t\n;&|")(point)))
       (unless and-move
        (goto-char start)))))
 
@@ -2725,7 +2786,7 @@ If INFO is supplied it is used, else it is calculated from current line."
     (if msg (message "%s" msg) (message nil))))
 
 (defun sh-show-indent (arg)
-  "Show the how the currently line would be indented.
+  "Show the how the current line would be indented.
 This tells you which variable, if any, controls the indentation of
 this line.
 If optional arg ARG is non-null (called interactively with a prefix),
@@ -2917,8 +2978,7 @@ so that `occur-next' and `occur-prev' will work."
 ;;
 ;; (defun what-i-learned (list)
 ;;   (let ((p list))
-;;     (save-excursion
-;;       (set-buffer "*scratch*")
+;;     (with-current-buffer "*scratch*"
 ;;       (goto-char (point-max))
 ;;       (insert "(setq\n")
 ;;       (while p
@@ -2939,7 +2999,8 @@ so that `occur-next' and `occur-prev' will work."
 
 Output in buffer \"*indent*\" shows any lines which have conflicting
 values of a variable, and the final value of all variables learned.
-This buffer is popped to automatically if there are any discrepancies.
+When called interactively, pop to this buffer automatically if
+there are any discrepancies.
 
 If no prefix ARG is given, then variables are set to numbers.
 If a prefix arg is given, then variables are set to symbols when
@@ -3151,9 +3212,9 @@ This command can often take a long time to run."
           )))
       ;; Are abnormal hooks considered bad form?
       (run-hook-with-args 'sh-learned-buffer-hook learned-var-list)
-      (if (or sh-popup-occur-buffer (> num-diffs 0))
-         (pop-to-buffer out-buffer))
-      )))
+      (and (called-interactively-p 'any)
+          (or sh-popup-occur-buffer (> num-diffs 0))
+          (pop-to-buffer out-buffer)))))
 
 (defun sh-guess-basic-offset (vec)
   "See if we can determine a reasonable value for `sh-basic-offset'.
@@ -3689,7 +3750,7 @@ The document is bounded by `sh-here-document-word'."
   (interactive "*P")
   (self-insert-command (prefix-numeric-value arg))
   (or arg
-      (not (eq (char-after (- (point) 2)) last-command-char))
+      (not (looking-back "[^<]<<"))
       (save-excursion
        (backward-char 2)
        (sh-quoted-p))
@@ -3726,18 +3787,6 @@ The document is bounded by `sh-here-document-word'."
 
 
 
-(defun sh-newline-and-indent ()
-  "Strip unquoted whitespace, insert newline, and indent like current line."
-  (interactive "*")
-  (indent-to (prog1 (current-indentation)
-              (delete-region (point)
-                             (progn
-                               (or (zerop (skip-chars-backward " \t"))
-                                   (if (sh-quoted-p)
-                                       (forward-char)))
-                               (point)))
-              (newline))))
-
 (defun sh-beginning-of-command ()
   "Move point to successive beginnings of commands."
   (interactive)