aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/sh-script.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/sh-script.el')
-rw-r--r--lisp/progmodes/sh-script.el104
1 files changed, 52 insertions, 52 deletions
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 9041bd50259..d41a81e38a6 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -939,7 +939,6 @@ See `sh-feature'.")
939;; These are used for the syntax table stuff (derived from cperl-mode). 939;; These are used for the syntax table stuff (derived from cperl-mode).
940;; Note: parse-sexp-lookup-properties must be set to t for it to work. 940;; Note: parse-sexp-lookup-properties must be set to t for it to work.
941(defconst sh-st-punc (string-to-syntax ".")) 941(defconst sh-st-punc (string-to-syntax "."))
942(defconst sh-st-symbol (string-to-syntax "_"))
943(defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string 942(defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string
944 943
945(defconst sh-escaped-line-re 944(defconst sh-escaped-line-re
@@ -957,7 +956,7 @@ See `sh-feature'.")
957(defvar sh-here-doc-re sh-here-doc-open-re) 956(defvar sh-here-doc-re sh-here-doc-open-re)
958(make-variable-buffer-local 'sh-here-doc-re) 957(make-variable-buffer-local 'sh-here-doc-re)
959 958
960(defun sh-font-lock-close-heredoc (bol eof indented) 959(defun sh-font-lock-close-heredoc (bol eof indented eol)
961 "Determine the syntax of the \\n after an EOF. 960 "Determine the syntax of the \\n after an EOF.
962If non-nil INDENTED indicates that the EOF was indented." 961If non-nil INDENTED indicates that the EOF was indented."
963 (let* ((eof-re (if eof (regexp-quote eof) "")) 962 (let* ((eof-re (if eof (regexp-quote eof) ""))
@@ -971,6 +970,8 @@ If non-nil INDENTED indicates that the EOF was indented."
971 (ere (concat "^" (if indented "[ \t]*") eof-re "\n")) 970 (ere (concat "^" (if indented "[ \t]*") eof-re "\n"))
972 (start (save-excursion 971 (start (save-excursion
973 (goto-char bol) 972 (goto-char bol)
973 ;; FIXME: will incorrectly find a <<EOF embedded inside
974 ;; the heredoc.
974 (re-search-backward (concat sre "\\|" ere) nil t)))) 975 (re-search-backward (concat sre "\\|" ere) nil t))))
975 ;; If subgroup 1 matched, we found an open-heredoc, otherwise we first 976 ;; If subgroup 1 matched, we found an open-heredoc, otherwise we first
976 ;; found a close-heredoc which makes the current close-heredoc inoperant. 977 ;; found a close-heredoc which makes the current close-heredoc inoperant.
@@ -990,7 +991,7 @@ If non-nil INDENTED indicates that the EOF was indented."
990 (sh-in-comment-or-string (point))))) 991 (sh-in-comment-or-string (point)))))
991 ;; No <<EOF2 found after our <<. 992 ;; No <<EOF2 found after our <<.
992 (= (point) start))) 993 (= (point) start)))
993 sh-here-doc-syntax) 994 (put-text-property eol (1+ eol) 'syntax-table sh-here-doc-syntax))
994 ((not (or start (save-excursion (re-search-forward sre nil t)))) 995 ((not (or start (save-excursion (re-search-forward sre nil t))))
995 ;; There's no <<EOF either before or after us, 996 ;; There's no <<EOF either before or after us,
996 ;; so we should remove ourselves from font-lock's keywords. 997 ;; so we should remove ourselves from font-lock's keywords.
@@ -1000,7 +1001,7 @@ If non-nil INDENTED indicates that the EOF was indented."
1000 (regexp-opt sh-here-doc-markers t) "\\(\n\\)")) 1001 (regexp-opt sh-here-doc-markers t) "\\(\n\\)"))
1001 nil)))) 1002 nil))))
1002 1003
1003(defun sh-font-lock-open-heredoc (start string) 1004(defun sh-font-lock-open-heredoc (start string eol)
1004 "Determine the syntax of the \\n after a <<EOF. 1005 "Determine the syntax of the \\n after a <<EOF.
1005START is the position of <<. 1006START is the position of <<.
1006STRING is the actual word used as delimiter (e.g. \"EOF\"). 1007STRING is the actual word used as delimiter (e.g. \"EOF\").
@@ -1030,13 +1031,8 @@ Point is at the beginning of the next line."
1030 ;; Don't bother fixing it now, but place a multiline property so 1031 ;; Don't bother fixing it now, but place a multiline property so
1031 ;; that when jit-lock-context-* refontifies the rest of the 1032 ;; that when jit-lock-context-* refontifies the rest of the
1032 ;; buffer, it also refontifies the current line with it. 1033 ;; buffer, it also refontifies the current line with it.
1033 (put-text-property start (point) 'font-lock-multiline t))) 1034 (put-text-property start (point) 'syntax-multiline t)))
1034 sh-here-doc-syntax)) 1035 (put-text-property eol (1+ eol) 'syntax-table sh-here-doc-syntax)))
1035
1036(defun sh-font-lock-here-doc (limit)
1037 "Search for a heredoc marker."
1038 ;; This looks silly, but it's because `sh-here-doc-re' keeps changing.
1039 (re-search-forward sh-here-doc-re limit t))
1040 1036
1041(defun sh-font-lock-quoted-subshell (limit) 1037(defun sh-font-lock-quoted-subshell (limit)
1042 "Search for a subshell embedded in a string. 1038 "Search for a subshell embedded in a string.
@@ -1045,9 +1041,7 @@ subshells can nest."
1045 ;; FIXME: This can (and often does) match multiple lines, yet it makes no 1041 ;; FIXME: This can (and often does) match multiple lines, yet it makes no
1046 ;; effort to handle multiline cases correctly, so it ends up being 1042 ;; effort to handle multiline cases correctly, so it ends up being
1047 ;; rather flakey. 1043 ;; rather flakey.
1048 (when (and (re-search-forward "\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(?:\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)" limit t) 1044 (when (eq ?\" (nth 3 (syntax-ppss))) ; Check we matched an opening quote.
1049 ;; Make sure the " we matched is an opening quote.
1050 (eq ?\" (nth 3 (syntax-ppss))))
1051 ;; bingo we have a $( or a ` inside a "" 1045 ;; bingo we have a $( or a ` inside a ""
1052 (let ((char (char-after (point))) 1046 (let ((char (char-after (point)))
1053 ;; `state' can be: double-quote, backquote, code. 1047 ;; `state' can be: double-quote, backquote, code.
@@ -1082,8 +1076,7 @@ subshells can nest."
1082 (double-quote nil) 1076 (double-quote nil)
1083 (t (setq state (pop states))))) 1077 (t (setq state (pop states)))))
1084 (t (error "Internal error in sh-font-lock-quoted-subshell"))) 1078 (t (error "Internal error in sh-font-lock-quoted-subshell")))
1085 (forward-char 1))) 1079 (forward-char 1)))))
1086 t))
1087 1080
1088 1081
1089(defun sh-is-quoted-p (pos) 1082(defun sh-is-quoted-p (pos)
@@ -1122,7 +1115,7 @@ subshells can nest."
1122 (when (progn (backward-char 2) 1115 (when (progn (backward-char 2)
1123 (if (> start (line-end-position)) 1116 (if (> start (line-end-position))
1124 (put-text-property (point) (1+ start) 1117 (put-text-property (point) (1+ start)
1125 'font-lock-multiline t)) 1118 'syntax-multiline t))
1126 ;; FIXME: The `in' may just be a random argument to 1119 ;; FIXME: The `in' may just be a random argument to
1127 ;; a normal command rather than the real `in' keyword. 1120 ;; a normal command rather than the real `in' keyword.
1128 ;; I.e. we should look back to try and find the 1121 ;; I.e. we should look back to try and find the
@@ -1136,40 +1129,44 @@ subshells can nest."
1136 sh-st-punc 1129 sh-st-punc
1137 nil)) 1130 nil))
1138 1131
1139(defun sh-font-lock-flush-syntax-ppss-cache (limit) 1132(defun sh-syntax-propertize-function (start end)
1140 ;; This should probably be a standard function provided by font-lock.el 1133 (goto-char start)
1141 ;; (or syntax.el). 1134 (while (prog1
1142 (syntax-ppss-flush-cache (point)) 1135 (re-search-forward sh-here-doc-re end 'move)
1143 (goto-char limit) 1136 (save-excursion
1144 nil) 1137 (save-match-data
1145 1138 (funcall
1146(defconst sh-font-lock-syntactic-keywords 1139 (syntax-propertize-rules
1147 ;; A `#' begins a comment when it is unquoted and at the beginning of a 1140 ;; A `#' begins a comment when it is unquoted and at the
1148 ;; word. In the shell, words are separated by metacharacters. 1141 ;; beginning of a word. In the shell, words are separated by
1149 ;; The list of special chars is taken from the single-unix spec 1142 ;; metacharacters. The list of special chars is taken from
1150 ;; of the shell command language (under `quoting') but with `$' removed. 1143 ;; the single-unix spec of the shell command language (under
1151 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol) 1144 ;; `quoting') but with `$' removed.
1152 ;; In a '...' the backslash is not escaping. 1145 ("[^|&;<>()`\\\"' \t\n]\\(#+\\)" (1 "_"))
1153 ("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote))) 1146 ;; In a '...' the backslash is not escaping.
1154 ;; The previous rule uses syntax-ppss, but the subsequent rules may 1147 ("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote)))
1155 ;; change the syntax, so we have to tell syntax-ppss that the states it 1148 ;; Make sure $@ and $? are correctly recognized as sexps.
1156 ;; has just computed will need to be recomputed. 1149 ("\\$\\([?@]\\)" (1 "_"))
1157 (sh-font-lock-flush-syntax-ppss-cache) 1150 ;; Distinguish the special close-paren in `case'.
1158 ;; Make sure $@ and $? are correctly recognized as sexps. 1151 (")" (0 (sh-font-lock-paren (match-beginning 0))))
1159 ("\\$\\([?@]\\)" 1 ,sh-st-symbol) 1152 ;; Highlight (possibly nested) subshells inside "" quoted
1160 ;; Find HEREDOC starters and add a corresponding rule for the ender. 1153 ;; regions correctly.
1161 (sh-font-lock-here-doc 1154 ("\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(?:\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)"
1162 (2 (sh-font-lock-open-heredoc 1155 (1 (ignore
1163 (match-beginning 0) (match-string 1)) nil t) 1156 ;; Save excursion because we want to also apply other
1164 (5 (sh-font-lock-close-heredoc 1157 ;; syntax-propertize rules within the affected region.
1165 (match-beginning 0) (match-string 4) 1158 (save-excursion
1166 (and (match-beginning 3) (/= (match-beginning 3) (match-end 3)))) 1159 (sh-font-lock-quoted-subshell end))))))
1167 nil t)) 1160 (prog1 start (setq start (point))) (point)))))
1168 ;; Distinguish the special close-paren in `case'. 1161 (if (match-beginning 2)
1169 (")" 0 (sh-font-lock-paren (match-beginning 0))) 1162 ;; FIXME: actually, once we see an heredoc opener, we should just
1170 ;; highlight (possibly nested) subshells inside "" quoted regions correctly. 1163 ;; search for its ender without propertizing anything in it.
1171 ;; This should be at the very end because it uses syntax-ppss. 1164 (sh-font-lock-open-heredoc
1172 (sh-font-lock-quoted-subshell))) 1165 (match-beginning 0) (match-string 1) (match-beginning 2))
1166 (sh-font-lock-close-heredoc
1167 (match-beginning 0) (match-string 4)
1168 (and (match-beginning 3) (/= (match-beginning 3) (match-end 3)))
1169 (match-beginning 5)))))
1173 1170
1174(defun sh-font-lock-syntactic-face-function (state) 1171(defun sh-font-lock-syntactic-face-function (state)
1175 (let ((q (nth 3 state))) 1172 (let ((q (nth 3 state)))
@@ -1553,9 +1550,12 @@ with your script for an edit-interpret-debug cycle."
1553 sh-font-lock-keywords-1 sh-font-lock-keywords-2) 1550 sh-font-lock-keywords-1 sh-font-lock-keywords-2)
1554 nil nil 1551 nil nil
1555 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil 1552 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
1556 (font-lock-syntactic-keywords . sh-font-lock-syntactic-keywords)
1557 (font-lock-syntactic-face-function 1553 (font-lock-syntactic-face-function
1558 . sh-font-lock-syntactic-face-function))) 1554 . sh-font-lock-syntactic-face-function)))
1555 (set (make-local-variable 'syntax-propertize-function)
1556 #'sh-syntax-propertize-function)
1557 (add-hook 'syntax-propertize-extend-region-functions
1558 #'syntax-propertize-multiline 'append 'local)
1559 (set (make-local-variable 'skeleton-pair-alist) '((?` _ ?`))) 1559 (set (make-local-variable 'skeleton-pair-alist) '((?` _ ?`)))
1560 (set (make-local-variable 'skeleton-pair-filter-function) 'sh-quoted-p) 1560 (set (make-local-variable 'skeleton-pair-filter-function) 'sh-quoted-p)
1561 (set (make-local-variable 'skeleton-further-elements) 1561 (set (make-local-variable 'skeleton-further-elements)