• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /macosx-10.10.1/emacs-93/emacs/lisp/progmodes/

Lines Matching +refs:sh +refs:set +refs:shell

0 ;;; sh-script.el --- shell-script editing commands for Emacs
30 ;; Major mode for editing shell scripts. Bourne, C and rc shells as well
33 ;; available for filenames, variables known from the script, the shell and
47 ;; The following description applies to sh and derived shells (bash,
52 ;; sh-indent-for-XXX and sh-indent-after-XXX. For example.
53 ;; sh-indent-after-if controls the indenting of a line following
54 ;; an if statement, and sh-indent-for-fi controls the indentation
57 ;; You can set each to a numeric value, but it is often more convenient
58 ;; to a symbol such as `+' which uses the value of variable `sh-basic-offset'.
62 ;; + Indent right by sh-basic-offset
63 ;; - Indent left by sh-basic-offset
64 ;; ++ Indent right twice sh-basic-offset
65 ;; -- Indent left twice sh-basic-offset
66 ;; * Indent right half sh-basic-offset
67 ;; / Indent left half sh-basic-offset.
69 ;; There are 4 commands to help set the indentation variables:
71 ;; `sh-show-indent'
75 ;; `sh-set-indent'
76 ;; This allows you to set the value of the variable controlling the
78 ;; number of special symbols to denote the value of sh-basic-offset,
83 ;; `sh-learn-line-indent'
85 ;; command. It will set the variable to the value that makes the line
86 ;; indent like that. If called with a prefix argument then it will set
89 ;; `sh-learn-buffer-indent'
94 ;; easily find where something was set. It is popped to automatically
95 ;; if there are any conflicts found or if `sh-popup-occur-buffer' is
97 ;; `sh-indent-comment' will be set if all comments follow the same
98 ;; pattern; if they don't it will be set to nil.
99 ;; Whether `sh-basic-offset' is set is determined by variable
100 ;; `sh-learn-basic-offset'.
102 ;; Unfortunately, `sh-learn-buffer-indent' can take a long time to run
107 ;; `sh-learn-buffer-indent' on a small region of the buffer should
113 ;; them? Originally I had hoped that `sh-learn-buffer-indent'
117 ;; (add-hook 'sh-set-shell-hook 'sh-learn-buffer-indent)
119 ;; However... `sh-learn-buffer-indent' is extremely slow,
126 ;; Use `sh-name-style' to give a name to the indentation settings of
128 ;; Use `sh-load-style' to load indentation settings for the current
130 ;; Use `sh-save-styles-to-buffer' to write all the styles to a buffer
137 ;; especially if one is using `sh-learn-buffer-indent'. However, if
141 ;; To get round this, there is a variable `sh-make-vars-local' and 2
142 ;; functions: `sh-make-vars-local' and `sh-reset-indent-vars-to-global-values'.
144 ;; If `sh-make-vars-local' is non-nil, then these variables become
147 ;; can make them local with the command `sh-make-vars-local'.
149 ;; command `sh-reset-indent-vars-to-global-values'.
155 ;; Indentation for a sh script is complicated for a number of reasons:
184 ;; - `sh-learn-buffer-indent' is extremely slow.
203 (defvar font-lock-set-defaults)
207 (defgroup sh nil
212 (defgroup sh-script nil
215 :group 'sh
216 :prefix "sh-")
219 (defcustom sh-ancestor-alist
220 '((ash . sh)
227 (jsh . sh)
230 (oash . sh)
232 (posix . sh)
235 (wsh . sh)
237 (rpm . sh))
239 This is the basis for `sh-feature'. See also `sh-alias-alist'.
248 sh Bourne Shell
262 :group 'sh-script)
265 (defcustom sh-alias-alist
272 (sh5 . sh)))
273 "*Alist for transforming shell names to what they really are.
275 shell it really is."
277 :group 'sh-script)
280 (defcustom sh-shell-file
286 (let* ((shell (getenv "SHELL"))
287 (shell-base
288 (and shell (file-name-nondirectory shell))))
289 ;; shell-script mode doesn't support DOS/Windows shells,
291 (if (or (null shell)
292 (member (downcase shell-base)
295 "/bin/sh"
296 (file-name-sans-extension (downcase shell)))))
298 "/bin/sh")
299 "*The executable file name for the shell being programmed."
301 :group 'sh-script)
304 (defcustom sh-shell-arg
305 ;; bash does not need any options when run in a shell script,
314 ;; use of a non-free widget set.
318 "*Single argument string for the magic number. See `sh-feature'."
323 :group 'sh-script)
325 (defcustom sh-imenu-generic-expression
326 `((sh
328 "*Alist of regular expressions for recognizing shell function definitions.
329 See `sh-feature' and `imenu-generic-expression'."
336 :group 'sh-script
339 (defvar sh-shell-variables nil
340 "Alist of shell variable names that should be included in completion.
345 (defvar sh-shell-variables-initialized nil
346 "Non-nil if `sh-shell-variables' is initialized.")
348 (defun sh-canonicalize-shell (shell)
349 "Convert a shell name SHELL to the one we should handle it as."
350 (if (string-match "\\.exe\\'" shell)
351 (setq shell (substring shell 0 (match-beginning 0))))
352 (or (symbolp shell)
353 (setq shell (intern shell)))
354 (or (cdr (assq shell sh-alias-alist))
355 shell))
357 (defvar sh-shell (sh-canonicalize-shell (file-name-nondirectory sh-shell-file))
358 "The shell being programmed. This is set by \\[sh-set-shell].")
359 ;;;###autoload(put 'sh-shell 'safe-local-variable 'symbolp)
361 (defvar sh-mode-abbrev-table nil)
363 (define-abbrev-table 'sh-mode-abbrev-table ())
368 ;;(defvar sh-abbrevs
369 ;; '((csh sh-abbrevs shell
370 ;; "switch" 'sh-case
371 ;; "getopts" 'sh-while-getopts)
373 ;; (es sh-abbrevs shell
374 ;; "function" 'sh-function)
376 ;; (ksh88 sh-abbrevs sh
377 ;; "select" 'sh-select)
379 ;; (rc sh-abbrevs shell
380 ;; "case" 'sh-case
381 ;; "function" 'sh-function)
383 ;; (sh sh-abbrevs shell
384 ;; "case" 'sh-case
385 ;; "function" 'sh-function
386 ;; "until" 'sh-until
387 ;; "getopts" 'sh-while-getopts)
390 ;; (shell "for" sh-for
391 ;; "loop" sh-indexed-loop
392 ;; "if" sh-if
393 ;; "tmpfile" sh-tmp-file
394 ;; "while" sh-while)
396 ;; (zsh sh-abbrevs ksh88
397 ;; "repeat" 'sh-repeat))
398 ;; "Abbrev-table used in Shell-Script mode. See `sh-feature'.
399 ;;;Due to the internal workings of abbrev tables, the shell name symbol is
404 (defun sh-mode-syntax-table (table &rest list)
405 "Copy TABLE and set syntax for successive CHARs according to strings S."
411 (defvar sh-mode-syntax-table nil
415 (defvar sh-mode-default-syntax-table
416 (sh-mode-syntax-table ()
436 "Default syntax table for shell mode.")
438 (defvar sh-mode-syntax-table-input
439 '((sh . nil))
440 "Syntax-table used in Shell-Script mode. See `sh-feature'.")
442 (defvar sh-mode-map
445 (define-key map "\C-c(" 'sh-function)
446 (define-key map "\C-c\C-w" 'sh-while)
447 (define-key map "\C-c\C-u" 'sh-until)
448 (define-key map "\C-c\C-t" 'sh-tmp-file)
449 (define-key map "\C-c\C-s" 'sh-select)
450 (define-key map "\C-c\C-r" 'sh-repeat)
451 (define-key map "\C-c\C-o" 'sh-while-getopts)
452 (define-key map "\C-c\C-l" 'sh-indexed-loop)
453 (define-key map "\C-c\C-i" 'sh-if)
454 (define-key map "\C-c\C-f" 'sh-for)
455 (define-key map "\C-c\C-c" 'sh-case)
456 (define-key map "\C-c?" 'sh-show-indent)
457 (define-key map "\C-c=" 'sh-set-indent)
458 (define-key map "\C-c<" 'sh-learn-line-indent)
459 (define-key map "\C-c>" 'sh-learn-buffer-indent)
460 (define-key map "\C-c\C-\\" 'sh-backslash-region)
462 (define-key map "=" 'sh-assignment)
463 (define-key map "\C-c+" 'sh-add)
464 (define-key map "\C-\M-x" 'sh-execute-region)
466 (define-key map "<" 'sh-maybe-here-document)
475 (define-key map [remap newline-and-indent] 'sh-newline-and-indent)
478 (define-key map "\C-c:" 'sh-set-shell)
479 (define-key map [remap backward-sentence] 'sh-beginning-of-command)
480 (define-key map [remap forward-sentence] 'sh-end-of-command)
482 (define-key menu-map [sh-while] '("While Loop" . sh-while))
483 (define-key menu-map [sh-until] '("Until Loop" . sh-until))
484 (define-key menu-map [sh-tmp-file] '("Temporary File" . sh-tmp-file))
485 (define-key menu-map [sh-select] '("Select Statement" . sh-select))
486 (define-key menu-map [sh-repeat] '("Repeat Loop" . sh-repeat))
487 (define-key menu-map [sh-getopts] '("Options Loop" . sh-while-getopts))
488 (define-key menu-map [sh-indexed-loop] '("Indexed Loop" . sh-indexed-loop))
489 (define-key menu-map [sh-if] '("If Statement" . sh-if))
490 (define-key menu-map [sh-for] '("For Loop" . sh-for))
491 (define-key menu-map [sh-case] '("Case Statement" . sh-case))
495 (defvar sh-skeleton-pair-default-alist '((?( _ ?)) (?\))
500 (defcustom sh-dynamic-complete-functions
501 '(shell-dynamic-complete-environment-variable
502 shell-dynamic-complete-command
506 :group 'sh-script)
509 (defcustom sh-require-final-newline
514 See `sh-feature'."
518 :group 'sh-script)
521 (defcustom sh-assignment-regexp
526 (sh . "\\<\\([a-zA-Z0-9_]+\\)="))
529 sign. See `sh-feature'."
533 :group 'sh-script)
536 (defcustom sh-indentation 4
539 :group 'sh-script)
542 (defcustom sh-remember-variable-min 3
545 :group 'sh-script)
548 (defvar sh-header-marker nil
549 "When non-nil is the end of header for prepending by \\[sh-execute-region].
553 (defcustom sh-beginning-of-command
555 "*Regexp to determine the beginning of a shell command.
558 :group 'sh-script)
561 (defcustom sh-end-of-command
563 "*Regexp to determine the end of a shell command.
566 :group 'sh-script)
570 (defcustom sh-here-document-word "EOF"
580 will only work correctly if `sh-basic-offset' is a multiple of
586 :group 'sh-script)
589 (defvar sh-test
590 '((sh "[ ]" . 3)
592 "Initial input in Bourne if, while and until skeletons. See `sh-feature'.")
597 (defcustom sh-builtins
598 '((bash sh-append posix
605 (bourne sh-append shell
609 (csh sh-append shell
613 (dtksh sh-append wksh)
618 (jsh sh-append sh
621 (jcsh sh-append csh
624 (ksh88 sh-append bourne
628 (oash sh-append sh
634 (pdksh sh-append ksh88
637 (posix sh-append sh
643 (sh sh-append bourne
647 (shell "cd" "echo" "eval" "set" "shift" "umask" "unset" "wait")
649 (wksh sh-append ksh88
652 (zsh sh-append ksh88
659 "*List of all shell builtins for completing read and fontification.
661 implemented as aliases. See `sh-feature'."
665 :group 'sh-script)
669 (defcustom sh-leading-keywords
670 '((bash sh-append sh
679 (sh "!" "do" "elif" "else" "if" "then" "trap" "type" "until" "while"))
681 Given some confusion between keywords and builtins depending on shell and
683 flow of control or syntax. See `sh-feature'."
687 :group 'sh-script)
690 (defcustom sh-other-keywords
691 '((bash sh-append bourne
695 (bourne sh-append sh
698 (csh sh-append shell
705 (ksh88 sh-append bourne
711 (sh sh-append shell
715 (shell "break" "case" "continue" "exec" "exit")
717 (zsh sh-append bash
719 "*List of keywords not in `sh-leading-keywords'.
720 See `sh-feature'."
724 :group 'sh-script)
728 (defvar sh-variables
729 '((bash sh-append sh
745 (csh sh-append shell
748 "shell" "status" "time" "verbose")
750 (es sh-append shell
754 (jcsh sh-append csh
757 (ksh88 sh-append sh
762 (oash sh-append sh
765 (rc sh-append shell
769 (sh sh-append shell
773 (shell "COLUMNS" "EDITOR" "HOME" "HUSHLOGIN" "LANG" "LC_COLLATE"
778 (tcsh sh-append csh
789 (zsh sh-append ksh88
797 "List of all shell variables available for completing read.
798 See `sh-feature'.")
804 (defface sh-heredoc
817 :group 'sh-indentation)
820 (defface sh-quoted-exec
828 :group 'sh-indentation)
831 (put 'sh-heredoc-face 'face-alias 'sh-heredoc)
832 (defvar sh-heredoc-face 'sh-heredoc)
834 (defface sh-escaped-newline '((t :inherit font-lock-string-face))
836 :group 'sh-script
839 (defvar sh-font-lock-keywords-var
840 '((csh sh-append shell
844 (es sh-append executable-font-lock-keywords
848 (rc sh-append es)
849 (bash sh-append shell ("\\$(\\(\\sw+\\)" (1 'sh-quoted-exec t) ))
850 (sh sh-append shell
862 (shell
863 ;; Using font-lock-string-face here confuses sh-get-indent-info.
864 ("\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\\\)$" 3 'sh-escaped-newline)
868 (rpm sh-append rpm2
870 (rpm2 sh-append shell
872 "Default expressions to highlight in Shell Script modes. See `sh-feature'.")
874 (defvar sh-font-lock-keywords-var-1
875 '((sh "[ \t]in\\>"))
878 (defvar sh-font-lock-keywords-var-2 ()
882 ;; Note: parse-sexp-lookup-properties must be set to t for it to work.
883 (defconst sh-st-punc (string-to-syntax "."))
884 (defconst sh-st-symbol (string-to-syntax "_"))
885 (defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string
887 (defconst sh-escaped-line-re
893 (defconst sh-here-doc-open-re
895 sh-escaped-line-re "\\(\n\\)"))
897 (defvar sh-here-doc-markers nil)
898 (make-variable-buffer-local 'sh-here-doc-markers)
899 (defvar sh-here-doc-re sh-here-doc-open-re)
900 (make-variable-buffer-local 'sh-here-doc-re)
902 (defun sh-font-lock-close-heredoc (bol eof indented)
910 sh-escaped-line-re
922 (not (sh-in-comment-or-string (match-beginning 0))))
930 (and (re-search-forward sh-here-doc-open-re start 'move)
932 (sh-in-comment-or-string (point)))))
935 sh-here-doc-syntax)
939 (setq sh-here-doc-markers (delete eof sh-here-doc-markers))
940 (setq sh-here-doc-re
941 (concat sh-here-doc-open-re "\\|^\\([ \t]*\\)"
942 (regexp-opt sh-here-doc-markers t) "\\(\n\\)"))
945 (defun sh-font-lock-open-heredoc (start string)
953 (sh-in-comment-or-string start))
957 (unless (member str sh-here-doc-markers)
958 (push str sh-here-doc-markers)
959 (setq sh-here-doc-re
960 (concat sh-here-doc-open-re "\\|^\\([ \t]*\\)"
961 (regexp-opt sh-here-doc-markers t) "\\(\n\\)"))))
968 ;; If the sh-escaped-line-re part of sh-here-doc-re has matched
976 sh-here-doc-syntax))
978 (defun sh-font-lock-here-doc (limit)
980 ;; This looks silly, but it's because `sh-here-doc-re' keeps changing.
981 (re-search-forward sh-here-doc-re limit t))
983 (defun sh-quoted-subshell (limit)
1026 ;; sh-apply-quoted-subshell rather than apply the highlight
1036 (defun sh-is-quoted-p (pos)
1038 (not (sh-is-quoted-p (1- pos)))))
1040 (defun sh-font-lock-paren (start)
1051 (and (sh-is-quoted-p (1- (point)))
1059 (sh-is-quoted-p (point)))
1064 sh-st-punc)))
1066 (defun sh-apply-quoted-subshell ()
1067 "Apply the `sh-st-punc' syntax to all the matches in `match-data'.
1075 (put-text-property a b 'syntax-table sh-st-punc))) sh-st-punc)
1077 (defconst sh-font-lock-syntactic-keywords
1079 ;; word. In the shell, words are separated by metacharacters.
1081 ;; of the shell command language (under `quoting') but with `$' removed.
1082 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol)
1084 ("\\(\\\\\\)'" 1 ,sh-st-punc)
1086 ("\\$\\([?@]\\)" 1 ,sh-st-symbol)
1088 (sh-font-lock-here-doc
1089 (2 (sh-font-lock-open-heredoc
1091 (5 (sh-font-lock-close-heredoc
1096 (")" 0 (sh-font-lock-paren (match-beginning 0)))
1099 (sh-quoted-subshell
1100 (1 (sh-apply-quoted-subshell) t t))))
1102 (defun sh-font-lock-syntactic-face-function (state)
1106 (if (eq q ?\`) 'sh-quoted-exec font-lock-string-face)
1107 sh-heredoc-face)
1110 (defgroup sh-indentation nil
1111 "Variables controlling indentation in shell scripts.
1114 `sh-make-vars-local' is no-nil. See the documentation for
1115 variable `sh-make-vars-local', command `sh-make-vars-local'
1116 and command `sh-reset-indent-vars-to-global-values'."
1117 :group 'sh-script)
1120 (defcustom sh-set-shell-hook nil
1121 "*Hook run by `sh-set-shell'."
1123 :group 'sh-script)
1125 (defcustom sh-mode-hook nil
1126 "*Hook run by `sh-mode'."
1128 :group 'sh-script)
1130 (defcustom sh-learn-basic-offset nil
1131 "*When `sh-guess-basic-offset' should learn `sh-basic-offset'.
1140 :group 'sh-indentation)
1142 (defcustom sh-popup-occur-buffer nil
1143 "*Controls when `sh-learn-buffer-indent' pops the `*indent*' buffer.
1149 :group 'sh-indentation)
1151 (defcustom sh-blink t
1152 "*If non-nil, `sh-show-indent' shows the line indentation is relative to.
1157 :group 'sh-indentation)
1159 (defcustom sh-first-lines-indent 0
1162 Can be set to a number, or to nil which means leave it as is."
1167 :group 'sh-indentation)
1170 (defcustom sh-basic-offset 4
1174 :group 'sh-indentation)
1176 (defcustom sh-indent-comment nil
1187 :group 'sh-indentation)
1190 (defvar sh-debug nil
1191 "Enable lots of debug messages - if function `sh-debug' is enabled.")
1195 ;; (defun sh-debug (&rest args)
1197 ;; (if sh-debug
1199 (defmacro sh-debug (&rest args))
1201 (defconst sh-symbol-list
1203 :menu-tag "+ Indent right by sh-basic-offset")
1205 :menu-tag "- Indent left by sh-basic-offset")
1207 :menu-tag "++ Indent right twice sh-basic-offset")
1209 :menu-tag "-- Indent left twice sh-basic-offset")
1211 :menu-tag "* Indent right half sh-basic-offset")
1213 :menu-tag "/ Indent left half sh-basic-offset")))
1215 (defcustom sh-indent-for-else 0
1221 ,@ sh-symbol-list
1223 :group 'sh-indentation)
1225 (defconst sh-number-or-symbol-list
1229 sh-symbol-list))
1231 (defcustom sh-indent-for-fi 0
1233 :type `(choice ,@ sh-number-or-symbol-list )
1234 :group 'sh-indentation)
1236 (defcustom sh-indent-for-done 0
1238 :type `(choice ,@ sh-number-or-symbol-list )
1239 :group 'sh-indentation)
1241 (defcustom sh-indent-after-else '+
1243 :type `(choice ,@ sh-number-or-symbol-list )
1244 :group 'sh-indentation)
1246 (defcustom sh-indent-after-if '+
1250 :type `(choice ,@ sh-number-or-symbol-list )
1251 :group 'sh-indentation)
1253 (defcustom sh-indent-for-then 0
1255 :type `(choice ,@ sh-number-or-symbol-list )
1256 :group 'sh-indentation)
1258 (defcustom sh-indent-for-do 0
1262 :type `(choice ,@ sh-number-or-symbol-list)
1263 :group 'sh-indentation)
1265 (defcustom sh-indent-after-do '+
1270 :type `(choice ,@ sh-number-or-symbol-list)
1271 :group 'sh-indentation)
1273 (defcustom sh-indent-after-loop-construct '+
1278 If the `do' is on a line by itself, then `sh-indent-after-do' is used instead."
1279 :type `(choice ,@ sh-number-or-symbol-list)
1280 :group 'sh-indentation)
1283 (defcustom sh-indent-after-done 0
1289 :type `(choice ,@ sh-number-or-symbol-list)
1290 :group 'sh-indentation)
1292 (defcustom sh-indent-for-case-label '+
1295 :type `(choice ,@ sh-number-or-symbol-list)
1296 :group 'sh-indentation)
1298 (defcustom sh-indent-for-case-alt '++
1301 :type `(choice ,@ sh-number-or-symbol-list)
1302 :group 'sh-indentation)
1305 (defcustom sh-indent-for-continuation '+
1307 :type `(choice ,@ sh-number-or-symbol-list)
1308 :group 'sh-indentation)
1310 (defcustom sh-indent-after-open '+
1312 For an open paren after a function, `sh-indent-after-function' is used."
1313 :type `(choice ,@ sh-number-or-symbol-list)
1314 :group 'sh-indentation)
1316 (defcustom sh-indent-after-function '+
1318 :type `(choice ,@ sh-number-or-symbol-list)
1319 :group 'sh-indentation)
1321 ;; These 2 are for the rc shell:
1323 (defcustom sh-indent-after-switch '+
1325 This is for the rc shell."
1326 :type `(choice ,@ sh-number-or-symbol-list)
1327 :group 'sh-indentation)
1329 (defcustom sh-indent-after-case '+
1331 This is for the rc shell."
1332 :type `(choice ,@ sh-number-or-symbol-list)
1333 :group 'sh-indentation)
1335 (defcustom sh-backslash-column 48
1336 "*Column in which `sh-backslash-region' inserts backslashes."
1338 :group 'sh)
1340 (defcustom sh-backslash-align t
1341 "*If non-nil, `sh-backslash-region' will align backslashes."
1343 :group 'sh)
1347 (defun sh-mkword-regexpr (word)
1353 (defconst sh-re-done (sh-mkword-regexpr "done"))
1356 (defconst sh-kws-for-done
1357 '((sh . ( "while" "until" "for" ) )
1361 "Which keywords can match the word `done' in this shell.")
1364 (defconst sh-indent-supported
1365 '((sh . t)
1368 "Shell types that shell indenting can do something with.")
1370 (defvar sh-indent-supported-here nil
1371 "Non-nil if we support indentation for the current buffer's shell type.")
1373 (defconst sh-var-list
1375 sh-basic-offset sh-first-lines-indent sh-indent-after-case
1376 sh-indent-after-do sh-indent-after-done
1377 sh-indent-after-else
1378 sh-indent-after-if
1379 sh-indent-after-loop-construct
1380 sh-indent-after-open
1381 sh-indent-comment
1382 sh-indent-for-case-alt
1383 sh-indent-for-case-label
1384 sh-indent-for-continuation
1385 sh-indent-for-do
1386 sh-indent-for-done
1387 sh-indent-for-else
1388 sh-indent-for-fi
1389 sh-indent-for-then
1395 (defvar sh-make-vars-local t
1399 command `sh-make-vars-local'.
1408 (defun sh-mode ()
1409 "Major mode for editing shell scripts.
1412 Unless the file's magic number indicates the shell, your usual shell is
1415 This mode adapts to the variations between shells (see `sh-set-shell') by
1416 means of an inheritance based feature lookup (see `sh-feature'). This
1418 shell-specific features.
1420 The default style of this mode is that of Rosenblatt's Korn shell book.
1421 The syntax of the statements varies with the shell being used. The
1422 following commands are available, based on the current shell's syntax:
1423 \\<sh-mode-map>
1424 \\[sh-case] case statement
1425 \\[sh-for] for loop
1426 \\[sh-function] function definition
1427 \\[sh-if] if statement
1428 \\[sh-indexed-loop] indexed loop from 1 to n
1429 \\[sh-while-getopts] while getopts loop
1430 \\[sh-repeat] repeat loop
1431 \\[sh-select] select loop
1432 \\[sh-until] until loop
1433 \\[sh-while] while loop
1435 For sh and rc shells indentation commands are:
1436 \\[sh-show-indent] Show the variable controlling this line's indentation.
1437 \\[sh-set-indent] Set then variable controlling this line's indentation.
1438 \\[sh-learn-line-indent] Change the indentation variable so this line
1440 \\[sh-learn-buffer-indent] Set the indentation variables so the
1445 \\[sh-newline-and-indent] Delete unquoted space and indent new line same as this one.
1446 \\[sh-end-of-command] Go to end of successive commands.
1447 \\[sh-beginning-of-command] Go to beginning of successive commands.
1448 \\[sh-set-shell] Set this buffer's shell, and maybe its magic number.
1449 \\[sh-execute-region] Have optional header and region be executed in a subshell.
1451 \\[sh-maybe-here-document] Without prefix, following an unquoted < inserts here document.
1455 If you generally program a shell different from your login shell you can
1456 set `sh-shell-file' accordingly. If your shell's file name doesn't correctly
1457 indicate what shell it is use `sh-alias-alist' to translate.
1459 If your shell gives error messages with line numbers, you can use \\[executable-interpret]
1463 (setq major-mode 'sh-mode
1465 (use-local-map sh-mode-map)
1472 (make-local-variable 'sh-header-marker)
1473 (make-local-variable 'sh-shell-file)
1474 (make-local-variable 'sh-shell)
1482 (make-local-variable 'sh-shell-variables)
1483 (make-local-variable 'sh-shell-variables-initialized)
1485 (make-local-variable 'sh-indent-supported-here)
1487 (setq skeleton-pair-default-alist sh-skeleton-pair-default-alist)
1494 local-abbrev-table sh-mode-abbrev-table
1495 comint-dynamic-complete-functions sh-dynamic-complete-functions
1500 `((sh-font-lock-keywords
1501 sh-font-lock-keywords-1 sh-font-lock-keywords-2)
1504 (font-lock-syntactic-keywords . sh-font-lock-syntactic-keywords)
1506 . sh-font-lock-syntactic-face-function))
1508 skeleton-pair-filter-function 'sh-quoted-p
1509 skeleton-further-elements '((< '(- (min sh-indentation
1511 skeleton-filter-function 'sh-feature
1513 sh-indent-supported-here nil)
1514 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1515 ;; Parse or insert magic number for exec, and set all variables depending
1516 ;; on the shell thus determined.
1517 (sh-set-shell
1523 sh-shell-file)
1527 ((string-match "[.]sh\\>" buffer-file-name)
1528 "sh")
1536 "sh")
1538 sh-shell-file))
1540 (run-mode-hooks 'sh-mode-hook))
1543 (defalias 'shell-script-mode 'sh-mode)
1546 (defun sh-font-lock-keywords (&optional keywords)
1547 "Function to get simple fontification based on `sh-font-lock-keywords'.
1549 (sh-feature sh-font-lock-keywords-var
1550 (when (stringp (sh-feature sh-assignment-regexp))
1552 `((,(sh-feature sh-assignment-regexp)
1558 (defun sh-font-lock-keywords-1 (&optional builtins)
1561 (regexp-opt (sh-feature sh-leading-keywords) t)
1563 (regexp-opt (append (sh-feature sh-leading-keywords)
1564 (sh-feature sh-other-keywords))
1566 (sh-font-lock-keywords
1569 (regexp-opt (sh-feature sh-builtins) t)
1573 ,@(sh-feature sh-font-lock-keywords-var-2)))
1576 ,@(sh-feature sh-font-lock-keywords-var-1)))))
1578 (defun sh-font-lock-keywords-2 ()
1580 (sh-font-lock-keywords-1 t))
1583 (defvar sh-regexp-for-done nil
1586 (defvar sh-kw-alist nil
1587 "A buffer-local, since it is shell-type dependent, list of keywords.")
1590 ;; This is used to set `sh-kw-alist' which is a list of sublists each
1603 ;; `sh-get-indent-info' does not stop but may keep going and test
1609 (defconst sh-kw
1610 '((sh
1611 ("if" nil sh-handle-prev-if)
1612 ("elif" sh-handle-this-else sh-handle-prev-else)
1613 ("else" sh-handle-this-else sh-handle-prev-else)
1614 ("fi" sh-handle-this-fi sh-handle-prev-fi)
1615 ("then" sh-handle-this-then sh-handle-prev-then)
1616 ("(" nil sh-handle-prev-open)
1617 ("{" nil sh-handle-prev-open)
1618 ("[" nil sh-handle-prev-open)
1619 ("}" sh-handle-this-close nil)
1620 (")" sh-handle-this-close nil)
1621 ("]" sh-handle-this-close nil)
1622 ("case" nil sh-handle-prev-case)
1623 ("esac" sh-handle-this-esac sh-handle-prev-esac)
1624 (case-label nil sh-handle-after-case-label) ;; ???
1625 (";;" nil sh-handle-prev-case-alt-end) ;; ???
1626 ("done" sh-handle-this-done sh-handle-prev-done)
1627 ("do" sh-handle-this-do sh-handle-prev-do))
1630 ;; the regexp `sh-regexp-for-done' handles the extra keywords
1633 ("{" nil sh-handle-prev-open)
1634 ("}" sh-handle-this-close nil)
1635 ("case" sh-handle-this-rc-case sh-handle-prev-rc-case))))
1639 (defun sh-set-shell (shell &optional no-query-flag insert-flag)
1640 "Set this buffer's shell to SHELL (a string).
1642 and make the visited file executable via `executable-set-magic',
1650 Calls the value of `sh-set-shell-hook' if set."
1652 sh-shell-file)
1654 (lambda (x) (eq (cdr x) 'sh-mode))
1655 nil nil nil sh-shell-file)
1658 (if (string-match "\\.exe\\'" shell)
1659 (setq shell (substring shell 0 (match-beginning 0))))
1660 (setq sh-shell (intern (file-name-nondirectory shell))
1661 sh-shell (or (cdr (assq sh-shell sh-alias-alist))
1662 sh-shell))
1664 (setq sh-shell-file
1665 (executable-set-magic shell (sh-feature sh-shell-arg)
1667 (let ((tem (sh-feature sh-require-final-newline)))
1671 mode-line-process (format "[%s]" sh-shell)
1672 sh-shell-variables nil
1673 sh-shell-variables-initialized nil
1674 imenu-generic-expression (sh-feature sh-imenu-generic-expression))
1675 (make-local-variable 'sh-mode-syntax-table)
1676 (let ((tem (sh-feature sh-mode-syntax-table-input)))
1677 (setq sh-mode-syntax-table
1678 (if tem (apply 'sh-mode-syntax-table tem)
1679 sh-mode-default-syntax-table)))
1680 (set-syntax-table sh-mode-syntax-table)
1681 (dolist (var (sh-feature sh-variables))
1682 (sh-remember-variable var))
1684 (if (setq sh-indent-supported-here (sh-feature sh-indent-supported))
1686 (message "Setting up indent for shell type %s" sh-shell)
1687 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1688 (set (make-local-variable 'sh-kw-alist) (sh-feature sh-kw))
1689 (let ((regexp (sh-feature sh-kws-for-done)))
1691 (set (make-local-variable 'sh-regexp-for-done)
1692 (sh-mkword-regexpr (regexp-opt regexp t)))))
1694 ;; sh-mode has already made indent-line-function local
1696 (setq indent-line-function 'sh-indent-line)
1697 (if sh-make-vars-local
1698 (sh-make-vars-local))
1699 (message "Indentation setup for shell type %s" sh-shell))
1700 (message "No indentation for this shell type.")
1701 (setq indent-line-function 'sh-basic-indent-line))
1703 (setq font-lock-set-defaults nil)
1704 (font-lock-set-defaults)
1706 (run-hooks 'sh-set-shell-hook))
1709 (defun sh-feature (alist &optional function)
1710 "Index ALIST by the current shell.
1714 - Fall back on successive ancestors (see `sh-ancestor-alist') as long as
1715 the alist contains no value for the current shell.
1716 The ultimate default is always `sh'.
1718 - If the value thus looked up is a list starting with `sh-append',
1719 we call the function `sh-append' with the rest of the list as
1723 one shell to be derived from another shell.
1735 (let ((orig-sh-shell sh-shell))
1736 (let ((sh-shell sh-shell)
1738 (while (and sh-shell
1739 (not (setq elt (assq sh-shell alist))))
1740 (setq sh-shell (cdr (assq sh-shell sh-ancestor-alist))))
1741 ;; If the shell is not known, treat it as sh.
1743 (setq elt (assq 'sh alist)))
1746 (memq (car val) '(sh-append sh-modify)))
1749 ;; Refer to the value for a different shell,
1751 (let ((sh-shell (car (cdr val))))
1752 (sh-feature alist))
1755 (setq sh-shell orig-sh-shell
1762 ;;(defun sh-abbrevs (ancestor &rest list)
1763 ;; "Iff it isn't, define the current shell as abbrev table and fill that.
1768 ;; (or (if (boundp sh-shell)
1769 ;; (symbol-value sh-shell))
1773 ;; (define-abbrev-table sh-shell ())
1777 ;; (define-abbrev (symbol-value sh-shell)
1783 ;; (define-abbrev (symbol-value sh-shell)
1791 ;; (symbol-value sh-shell)))
1794 (defun sh-append (ancestor &rest list)
1799 (defun sh-modify (skeleton &rest list)
1810 (defun sh-basic-indent-line ()
1811 "Indent a line for Sh mode (shell script mode).
1812 Indent as far as preceding non-empty line, then by steps of `sh-indentation'.
1835 (max previous (* (1+ (/ current sh-indentation))
1836 sh-indentation))
1837 (* (1+ (/ current sh-indentation)) sh-indentation))))))
1842 (defun sh-execute-region (start end &optional flag)
1845 are already set which is why you can mark a header within the script.
1852 (setq sh-header-marker (if (> (prefix-numeric-value flag) 0)
1854 (if sh-header-marker
1857 (goto-char sh-header-marker)
1859 (shell-command-on-region (point-min)
1860 (setq end (+ sh-header-marker
1862 sh-shell-file)
1863 (delete-region sh-header-marker end)))
1864 (shell-command-on-region start end (concat sh-shell-file " -")))))
1867 (defun sh-remember-variable (var)
1869 (or (< (length var) sh-remember-variable-min)
1871 (assoc var sh-shell-variables)
1872 (push (cons var var) sh-shell-variables))
1877 (defun sh-quoted-p ()
1883 (defun sh-must-support-indent ()
1884 "*Signal an error if the shell type for this buffer is not supported.
1886 (unless sh-indent-supported-here
1887 (error "This buffer's shell does not support indentation through Emacs")))
1889 (defun sh-make-vars-local ()
1892 variable `sh-make-vars-local' has been set to nil.
1895 command `sh-reset-indent-vars-to-global-values'."
1897 (mapcar 'make-local-variable sh-var-list)
1900 (defun sh-reset-indent-vars-to-global-values ()
1902 Then, if variable `sh-make-vars-local' is non-nil, make them local."
1904 (mapcar 'kill-local-variable sh-var-list)
1905 (if sh-make-vars-local
1906 (mapcar 'make-local-variable sh-var-list)))
1909 ;; Theoretically these are only needed in shell and derived modes.
1911 (defconst sh-special-keywords "then\\|do")
1913 (defun sh-help-string-for-variable (var)
1914 "Construct a string for `sh-read-variable' when changing variable VAR ."
1917 (unless (memq var '(sh-first-lines-indent sh-indent-comment))
1924 the value of variable `sh-basic-offset'
1928 sh-basic-offset
1931 sh-symbol-list "\n\t"))))
1937 (defun sh-read-variable (var)
1940 (let ((minibuffer-help-form `(sh-help-string-for-variable
1952 (defun sh-in-comment-or-string (start)
1958 (defun sh-goto-matching-if ()
1961 (let ((found (sh-find-prev-matching "\\bif\\b" "\\bfi\\b" 1)))
1966 ;; Functions named sh-handle-this-XXX are called when the keyword on the
1968 ;; those named sh-handle-prev-XXX are when XXX appears on the previous line.
1970 (defun sh-handle-prev-if ()
1971 (list '(+ sh-indent-after-if)))
1973 (defun sh-handle-this-else ()
1974 (if (sh-goto-matching-if)
1976 (list "aligned to if" '(+ sh-indent-for-else))
1980 (defun sh-handle-prev-else ()
1981 (if (sh-goto-matching-if)
1982 (list '(+ sh-indent-after-if))
1985 (defun sh-handle-this-fi ()
1986 (if (sh-goto-matching-if)
1987 (list "aligned to if" '(+ sh-indent-for-fi))
1991 (defun sh-handle-prev-fi ()
1997 (sh-goto-matching-if)
2000 (defun sh-handle-this-then ()
2001 (let ((p (sh-goto-matching-if)))
2003 (list '(+ sh-indent-for-then))
2006 (defun sh-handle-prev-then ()
2007 (let ((p (sh-goto-matching-if)))
2009 (list '(+ sh-indent-after-if))
2012 (defun sh-handle-prev-open ()
2014 (let ((x (sh-prev-stmt)))
2022 (list '(+ sh-indent-after-function))
2023 (list '(+ sh-indent-after-open)))
2026 (defun sh-handle-this-close ()
2028 (if (sh-safe-forward-sexp -1)
2031 (defun sh-goto-matching-case ()
2032 (let ((found (sh-find-prev-matching "\\bcase\\b" "\\besac\\b" 1)))
2035 (defun sh-handle-prev-case ()
2039 (list '(+ sh-indent-for-case-label))
2042 (defun sh-handle-this-esac ()
2043 (if (sh-goto-matching-case)
2046 (defun sh-handle-prev-esac ()
2047 (if (sh-goto-matching-case)
2050 (defun sh-handle-after-case-label ()
2051 (if (sh-goto-matching-case)
2052 (list '(+ sh-indent-for-case-alt))))
2054 (defun sh-handle-prev-case-alt-end ()
2055 (if (sh-goto-matching-case)
2056 (list '(+ sh-indent-for-case-label))))
2058 (defun sh-safe-forward-sexp (&optional arg)
2066 (sh-debug "oops!(1) %d" (point))
2069 (defun sh-goto-match-for-done ()
2070 (let ((found (sh-find-prev-matching sh-regexp-for-done sh-re-done 1)))
2074 (defun sh-handle-this-done ()
2075 (if (sh-goto-match-for-done)
2076 (list "aligned to do stmt" '(+ sh-indent-for-done))))
2078 (defun sh-handle-prev-done ()
2079 (if (sh-goto-match-for-done)
2082 (defun sh-handle-this-do ()
2083 (if (sh-goto-match-for-done)
2084 (list '(+ sh-indent-for-do))))
2086 (defun sh-handle-prev-do ()
2094 (sh-goto-match-for-done))
2095 (sh-debug "match for done found on THIS line")
2096 (list '(+ sh-indent-after-loop-construct)))
2097 ((sh-goto-match-for-done)
2098 (sh-debug "match for done found on PREV line")
2099 (list '(+ sh-indent-after-do)))
2105 (defun sh-find-prev-switch ()
2109 (defun sh-handle-this-rc-case ()
2110 (if (sh-find-prev-switch)
2111 (list '(+ sh-indent-after-switch))
2112 ;; (list '(+ sh-indent-for-case-label))
2115 (defun sh-handle-prev-rc-case ()
2116 (list '(+ sh-indent-after-case)))
2118 (defun sh-check-rule (n thing)
2119 (let ((rule (nth n (assoc thing sh-kw-alist)))
2124 (sh-debug "rule (%d) for %s at %d is %s\n-> returned %s"
2129 (defun sh-get-indent-info ()
2143 special variables such as `sh-indent-comment'.
2147 ;; See comments before `sh-kw'.
2163 (eq (get-text-property (point) 'face) sh-heredoc-face))
2169 (setq result (list '(= sh-indent-comment)))
2171 ;; sh-indent-comment is t (indent as normal)
2172 (setq align-point (sh-prev-line nil))
2179 (if (sh-this-is-a-continuation)
2192 ;; (setq prev-line-end (sh-prev-line))
2193 (setq align-point (sh-prev-line nil))
2194 (list '(+ sh-indent-for-continuation))))
2198 (setq this-kw (sh-get-kw)))
2203 (if (setq val (sh-check-rule 1 this-kw))
2206 (sh-debug
2210 ;; set prev-line to continue processing remainder
2216 (setq prev-line-end (sh-prev-line 'end)))
2226 (while (and x (setq x (sh-prev-thing)))
2227 (sh-debug "at %d x is: %s result is: %s" (point) x result)
2231 sh-st-punc))
2232 (sh-debug "Case label) here")
2234 (if (setq val (sh-check-rule 2 x))
2243 (setq x (sh-safe-forward-sexp -1))
2251 (sh-debug "Checking special thing: %s" x)
2252 (if (setq val (sh-check-rule 2 x))
2257 (sh-debug "Skipping back for %s" x)
2259 (setq x (sh-safe-forward-sexp -1)))
2261 (sh-debug "Checking string %s at %s" x (point))
2262 (if (setq val (sh-check-rule 2 x))
2274 (sh-debug "result is %s" result)
2276 (sh-debug "No prev line!")
2277 (sh-debug "result: %s align-point: %s" result align-point)
2284 (sh-debug "result is now: %s" result)
2289 (list '= 'sh-first-lines-indent)))))
2293 (sh-debug "result is: %s" result)
2299 (defun sh-get-indent-var-for-line (&optional info)
2309 (setq info (sh-get-indent-info)))
2319 (error "sh-get-indent-var-for-line invalid elt: %s" elt))
2324 ;; A bit of a kludge - when we see the sh-indent-comment
2327 (if (eq var 'sh-indent-comment)
2334 (error "sh-get-indent-var-for-line invalid list elt: %s" elt)))
2359 (defun sh-prev-line (&optional end)
2369 sh-heredoc-face))
2379 (while (and (sh-this-is-a-continuation)
2386 (defun sh-prev-stmt ()
2403 (if (sh-safe-forward-sexp -1)
2405 (if (looking-at sh-special-keywords)
2414 (let ((back (sh-prev-line nil)))
2420 (if (or (and (bolp) (not (sh-this-is-a-continuation)))
2435 (sh-debug "Did not find prev stmt.")))
2439 (defun sh-get-word ()
2440 "Get a shell word skipping whitespace from point."
2446 (sh-safe-forward-sexp)
2453 (defun sh-prev-thing ()
2455 ;; This is called when `sh-get-indent-info' is working backwards on
2469 (min-point (if (sh-this-is-a-continuation)
2470 (sh-prev-line nil)
2478 (sh-debug "stopping at %d c is %s start=%d min-point=%d"
2495 (sh-debug "point: %d >= start: %d" (point) start)
2498 (sh-debug "Now at %d start=%d" (point) start)
2499 (setq kwd (sh-get-word))
2500 (if (member kwd (sh-feature sh-leading-keywords))
2509 (defun sh-this-is-a-continuation ()
2517 (defun sh-get-kw (&optional where and-move)
2529 (defun sh-find-prev-matching (open close &optional depth)
2530 "Find a matching token for a set of opening and closing keywords.
2542 (setq prev (sh-prev-stmt)))
2552 (sh-debug "found open at %d - depth = %d" (point) depth))
2555 (sh-debug "found close - depth = %d" depth))
2565 (defun sh-var-value (var &optional ignore-error)
2579 sh-basic-offset)
2581 (- sh-basic-offset))
2583 (* 2 sh-basic-offset))
2585 (* 2 (- sh-basic-offset)))
2587 (/ sh-basic-offset 2))
2589 (/ (- sh-basic-offset) 2))
2598 (defun sh-set-var-value (var value &optional no-symbol)
2604 (set var value))
2605 ((= value sh-basic-offset)
2606 (set var '+))
2607 ((= value (- sh-basic-offset))
2608 (set var '-))
2609 ((eq value (* 2 sh-basic-offset))
2610 (set var '++))
2611 ((eq value (* 2 (- sh-basic-offset)))
2612 (set var '--))
2613 ((eq value (/ sh-basic-offset 2))
2614 (set var '*))
2615 ((eq value (/ (- sh-basic-offset) 2))
2616 (set var '/))
2618 (set var value)))
2622 (defun sh-calculate-indent (&optional info)
2629 (setq info (sh-get-indent-info)))
2632 (sh-debug "info: %s ofs=%s" info ofs)
2646 (setq val (sh-var-value b))
2652 ;; set info to nil so we stop immediately
2662 (error "sh-calculate-indent invalid a a=%s b=%s" a b))))
2664 (error "sh-calculate-indent invalid elt: a=%s b=%s" a b))))
2666 (error "sh-calculate-indent invalid elt %s" elt)))
2667 (sh-debug "a=%s b=%s val=%s base-value=%s ofs=%s"
2671 (sh-debug "at end: base-value: %s ofs: %s" base-value ofs)
2677 (sh-debug "base (%d) + ofs (%d) = %d"
2681 (error "sh-calculate-indent: Help. base-value=%s ofs=%s"
2686 (defun sh-indent-line ()
2689 (let ((indent (sh-calculate-indent))
2701 (defun sh-blink (blinkpos &optional msg)
2711 (defun sh-show-indent (arg)
2717 If variable `sh-blink' is non-nil then momentarily go to the line
2720 (sh-must-support-indent)
2721 (let* ((info (sh-get-indent-info))
2722 (var (sh-get-indent-var-for-line info))
2727 (setq val (sh-calculate-indent info))
2740 (if sh-blink
2741 (let ((info (sh-get-indent-info)))
2744 (sh-blink (nth 1 (car info)) msg)
2749 (defun sh-set-indent ()
2754 (sh-must-support-indent)
2755 (let* ((info (sh-get-indent-info))
2756 (var (sh-get-indent-var-for-line info))
2759 (message "Cannot set indent - %s" var)
2761 (setq val (sh-read-variable var))
2764 (set var val)
2765 (setq indent-val (sh-calculate-indent info))
2774 ;; (sh-indent-line)
2777 (set var old-val)
2785 (defun sh-learn-line-indent (arg)
2789 then set it to a value which would indent the line the way it
2795 (sh-must-support-indent)
2802 (message "sh-learn-line-indent ignores empty lines.")
2803 (let* ((info (sh-get-indent-info))
2804 (var (sh-get-indent-var-for-line info))
2811 ((eq var 'sh-indent-comment)
2813 ;; - if curr-indent is 0, set to curr-indent
2815 ;; then set to t
2816 ;; - else set to curr-indent.
2817 (setq sh-indent-comment
2820 (let* ((sh-indent-comment t)
2821 (val2 (sh-calculate-indent info)))
2825 (message "%s set to %s" var (symbol-value var))
2827 ((numberp (setq sval (sh-var-value var)))
2828 (setq ival (sh-calculate-indent info))
2831 (sh-debug "curr-indent: %d ival: %d diff: %d var:%s sval %s"
2835 ;;; a value of `+' with the current value of sh-basic-offset
2839 (sh-set-var-value var new-val no-symbol)
2840 (message "%s set to %s" var (symbol-value var))
2848 (defun sh-mark-init (buffer)
2849 "Initialize a BUFFER to be used by `sh-mark-line'."
2855 (defun sh-mark-line (message point buffer &optional add-linenum occur-point)
2865 (set-marker m1 point (current-buffer))
2870 (set-buffer (get-buffer buffer))
2871 (set-buffer (get-buffer-create buffer))
2898 (defvar sh-learned-buffer-hook nil
2900 ;; Example of how to use sh-learned-buffer-hook
2905 ;; (set-buffer "*scratch*")
2915 ;; (add-hook 'sh-learned-buffer-hook 'what-i-learned)
2918 ;; Originally this was sh-learn-region-indent (beg end)
2921 (defun sh-learn-buffer-indent (&optional arg)
2928 If no prefix ARG is given, then variables are set to numbers.
2929 If a prefix arg is given, then variables are set to symbols when
2932 If a positive numerical prefix is given, then `sh-basic-offset'
2933 is set to the prefix's numerical value.
2934 Otherwise, sh-basic-offset may or may not be changed, according
2935 to the value of variable `sh-learn-basic-offset'.
2937 Abnormal hook `sh-learned-buffer-hook' if non-nil is called when the
2944 (sh-must-support-indent)
2950 previous-set-info
2962 (sh-mark-init out-buffer)
2966 (setq sh-basic-offset arg)
2968 (format "Using specified sh-basic-offset of %d"
2969 sh-basic-offset)))
2971 (format "Initial value of sh-basic-offset: %s"
2972 sh-basic-offset)))
2980 (let* ((sh-indent-comment t) ;; info must return default indent
2981 (info (sh-get-indent-info))
2982 (var (sh-get-indent-var-for-line info))
2990 ((numberp (setq sval (sh-var-value var 'no-error)))
2992 (setq ival (sh-calculate-indent))
2995 (sh-set-var-value var new-val 'no-symbol)
2997 (if (setq previous-set-info (assoc var learned-var-list))
3001 (nth 1 previous-set-info))
3002 (sh-mark-line
3003 (format "Variable %s was set to %s"
3006 (sh-mark-line
3007 (format " but was previously set to %s"
3008 (nth 1 previous-set-info))
3009 (nth 2 previous-set-info) out-buffer t)
3011 ;; (delete previous-set-info learned-var-list)
3012 (setcdr previous-set-info
3022 (sh-debug
3029 ((eq var 'sh-indent-comment)
3030 (unless (= curr-indent (sh-calculate-indent info))
3039 (sh-debug "Cannot learn this line!!!")
3041 (sh-debug
3046 (if sh-debug
3052 (sh-mark-line msg nil out-buffer)))
3065 (sh-debug msg)
3066 (sh-mark-line msg nil out-buffer)
3068 (sh-mark-line initial-msg nil out-buffer t t)
3070 (setq suggested (sh-guess-basic-offset vec))
3075 ;; t => set it if we have a single value as a number
3076 ((and (eq sh-learn-basic-offset t) (numberp suggested))
3078 ;; other non-nil => set it if only one value was found
3079 (sh-learn-basic-offset
3089 (append (list (list 'sh-basic-offset
3090 (setq sh-basic-offset new-value)
3095 (sh-mark-line
3096 (format "Changed sh-basic-offset to: %d" sh-basic-offset)
3098 (sh-mark-line
3100 (format "Possible value(s) for sh-basic-offset: %s"
3102 (format "Suggested sh-basic-offset: %d" suggested))
3107 (append (list (list 'sh-indent-comment comment-col (point-max)))
3109 (setq sh-indent-comment comment-col)
3111 (sh-mark-line "\nLearned variable settings:" nil out-buffer)
3118 (when (and (not (eq var 'sh-basic-offset))
3120 (sh-set-var-value var val)))))
3123 (sh-mark-line (format " %s %s" var (symbol-value var))
3137 (run-hook-with-args 'sh-learned-buffer-hook learned-var-list)
3138 (if (or sh-popup-occur-buffer (> num-diffs 0))
3142 (defun sh-guess-basic-offset (vec)
3143 "See if we can determine a reasonable value for `sh-basic-offset'.
3146 `sh-learn-buffer-indent'.
3174 (sh-debug (format "vec: %s\ntotals: %s\ntot: %d"
3197 (message "Possible choices for sh-basic-offset: %s"
3200 (message "No obvious value for sh-basic-offset. Perhaps %d"
3210 (defvar sh-styles-alist nil
3211 "A list of all known shell indentation styles.")
3213 (defun sh-name-style (name &optional confirm-overwrite)
3226 sh-var-list)))
3227 (style (assoc name sh-styles-alist)))
3235 (push slist sh-styles-alist))))
3237 (defun sh-load-style (name)
3238 "Set shell indentation values for this buffer from those in style NAME."
3241 sh-styles-alist nil t)))
3242 (let ((sl (assoc name sh-styles-alist)))
3244 (error "sh-load-style - style %s not known" name)
3246 (set (car var) (cdr var))))))
3248 (defun sh-save-styles-to-buffer (buff)
3256 (pp `(setq sh-styles-alist ',sh-styles-alist) (current-buffer))))
3264 ;; appropriate for your favorite shell.
3266 (defconst sh-non-closing-paren
3269 (propertize ")" 'syntax-table sh-st-punc 'rear-nonsticky t))
3271 (define-skeleton sh-case
3272 "Insert a case/switch statement. See `sh-feature'."
3298 (sh "expression: "
3301 > str sh-non-closing-paren \n
3304 > "*" sh-non-closing-paren \n
3309 (define-skeleton sh-for
3310 "Insert a for loop. See `sh-feature'."
3311 (csh sh-modify sh
3318 (es sh-modify rc
3320 (rc sh-modify sh
3324 (sh "Index variable: "
3326 > _ | ?$ & (sh-remember-variable str) \n
3331 (define-skeleton sh-indexed-loop
3332 "Insert an indexed loop from 1 to n. See `sh-feature'."
3333 (bash sh-modify posix)
3340 (es sh-modify rc
3347 > _ ?$ (sh-remember-variable str) > \n
3355 str ?= (sh-add (sh-remember-variable str) 1) \n
3361 > _ ?$ (sh-remember-variable str) \n
3363 (sh "Index variable: "
3367 > _ ?$ (sh-remember-variable str) \n
3371 (defun sh-shell-initialize-variables ()
3373 Add these variables to `sh-shell-variables'."
3377 (setq sh-shell-variables-initialized t)
3379 (sh-assignment 0)))
3383 (defvar sh-add-buffer)
3385 (defun sh-add-completer (string predicate code)
3386 "Do completion using `sh-shell-variables', but initialize it first.
3396 (let ((sh-shell-variables
3397 (with-current-buffer sh-add-buffer
3398 (or sh-shell-variables-initialized
3399 (sh-shell-initialize-variables))
3405 sh-shell-variables))))
3407 ((nil) (try-completion string sh-shell-variables predicate))
3408 (lambda (test-completion string sh-shell-variables predicate))
3409 (t (all-completions string sh-shell-variables predicate)))))
3411 (defun sh-add (var delta)
3412 "Insert an addition of VAR and prefix DELTA for Bourne (type) shell."
3414 (let ((sh-add-buffer (current-buffer)))
3415 (list (completing-read "Variable: " 'sh-add-completer)
3417 (insert (sh-feature '((bash . "$(( ")
3421 (sh . "`expr $")
3423 (sh-remember-variable var)
3426 (sh-feature '((bash . " ))")
3430 (sh . "`")
3435 (define-skeleton sh-function
3436 "Insert a function definition. See `sh-feature'."
3437 (bash sh-modify ksh88
3443 (rc sh-modify ksh88
3445 (sh ()
3452 (define-skeleton sh-if
3453 "Insert an if statement. See `sh-feature'."
3484 (sh "condition: "
3485 '(setq input (sh-feature sh-test))
3498 (define-skeleton sh-repeat
3499 "Insert a repeat loop definition. See `sh-feature'."
3509 ;;;(put 'sh-repeat 'menu-enable '(sh-feature sh-repeat))
3513 (define-skeleton sh-select
3514 "Insert a select statement. See `sh-feature'."
3519 (bash sh-append ksh88))
3520 ;;;(put 'sh-select 'menu-enable '(sh-feature sh-select))
3524 (define-skeleton sh-tmp-file
3525 "Insert code to setup temporary file handling. See `sh-feature'."
3526 (bash sh-append ksh88)
3528 "set tmp = `mktemp -t " str ".XXXXXX`" \n
3545 (ksh88 sh-modify sh
3550 (sh (file-name-nondirectory (buffer-file-name))
3556 (define-skeleton sh-until
3557 "Insert an until loop. See `sh-feature'."
3558 (sh "condition: "
3559 '(setq input (sh-feature sh-test))
3563 ;;;(put 'sh-until 'menu-enable '(sh-feature sh-until))
3567 (define-skeleton sh-while
3568 "Insert a while loop. See `sh-feature'."
3569 (csh sh-modify sh
3575 (es sh-modify sh
3579 (rc sh-modify sh
3583 (sh "condition: "
3584 '(setq input (sh-feature sh-test))
3591 (define-skeleton sh-while-getopts
3592 "Insert a while getopts loop. See `sh-feature'.
3595 (bash sh-modify sh
3609 > "set " v1 & " = $2" | -4 & _ \n
3620 (ksh88 sh-modify sh
3624 (posix sh-modify sh
3626 (sh "optstring: "
3636 > str "|+" str sh-non-closing-paren \n
3639 > "*" sh-non-closing-paren \n
3652 "shift " (sh-add "OPTIND" -1) \n
3657 (defun sh-assignment (arg)
3662 (sh-remember-variable
3664 (if (re-search-forward (sh-feature sh-assignment-regexp)
3671 (defun sh-maybe-here-document (arg)
3673 The document is bounded by `sh-here-document-word'."
3680 (sh-quoted-p))
3681 (let ((tabs (if (string-match "\\`-" sh-here-document-word)
3685 sh-here-document-word)))
3686 (insert sh-here-document-word)
3690 (sh-quoted-p)
3704 (autoload 'shell-dynamic-complete-command "shell"
3710 (autoload 'shell-dynamic-complete-environment-variable "shell"
3715 (defun sh-newline-and-indent ()
3722 (if (sh-quoted-p)
3727 (defun sh-beginning-of-command ()
3730 (if (re-search-backward sh-beginning-of-command nil t)
3733 (defun sh-end-of-command ()
3736 (if (re-search-forward sh-end-of-command nil t)
3741 (defun sh-backslash-region (from to delete-flag)
3749 shell command and conveniently use this command."
3753 (let ((column sh-backslash-column)
3757 (if sh-backslash-align
3786 (sh-append-backslash column)
3787 (sh-delete-backslash))
3791 (defun sh-append-backslash (column)
3797 (indent-to column (if sh-backslash-align nil 1)))
3798 (indent-to column (if sh-backslash-align nil 1))
3801 (defun sh-delete-backslash ()
3810 (provide 'sh-script)
3813 ;;; sh-script.el ends here