comparison lisp/progmodes/sh-script.el @ 78197:f942a5cc0de4

(sh-font-lock-backslash-quote, sh-font-lock-flush-syntax-ppss-cache): New funs. (sh-font-lock-syntactic-keywords): Use them to distinguish the different possible cases for \'. (sh-font-lock-paren): Mark the relevant text with font-lock-multiline.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 23 Jul 2007 13:07:29 +0000
parents dac1de8103f2
children c1ec1c8a8d2e
comparison
equal deleted inserted replaced
78196:2e0600da7d6a 78197:f942a5cc0de4
169 ;; To try and address points 2 3 and 5 I used a feature that cperl mode 169 ;; To try and address points 2 3 and 5 I used a feature that cperl mode
170 ;; uses, that of a text's syntax property. This, however, has 2 170 ;; uses, that of a text's syntax property. This, however, has 2
171 ;; disadvantages: 171 ;; disadvantages:
172 ;; 1. We need to scan the buffer to find which ")" symbols belong to a 172 ;; 1. We need to scan the buffer to find which ")" symbols belong to a
173 ;; case alternative, to find any here documents, and handle "$#". 173 ;; case alternative, to find any here documents, and handle "$#".
174 ;; 2. Setting the text property makes the buffer modified. If the
175 ;; buffer is read-only buffer we have to cheat and bypass the read-only
176 ;; status. This is for cases where the buffer started read-only buffer
177 ;; but the user issued `toggle-read-only'.
178 ;; 174 ;;
179 ;; Bugs 175 ;; Bugs
180 ;; ---- 176 ;; ----
181 ;; - Indenting many lines is slow. It currently does each line 177 ;; - Indenting many lines is slow. It currently does each line
182 ;; independently, rather than saving state information. 178 ;; independently, rather than saving state information.
183 ;; 179 ;;
184 ;; - `sh-learn-buffer-indent' is extremely slow. 180 ;; - `sh-learn-buffer-indent' is extremely slow.
181 ;;
182 ;; - "case $x in y) echo ;; esac)" the last ) is mis-identified as being
183 ;; part of a case-pattern. You need to add a semi-colon after "esac" to
184 ;; coerce sh-script into doing the right thing.
185 ;;
186 ;; - "echo $z in ps | head)" the last ) is mis-identified as being part of
187 ;; a case-pattern. You need to put the "in" between quotes to coerce
188 ;; sh-script into doing the right thing.
189 ;;
190 ;; - A line starting with "}>foo" is not indented like "} >foo".
185 ;; 191 ;;
186 ;; Richard Sharman <rsharman@pobox.com> June 1999. 192 ;; Richard Sharman <rsharman@pobox.com> June 1999.
187 193
188 ;;; Code: 194 ;;; Code:
189 195
882 (defconst sh-st-punc (string-to-syntax ".")) 888 (defconst sh-st-punc (string-to-syntax "."))
883 (defconst sh-st-symbol (string-to-syntax "_")) 889 (defconst sh-st-symbol (string-to-syntax "_"))
884 (defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string 890 (defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string
885 891
886 (defconst sh-escaped-line-re 892 (defconst sh-escaped-line-re
887 ;; Should match until the real end-of-continued line, but if that is not 893 ;; Should match until the real end-of-continued-line, but if that is not
888 ;; possible (because we bump into EOB or the search bound), then we should 894 ;; possible (because we bump into EOB or the search bound), then we should
889 ;; match until the search bound. 895 ;; match until the search bound.
890 "\\(?:\\(?:.*[^\\\n]\\)?\\(?:\\\\\\\\\\)*\\\\\n\\)*.*") 896 "\\(?:\\(?:.*[^\\\n]\\)?\\(?:\\\\\\\\\\)*\\\\\n\\)*.*")
891 897
892 (defconst sh-here-doc-open-re 898 (defconst sh-here-doc-open-re
1057 ;; Maybe we've bumped into an escaped newline. 1063 ;; Maybe we've bumped into an escaped newline.
1058 (sh-is-quoted-p (point))) 1064 (sh-is-quoted-p (point)))
1059 (backward-char 1)) 1065 (backward-char 1))
1060 (when (eq (char-before) ?|) 1066 (when (eq (char-before) ?|)
1061 (backward-char 1) t))) 1067 (backward-char 1) t)))
1062 (when (save-excursion (backward-char 2) (looking-at ";;\\|in")) 1068 ;; FIXME: ";; esac )" is a case that looks like a case-pattern but it's
1069 ;; really just a close paren after a case statement. I.e. if we skipped
1070 ;; over `esac' just now, we're not looking at a case-pattern.
1071 (when (progn (backward-char 2)
1072 (if (> start (line-end-position))
1073 (put-text-property (point) (1+ start)
1074 'font-lock-multiline t))
1075 ;; FIXME: The `in' may just be a random argument to
1076 ;; a normal command rather than the real `in' keyword.
1077 ;; I.e. we should look back to try and find the
1078 ;; corresponding `case'.
1079 (looking-at ";;\\|in"))
1063 sh-st-punc))) 1080 sh-st-punc)))
1081
1082 (defun sh-font-lock-backslash-quote ()
1083 (if (eq (save-excursion (nth 3 (syntax-ppss (match-beginning 0)))) ?\')
1084 ;; In a '...' the backslash is not escaping.
1085 sh-st-punc
1086 nil))
1087
1088 (defun sh-font-lock-flush-syntax-ppss-cache (limit)
1089 ;; This should probably be a standard function provided by font-lock.el
1090 ;; (or syntax.el).
1091 (syntax-ppss-flush-cache (point))
1092 (goto-char limit)
1093 nil)
1064 1094
1065 (defun sh-apply-quoted-subshell () 1095 (defun sh-apply-quoted-subshell ()
1066 "Apply the `sh-st-punc' syntax to all the matches in `match-data'. 1096 "Apply the `sh-st-punc' syntax to all the matches in `match-data'.
1067 This is used to flag quote characters in subshell constructs inside strings 1097 This is used to flag quote characters in subshell constructs inside strings
1068 \(which should therefore not be treated as normal quote characters\)" 1098 \(which should therefore not be treated as normal quote characters\)"
1078 ;; word. In the shell, words are separated by metacharacters. 1108 ;; word. In the shell, words are separated by metacharacters.
1079 ;; The list of special chars is taken from the single-unix spec 1109 ;; The list of special chars is taken from the single-unix spec
1080 ;; of the shell command language (under `quoting') but with `$' removed. 1110 ;; of the shell command language (under `quoting') but with `$' removed.
1081 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol) 1111 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol)
1082 ;; In a '...' the backslash is not escaping. 1112 ;; In a '...' the backslash is not escaping.
1083 ("\\(\\\\\\)'" 1 ,sh-st-punc) 1113 ("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote)))
1114 ;; The previous rule uses syntax-ppss, but the subsequent rules may
1115 ;; change the syntax, so we have to tell syntax-ppss that the states it
1116 ;; has just computed will need to be recomputed.
1117 (sh-font-lock-flush-syntax-ppss-cache)
1084 ;; Make sure $@ and @? are correctly recognized as sexps. 1118 ;; Make sure $@ and @? are correctly recognized as sexps.
1085 ("\\$\\([?@]\\)" 1 ,sh-st-symbol) 1119 ("\\$\\([?@]\\)" 1 ,sh-st-symbol)
1086 ;; Find HEREDOC starters and add a corresponding rule for the ender. 1120 ;; Find HEREDOC starters and add a corresponding rule for the ender.
1087 (sh-font-lock-here-doc 1121 (sh-font-lock-here-doc
1088 (2 (sh-font-lock-open-heredoc 1122 (2 (sh-font-lock-open-heredoc