comparison lisp/progmodes/sh-script.el @ 90428:a8190f7e546e

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 285-296) - Update from CVS - Merge from gnus--rel--5.10 - Update from CVS: admin/FOR-RELEASE: Update refcard section. * gnus--rel--5.10 (patch 102-104) - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-64
author Miles Bader <miles@gnu.org>
date Wed, 07 Jun 2006 18:05:10 +0000
parents 72dea2ff0142 44d77343c9ac
children 8a8e69664178
comparison
equal deleted inserted replaced
90427:ddb25860d044 90428:a8190f7e546e
812 (:foreground "tan" )) 812 (:foreground "tan" ))
813 (t 813 (t
814 (:weight bold))) 814 (:weight bold)))
815 "Face to show a here-document" 815 "Face to show a here-document"
816 :group 'sh-indentation) 816 :group 'sh-indentation)
817
818 ;; These colours are probably icky. It's just a placeholder though.
819 (defface sh-quoted-exec
820 '((((class color) (background dark))
821 (:foreground "salmon"))
822 (((class color) (background light))
823 (:foreground "magenta"))
824 (t
825 (:weight bold)))
826 "Face to show quoted execs like ``"
827 :group 'sh-indentation)
828
817 ;; backward-compatibility alias 829 ;; backward-compatibility alias
818 (put 'sh-heredoc-face 'face-alias 'sh-heredoc) 830 (put 'sh-heredoc-face 'face-alias 'sh-heredoc)
819 (defvar sh-heredoc-face 'sh-heredoc) 831 (defvar sh-heredoc-face 'sh-heredoc)
820 832
821 (defface sh-escaped-newline '((t :inherit font-lock-string-face)) 833 (defface sh-escaped-newline '((t :inherit font-lock-string-face))
831 (es sh-append executable-font-lock-keywords 843 (es sh-append executable-font-lock-keywords
832 ("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1 844 ("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1
833 font-lock-variable-name-face)) 845 font-lock-variable-name-face))
834 846
835 (rc sh-append es) 847 (rc sh-append es)
836 848 (bash sh-append shell ("\\$(\\(\\sw+\\)" (1 'sh-quoted-exec t) ))
837 (sh sh-append shell 849 (sh sh-append shell
838 ;; Variable names. 850 ;; Variable names.
839 ("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2 851 ("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2
840 font-lock-variable-name-face) 852 font-lock-variable-name-face)
841 ;; Function names. 853 ;; Function names.
965 (defun sh-font-lock-here-doc (limit) 977 (defun sh-font-lock-here-doc (limit)
966 "Search for a heredoc marker." 978 "Search for a heredoc marker."
967 ;; This looks silly, but it's because `sh-here-doc-re' keeps changing. 979 ;; This looks silly, but it's because `sh-here-doc-re' keeps changing.
968 (re-search-forward sh-here-doc-re limit t)) 980 (re-search-forward sh-here-doc-re limit t))
969 981
982 (defun sh-quoted-subshell (limit)
983 "Search for a subshell embedded in a string. Find all the unescaped
984 \" characters within said subshell, remembering that subshells can nest."
985 (if (re-search-forward "\"\\(?:.\\|\n\\)*?\\(\\$(\\|`\\)" limit t)
986 ;; bingo we have a $( or a ` inside a ""
987 (let ((char (char-after (point)))
988 (continue t)
989 (pos (point))
990 (data nil) ;; value to put into match-data (and return)
991 (last nil) ;; last char seen
992 (bq (equal (match-string 1) "`")) ;; ` state flip-flop
993 (seen nil) ;; list of important positions
994 (nest 1)) ;; subshell nesting level
995 (while (and continue char (<= pos limit))
996 ;; unescaped " inside a $( ... ) construct.
997 ;; state machine time...
998 ;; \ => ignore next char;
999 ;; ` => increase or decrease nesting level based on bq flag
1000 ;; ) [where nesting > 0] => decrease nesting
1001 ;; ( [where nesting > 0] => increase nesting
1002 ;; ( [preceeded by $ ] => increase nesting
1003 ;; " [nesting <= 0 ] => terminate, we're done.
1004 ;; " [nesting > 0 ] => remember this, it's not a proper "
1005 (if (eq ?\\ last) nil
1006 (if (eq ?\` char) (setq nest (+ nest (if bq -1 1)) bq (not bq))
1007 (if (and (> nest 0) (eq ?\) char)) (setq nest (1- nest))
1008 (if (and (eq ?$ last) (eq ?\( char)) (setq nest (1+ nest))
1009 (if (and (> nest 0) (eq ?\( char)) (setq nest (1+ nest))
1010 (if (eq char ?\")
1011 (if (>= 0 nest) (setq continue nil)
1012 (setq seen (cons pos seen)) ) ))))))
1013 ;;(message "POS: %d [%d]" pos nest)
1014 (setq last char
1015 pos (1+ pos)
1016 char (char-after pos)) )
1017 (when seen
1018 ;;(message "SEEN: %S" seen)
1019 (setq data (list (current-buffer)))
1020 (mapc (lambda (P)
1021 (setq data (cons P (cons (1+ P) data)) ) ) seen)
1022 (store-match-data data))
1023 data) ))
1024
970 (defun sh-is-quoted-p (pos) 1025 (defun sh-is-quoted-p (pos)
971 (and (eq (char-before pos) ?\\) 1026 (and (eq (char-before pos) ?\\)
972 (not (sh-is-quoted-p (1- pos))))) 1027 (not (sh-is-quoted-p (1- pos)))))
973 1028
974 (defun sh-font-lock-paren (start) 1029 (defun sh-font-lock-paren (start)
995 (when (eq (char-before) ?|) 1050 (when (eq (char-before) ?|)
996 (backward-char 1) t))) 1051 (backward-char 1) t)))
997 (when (save-excursion (backward-char 2) (looking-at ";;\\|in")) 1052 (when (save-excursion (backward-char 2) (looking-at ";;\\|in"))
998 sh-st-punc))) 1053 sh-st-punc)))
999 1054
1055 (defun sh-apply-quoted-subshell ()
1056 "Apply the `sh-st-punc' syntax to all the matches in `match-data'.
1057 This is used to flag quote characters in subshell constructs inside strings
1058 \(which should therefore not be treated as normal quote characters\)"
1059 (let ((m (match-data)) a b)
1060 (while m
1061 (setq a (car m)
1062 b (cadr m)
1063 m (cddr m))
1064 (put-text-property a b 'syntax-table sh-st-punc))) sh-st-punc)
1065
1000 (defconst sh-font-lock-syntactic-keywords 1066 (defconst sh-font-lock-syntactic-keywords
1001 ;; A `#' begins a comment when it is unquoted and at the beginning of a 1067 ;; A `#' begins a comment when it is unquoted and at the beginning of a
1002 ;; word. In the shell, words are separated by metacharacters. 1068 ;; word. In the shell, words are separated by metacharacters.
1003 ;; The list of special chars is taken from the single-unix spec 1069 ;; The list of special chars is taken from the single-unix spec
1004 ;; of the shell command language (under `quoting') but with `$' removed. 1070 ;; of the shell command language (under `quoting') but with `$' removed.
1005 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol) 1071 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol)
1006 ;; In a '...' the backslash is not escaping. 1072 ;; In a '...' the backslash is not escaping.
1007 ("\\(\\\\\\)'" 1 ,sh-st-punc) 1073 ("\\(\\\\\\)'" 1 ,sh-st-punc)
1008 ;; Make sure $@ and @? are correctly recognized as sexps. 1074 ;; Make sure $@ and @? are correctly recognized as sexps.
1009 ("\\$\\([?@]\\)" 1 ,sh-st-symbol) 1075 ("\\$\\([?@]\\)" 1 ,sh-st-symbol)
1076 ;; highlight (possibly nested) subshells inside "" quoted regions correctly.
1077 (sh-quoted-subshell
1078 (1 (sh-apply-quoted-subshell) t t))
1010 ;; Find HEREDOC starters and add a corresponding rule for the ender. 1079 ;; Find HEREDOC starters and add a corresponding rule for the ender.
1011 (sh-font-lock-here-doc 1080 (sh-font-lock-here-doc
1012 (2 (sh-font-lock-open-heredoc 1081 (2 (sh-font-lock-open-heredoc
1013 (match-beginning 0) (match-string 1)) nil t) 1082 (match-beginning 0) (match-string 1)) nil t)
1014 (5 (sh-font-lock-close-heredoc 1083 (5 (sh-font-lock-close-heredoc
1017 nil t)) 1086 nil t))
1018 ;; Distinguish the special close-paren in `case'. 1087 ;; Distinguish the special close-paren in `case'.
1019 (")" 0 (sh-font-lock-paren (match-beginning 0))))) 1088 (")" 0 (sh-font-lock-paren (match-beginning 0)))))
1020 1089
1021 (defun sh-font-lock-syntactic-face-function (state) 1090 (defun sh-font-lock-syntactic-face-function (state)
1022 (if (nth 3 state) 1091 (let ((q (nth 3 state)))
1023 (if (characterp (nth 3 state)) 1092 (if q
1024 font-lock-string-face 1093 (if (characterp q)
1025 sh-heredoc-face) 1094 (if (eq q ?\`) 'sh-quoted-exec font-lock-string-face)
1026 font-lock-comment-face)) 1095 sh-heredoc-face)
1096 font-lock-comment-face)))
1027 1097
1028 (defgroup sh-indentation nil 1098 (defgroup sh-indentation nil
1029 "Variables controlling indentation in shell scripts. 1099 "Variables controlling indentation in shell scripts.
1030 1100
1031 Note: customizing these variables will not affect existing buffers if 1101 Note: customizing these variables will not affect existing buffers if
1388 (make-local-variable 'require-final-newline) 1458 (make-local-variable 'require-final-newline)
1389 (make-local-variable 'sh-header-marker) 1459 (make-local-variable 'sh-header-marker)
1390 (make-local-variable 'sh-shell-file) 1460 (make-local-variable 'sh-shell-file)
1391 (make-local-variable 'sh-shell) 1461 (make-local-variable 'sh-shell)
1392 (make-local-variable 'skeleton-pair-alist) 1462 (make-local-variable 'skeleton-pair-alist)
1393 (make-local-variable 'skeleton-pair-filter) 1463 (make-local-variable 'skeleton-pair-filter-function)
1394 (make-local-variable 'comint-dynamic-complete-functions) 1464 (make-local-variable 'comint-dynamic-complete-functions)
1395 (make-local-variable 'comint-prompt-regexp) 1465 (make-local-variable 'comint-prompt-regexp)
1396 (make-local-variable 'font-lock-defaults) 1466 (make-local-variable 'font-lock-defaults)
1397 (make-local-variable 'skeleton-filter) 1467 (make-local-variable 'skeleton-filter-function)
1398 (make-local-variable 'skeleton-newline-indent-rigidly) 1468 (make-local-variable 'skeleton-newline-indent-rigidly)
1399 (make-local-variable 'sh-shell-variables) 1469 (make-local-variable 'sh-shell-variables)
1400 (make-local-variable 'sh-shell-variables-initialized) 1470 (make-local-variable 'sh-shell-variables-initialized)
1401 (make-local-variable 'imenu-generic-expression) 1471 (make-local-variable 'imenu-generic-expression)
1402 (make-local-variable 'sh-indent-supported-here) 1472 (make-local-variable 'sh-indent-supported-here)
1420 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil 1490 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
1421 (font-lock-syntactic-keywords . sh-font-lock-syntactic-keywords) 1491 (font-lock-syntactic-keywords . sh-font-lock-syntactic-keywords)
1422 (font-lock-syntactic-face-function 1492 (font-lock-syntactic-face-function
1423 . sh-font-lock-syntactic-face-function)) 1493 . sh-font-lock-syntactic-face-function))
1424 skeleton-pair-alist '((?` _ ?`)) 1494 skeleton-pair-alist '((?` _ ?`))
1425 skeleton-pair-filter 'sh-quoted-p 1495 skeleton-pair-filter-function 'sh-quoted-p
1426 skeleton-further-elements '((< '(- (min sh-indentation 1496 skeleton-further-elements '((< '(- (min sh-indentation
1427 (current-column))))) 1497 (current-column)))))
1428 skeleton-filter 'sh-feature 1498 skeleton-filter-function 'sh-feature
1429 skeleton-newline-indent-rigidly t 1499 skeleton-newline-indent-rigidly t
1430 sh-indent-supported-here nil) 1500 sh-indent-supported-here nil)
1431 (set (make-local-variable 'parse-sexp-ignore-comments) t) 1501 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1432 ;; Parse or insert magic number for exec, and set all variables depending 1502 ;; Parse or insert magic number for exec, and set all variables depending
1433 ;; on the shell thus determined. 1503 ;; on the shell thus determined.