;;; sh-script.el --- shell-script editing commands for Emacs
-;; Copyright (C) 1993, 94, 95, 96, 97, 1999, 2001
+;; Copyright (C) 1993, 94, 95, 96, 97, 1999, 2001, 2003
;; Free Software Foundation, Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; You can do this automatically like this:
;; (add-hook 'sh-set-shell-hook 'sh-learn-buffer-indent)
;;
-;; However... `sh-learn-buffer-indent' is extremely slow,
+;; However... `sh-learn-buffer-indent' is extremely slow,
;; especially on large-ish buffer. Also, if there are conflicts the
;; "last one wins" which may not produce the desired setting.
;;
(defcustom sh-alias-alist
- (nconc (if (eq system-type 'gnu/linux)
+ (append (if (eq system-type 'gnu/linux)
'((csh . tcsh)
(ksh . pdksh)))
;; for the time being
-(easy-mmode-defsyntax sh-mode-syntax-table
- '((?\# . "<")
- (?\^l . ">#")
- (?\n . ">#")
- (?\" . "\"\"")
- (?\' . "\"'")
- (?\` . "\"`")
- (?! . "_")
- (?% . "_")
- (?: . "_")
- (?. . "_")
- (?^ . "_")
- (?~ . "_")
- (?< . ".")
- (?> . "."))
- "Syntax-table used in Shell-Script mode.")
+(defvar sh-mode-syntax-table
+ '((sh eval sh-mode-syntax-table ()
+ ?\# "<"
+ ?\n ">#"
+ ?\" "\"\""
+ ?\' "\"'"
+ ?\` "\"`"
+ ?! "_"
+ ?% "_"
+ ?: "_"
+ ?. "_"
+ ?^ "_"
+ ?~ "_"
+ ?< "."
+ ?> ".")
+ (csh eval identity sh)
+ (rc eval identity sh))
+ "Syntax-table used in Shell-Script mode. See `sh-feature'.")
(defvar sh-mode-map
(let ((map (make-sparse-keymap))
(define-key map "`" 'skeleton-pair-insert-maybe)
(define-key map "\"" 'skeleton-pair-insert-maybe)
- (substitute-key-definition 'complete-tag 'comint-dynamic-complete
- map (current-global-map))
- (substitute-key-definition 'newline-and-indent 'sh-newline-and-indent
- map (current-global-map))
- (substitute-key-definition 'delete-backward-char
- 'backward-delete-char-untabify
- map (current-global-map))
+ (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)
- (substitute-key-definition 'beginning-of-defun
- 'sh-beginning-of-compound-command
- map (current-global-map))
- (substitute-key-definition 'backward-sentence 'sh-beginning-of-command
- map (current-global-map))
- (substitute-key-definition 'forward-sentence 'sh-end-of-command
- map (current-global-map))
+ (define-key map [remap beginning-of-defun]
+ 'sh-beginning-of-compound-command)
+ (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))
(defface sh-heredoc-face
'((((class color)
(background dark))
- (:foreground "yellow" :bold t))
+ (:foreground "yellow" :weight bold))
(((class color)
(background light))
(:foreground "tan" ))
(t
- (:bold t)))
+ (:weight bold)))
"Face to show a here-document"
:group 'sh-indentation)
(defvar sh-heredoc-face 'sh-heredoc-face)
sh-symbol-list))
(defcustom sh-indent-for-fi 0
- "*How much to indent a fi relative to an if. Usually 0."
+ "*How much to indent a fi relative to an if. Usually 0."
:type `(choice ,@ sh-number-or-symbol-list )
:group 'sh-indentation)
(defcustom sh-indent-for-done '0
- "*How much to indent a done relative to its matching stmt. Usually 0."
+ "*How much to indent a done relative to its matching stmt. Usually 0."
:type `(choice ,@ sh-number-or-symbol-list )
:group 'sh-indentation)
:group 'sh-indentation)
(defcustom sh-indent-for-then '+
- "*How much to indent an then relative to an if."
+ "*How much to indent a then relative to an if."
:type `(choice ,@ sh-number-or-symbol-list )
:group 'sh-indentation)
(defvar sh-indent-supported-here nil
"Non-nil if we support indentation for the current buffer's shell type.")
-(defconst sh-electric-rparen-needed
- '((sh . t))
- "Non-nil if the shell type needs an electric handling of case alternatives.")
-
(defconst sh-var-list
'(
sh-basic-offset sh-first-lines-indent sh-indent-after-case
((and buffer-file-name
(string-match "\\.m?spec$" buffer-file-name))
"rpm")))))
- (sh-set-shell (or interpreter sh-shell-file) nil nil)))
+ (sh-set-shell (or interpreter sh-shell-file) nil nil))
+ (run-hooks 'sh-mode-hook))
;;;###autoload
(defalias 'shell-script-mode 'sh-mode)
(defun sh-set-shell (shell &optional no-query-flag insert-flag)
"Set this buffer's shell to SHELL (a string).
-Makes this script executable via `executable-set-magic', and sets up the
-proper starting #!-line, if INSERT-FLAG is non-nil.
+When used interactively, insert the proper starting #!-line,
+and make the visited file executable via `executable-set-magic',
+perhaps querying depending on the value of `executable-query'.
+
+When this function is called noninteractively, INSERT-FLAG (the third
+argument) controls whether to insert a #!-line and think about making
+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 "Name or path of shell: "
- interpreter-mode-alist
- (lambda (x) (eq (cdr x) 'sh-mode)))
+ (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)
(eq executable-query 'function)
t))
(if (string-match "\\.exe\\'" shell)
sh-shell-variables-initialized nil
imenu-generic-expression (sh-feature sh-imenu-generic-expression)
imenu-case-fold-search nil)
+ (set-syntax-table (or (sh-feature sh-mode-syntax-table)
+ (standard-syntax-table)))
(dolist (var (sh-feature sh-variables))
(sh-remember-variable var))
(make-local-variable 'indent-line-function)
;; (symbol-value sh-shell)))
+(defun sh-mode-syntax-table (table &rest list)
+ "Copy TABLE and set syntax for successive CHARs according to strings S."
+ (setq table (copy-syntax-table table))
+ (while list
+ (modify-syntax-entry (pop list) (pop list) table))
+ table)
+
(defun sh-append (ancestor &rest list)
"Return list composed of first argument (a list) physically appended to rest."
(nconc list ancestor))
(defun sh-mark-init (buffer)
"Initialize a BUFFER to be used by `sh-mark-line'."
- (let ((main-buffer (current-buffer)))
- (save-excursion
- (set-buffer (get-buffer-create buffer))
- (erase-buffer)
- (occur-mode)
- (setq occur-buffer main-buffer)
- )))
+ (save-excursion
+ (set-buffer (get-buffer-create buffer))
+ (erase-buffer)
+ (occur-mode)
+ ))
(defun sh-mark-line (message point buffer &optional add-linenum occur-point)
If OCCUR-POINT is non-nil then the line is marked as a new occurrence
so that `occur-next' and `occur-prev' will work."
(let ((m1 (make-marker))
- (main-buffer (current-buffer))
start
(line ""))
(when point
(set-buffer (get-buffer buffer))
(set-buffer (get-buffer-create buffer))
(occur-mode)
- (setq occur-buffer main-buffer)
)
(goto-char (point-max))
(setq start (point))
(insert "\n")
(if point
(progn
- (put-text-property start (point) 'occur m1)
+ (put-text-property start (point) 'occur-target m1)
(if occur-point
- (put-text-property occur-point (1+ occur-point)
- 'occur-point t))
+ (put-text-property start occur-point
+ 'occur-match t))
))
)))