aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/ruby-mode.el89
1 files changed, 75 insertions, 14 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 66aa256f947..5d79437c3c2 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -784,7 +784,7 @@ and `\\' when preceded by `?'."
784 (not (looking-at "[a-z_]")))) 784 (not (looking-at "[a-z_]"))))
785 (and (looking-at ruby-operator-re) 785 (and (looking-at ruby-operator-re)
786 (not (ruby-special-char-p)) 786 (not (ruby-special-char-p))
787 ;; operator at the end of line 787 ;; Operator at the end of line.
788 (let ((c (char-after (point)))) 788 (let ((c (char-after (point))))
789 (and 789 (and
790;; (or (null begin) 790;; (or (null begin)
@@ -794,8 +794,9 @@ and `\\' when preceded by `?'."
794;; (not (or (eolp) (looking-at "#") 794;; (not (or (eolp) (looking-at "#")
795;; (and (eq (car (nth 1 state)) ?{) 795;; (and (eq (car (nth 1 state)) ?{)
796;; (looking-at "|")))))) 796;; (looking-at "|"))))))
797 (or (not (eq ?/ c)) 797 ;; Not a regexp or general delimited literal.
798 (null (nth 0 (ruby-parse-region (or begin parse-start) (point))))) 798 (null (nth 0 (ruby-parse-region (or begin parse-start)
799 (point))))
799 (or (not (eq ?| (char-after (point)))) 800 (or (not (eq ?| (char-after (point))))
800 (save-excursion 801 (save-excursion
801 (or (eolp) (forward-char -1)) 802 (or (eolp) (forward-char -1))
@@ -1110,6 +1111,8 @@ See `add-log-current-defun-function'."
1110 mlist))))) 1111 mlist)))))
1111 1112
1112(declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit)) 1113(declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit))
1114(declare-function ruby-syntax-general-delimiters-goto-beg "ruby-mode" ())
1115(declare-function ruby-syntax-propertize-general-delimiters "ruby-mode" (limit))
1113 1116
1114(if (eval-when-compile (fboundp #'syntax-propertize-rules)) 1117(if (eval-when-compile (fboundp #'syntax-propertize-rules))
1115 ;; New code that works independently from font-lock. 1118 ;; New code that works independently from font-lock.
@@ -1118,26 +1121,48 @@ See `add-log-current-defun-function'."
1118 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." 1121 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
1119 (goto-char start) 1122 (goto-char start)
1120 (ruby-syntax-propertize-heredoc end) 1123 (ruby-syntax-propertize-heredoc end)
1124 (ruby-syntax-general-delimiters-goto-beg)
1121 (funcall 1125 (funcall
1122 (syntax-propertize-rules 1126 (syntax-propertize-rules
1123 ;; #{ }, #$hoge, #@foo are not comments 1127 ;; #{ }, #$hoge, #@foo are not comments.
1124 ("\\(#\\)[{$@]" (1 ".")) 1128 ("\\(#\\)[{$@]" (1 "."))
1125 ;; $' $" $` .... are variables 1129 ;; $' $" $` .... are variables.
1126 ;; ?' ?" ?` are ascii codes 1130 ;; ?' ?" ?` are ascii codes.
1127 ("\\([?$]\\)[#\"'`]" 1131 ("\\([?$]\\)[#\"'`]"
1128 (1 (unless (save-excursion 1132 (1 (unless (save-excursion
1129 ;; Not within a string. 1133 ;; Not within a string.
1130 (nth 3 (syntax-ppss (match-beginning 0)))) 1134 (nth 3 (syntax-ppss (match-beginning 0))))
1131 (string-to-syntax "\\")))) 1135 (string-to-syntax "\\"))))
1132 ;; regexps 1136 ;; Regexps: regexps are distinguished from division either because
1133 ("\\(^\\|[[=(,~?:;<>]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)" 1137 ;; of the keyword/symbol before them, or because of the code
1134 (4 "\"/") 1138 ;; following them.
1135 (6 "\"/")) 1139 ((concat
1140 ;; Special tokens that can't be followed by a division operator.
1141 "\\(?:\\(^\\|[[=(,~?:;<>]\\|\\(?:^\\|\\s \\)"
1142 (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
1143 "or" "&&" "||"
1144 "gsub" "gsub!" "sub" "sub!" "scan" "split" "split!"))
1145 "\\)\\s *\\)?"
1146 ;; The regular expression itself.
1147 "\\(/\\)[^/\n\\\\]*\\(?:\\\\.[^/\n\\\\]*\\)*\\(/\\)"
1148 ;; Special code that cannot follow a division operator.
1149 ;; FIXME: Just because the second slash of "/foo/ do bar" can't
1150 ;; be a division, doesn't mean it can't *start* a regexp, as in
1151 ;; "x = toto/foo; if /do bar/".
1152 "\\([imxo]*\\s *\\(?:,\\|\\_<do\\_>\\)\\)?")
1153 (2 (when (or (match-beginning 1) (match-beginning 4))
1154 (string-to-syntax "\"/")))
1155 (3 (if (or (match-beginning 1) (match-beginning 4))
1156 (string-to-syntax "\"/")
1157 (goto-char (match-end 2)))))
1136 ("^=en\\(d\\)\\_>" (1 "!")) 1158 ("^=en\\(d\\)\\_>" (1 "!"))
1137 ("^\\(=\\)begin\\_>" (1 "!")) 1159 ("^\\(=\\)begin\\_>" (1 "!"))
1138 ;; Handle here documents. 1160 ;; Handle here documents.
1139 ((concat ruby-here-doc-beg-re ".*\\(\n\\)") 1161 ((concat ruby-here-doc-beg-re ".*\\(\n\\)")
1140 (7 (prog1 "\"" (ruby-syntax-propertize-heredoc end))))) 1162 (7 (prog1 "\"" (ruby-syntax-propertize-heredoc end))))
1163 ;; Handle percent literals: %w(), %q{}, etc.
1164 ("\\(?:^\\|[[ \t\n<+(,=]\\)\\(%\\)[qQrswWx]?\\([[:punct:]]\\)"
1165 (1 (prog1 "|" (ruby-syntax-propertize-general-delimiters end)))))
1141 (point) end)) 1166 (point) end))
1142 1167
1143 (defun ruby-syntax-propertize-heredoc (limit) 1168 (defun ruby-syntax-propertize-heredoc (limit)
@@ -1163,6 +1188,41 @@ See `add-log-current-defun-function'."
1163 ;; Make extra sure we don't move back, lest we could fall into an 1188 ;; Make extra sure we don't move back, lest we could fall into an
1164 ;; inf-loop. 1189 ;; inf-loop.
1165 (if (< (point) start) (goto-char start)))))) 1190 (if (< (point) start) (goto-char start))))))
1191
1192 (defun ruby-syntax-general-delimiters-goto-beg ()
1193 (let ((state (syntax-ppss)))
1194 ;; Move to the start of the literal, in case it's multiline.
1195 ;; TODO: determine the literal type more reliably here?
1196 (when (eq t (nth 3 state))
1197 (goto-char (nth 8 state))
1198 (beginning-of-line))))
1199
1200 (defun ruby-syntax-propertize-general-delimiters (limit)
1201 (goto-char (match-beginning 2))
1202 (let* ((op (char-after))
1203 (ops (char-to-string op))
1204 (cl (or (cdr (aref (syntax-table) op))
1205 (cdr (assoc op '((?< . ?>))))))
1206 parse-sexp-lookup-properties)
1207 (ignore-errors
1208 (if cl
1209 (progn ; Paired delimiters.
1210 ;; Delimiter pairs of the same kind can be nested
1211 ;; inside the literal, as long as they are balanced.
1212 ;; Create syntax table that ignores other characters.
1213 (with-syntax-table (make-char-table 'syntax-table nil)
1214 (modify-syntax-entry op (concat "(" (char-to-string cl)))
1215 (modify-syntax-entry cl (concat ")" ops))
1216 (modify-syntax-entry ?\\ "\\")
1217 (save-restriction
1218 (narrow-to-region (point) limit)
1219 (forward-list)))) ; skip to the paired character
1220 ;; Single character delimiter.
1221 (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
1222 (regexp-quote ops)) limit nil))
1223 ;; If we reached here, the closing delimiter was found.
1224 (put-text-property (1- (point)) (point)
1225 'syntax-table (string-to-syntax "|")))))
1166 ) 1226 )
1167 1227
1168 ;; For Emacsen where syntax-propertize-rules is not (yet) available, 1228 ;; For Emacsen where syntax-propertize-rules is not (yet) available,
@@ -1207,6 +1267,10 @@ This should only be called after matching against `ruby-here-doc-end-re'."
1207 (4 (7 . ?/)) 1267 (4 (7 . ?/))
1208 (6 (7 . ?/))) 1268 (6 (7 . ?/)))
1209 ("^=en\\(d\\)\\_>" 1 "!") 1269 ("^=en\\(d\\)\\_>" 1 "!")
1270 ;; General delimited string.
1271 ("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
1272 (3 "\"")
1273 (5 "\""))
1210 ("^\\(=\\)begin\\_>" 1 (ruby-comment-beg-syntax)) 1274 ("^\\(=\\)begin\\_>" 1 (ruby-comment-beg-syntax))
1211 ;; Currently, the following case is highlighted incorrectly: 1275 ;; Currently, the following case is highlighted incorrectly:
1212 ;; 1276 ;;
@@ -1415,9 +1479,6 @@ See `font-lock-syntax-table'.")
1415 1 font-lock-variable-name-face) 1479 1 font-lock-variable-name-face)
1416 '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+" 1480 '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
1417 0 font-lock-variable-name-face) 1481 0 font-lock-variable-name-face)
1418 ;; general delimited string
1419 '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
1420 (2 font-lock-string-face))
1421 ;; constants 1482 ;; constants
1422 '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)" 1483 '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
1423 2 font-lock-type-face) 1484 2 font-lock-type-face)