aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2012-11-14 16:17:21 +0400
committerDmitry Gutov2012-11-14 16:17:21 +0400
commitc62792e7dfa403db8c36cb92f32fb69258a199ef (patch)
treeb66f89060cd2f882a04b508896cbbbd424b08412
parent710f581278f6eaea5dbc5c0bcc7c206be9690746 (diff)
downloademacs-c62792e7dfa403db8c36cb92f32fb69258a199ef.tar.gz
emacs-c62792e7dfa403db8c36cb92f32fb69258a199ef.zip
* lisp/progmodes/ruby-mode.el
(ruby-syntax-propertize-function): After everything else, search for expansions in string literals, mark their insides as whitespace syntax and save match data for font-lock. (ruby-font-lock-keywords): Highlight just the 2nd group from expression expansion matches. (ruby-match-expression-expansion): Use the match data saved to the text property in ruby-syntax-propertize-function. * test/automated/ruby-mode-tests.el Change direct font-lock face references to var references. (ruby-interpolation-suppresses-syntax-inside): New test. (ruby-interpolation-inside-percent-literal-with-paren): New failing test.
-rw-r--r--lisp/ChangeLog9
-rw-r--r--lisp/progmodes/ruby-mode.el32
-rw-r--r--test/ChangeLog4
-rw-r--r--test/automated/ruby-mode-tests.el30
4 files changed, 62 insertions, 13 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 19623bd06b7..99bfabb8115 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -2,6 +2,15 @@
2 2
3 * progmodes/ruby-mode.el (ruby-expr-beg): Make heredoc detection 3 * progmodes/ruby-mode.el (ruby-expr-beg): Make heredoc detection
4 more strict. Add docstring. 4 more strict. Add docstring.
5 (ruby-expression-expansion-re): Extract from
6 `ruby-match-expression-expansion'.
7 (ruby-syntax-propertize-function): After everything else, search
8 for expansions in string literals, mark their insides as
9 whitespace syntax and save match data for font-lock.
10 (ruby-font-lock-keywords): Use the 2nd group from expression
11 expansion matches.
12 (ruby-match-expression-expansion): Use the match data saved to the
13 text property in ruby-syntax-propertize-function.
5 14
62012-11-14 Stefan Monnier <monnier@iro.umontreal.ca> 152012-11-14 Stefan Monnier <monnier@iro.umontreal.ca>
7 16
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 686bec89a95..9d78b20ba4c 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -105,7 +105,10 @@
105(eval-and-compile 105(eval-and-compile
106 (defconst ruby-here-doc-beg-re 106 (defconst ruby-here-doc-beg-re
107 "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" 107 "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
108 "Regexp to match the beginning of a heredoc.")) 108 "Regexp to match the beginning of a heredoc.")
109
110 (defconst ruby-expression-expansion-re
111 "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)"))
109 112
110(defun ruby-here-doc-end-match () 113(defun ruby-here-doc-end-match ()
111 "Return a regexp to find the end of a heredoc. 114 "Return a regexp to find the end of a heredoc.
@@ -1249,7 +1252,19 @@ It will be properly highlighted even when the call omits parens."))
1249 ;; Handle percent literals: %w(), %q{}, etc. 1252 ;; Handle percent literals: %w(), %q{}, etc.
1250 ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re) 1253 ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re)
1251 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) 1254 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end)))))
1252 (point) end)) 1255 (point) end)
1256 (remove-text-properties start end '(ruby-expansion-match-data))
1257 (goto-char start)
1258 ;; Find all expression expansions and
1259 ;; - set the syntax of all text inside to whitespace,
1260 ;; - save the match data to a text property, for font-locking later.
1261 (while (re-search-forward ruby-expression-expansion-re end 'move)
1262 (when (ruby-in-ppss-context-p 'string)
1263 (put-text-property (match-beginning 2) (match-end 2)
1264 'syntax-table (string-to-syntax "-"))
1265 (put-text-property (match-beginning 2) (1+ (match-beginning 2))
1266 'ruby-expansion-match-data
1267 (match-data)))))
1253 1268
1254 (defun ruby-syntax-propertize-heredoc (limit) 1269 (defun ruby-syntax-propertize-heredoc (limit)
1255 (let ((ppss (syntax-ppss)) 1270 (let ((ppss (syntax-ppss))
@@ -1582,7 +1597,7 @@ See `font-lock-syntax-table'.")
1582 '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face) 1597 '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face)
1583 ;; expression expansion 1598 ;; expression expansion
1584 '(ruby-match-expression-expansion 1599 '(ruby-match-expression-expansion
1585 0 font-lock-variable-name-face t) 1600 2 font-lock-variable-name-face t)
1586 ;; warn lower camel case 1601 ;; warn lower camel case
1587 ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" 1602 ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
1588 ; 0 font-lock-warning-face) 1603 ; 0 font-lock-warning-face)
@@ -1590,9 +1605,14 @@ See `font-lock-syntax-table'.")
1590 "Additional expressions to highlight in Ruby mode.") 1605 "Additional expressions to highlight in Ruby mode.")
1591 1606
1592(defun ruby-match-expression-expansion (limit) 1607(defun ruby-match-expression-expansion (limit)
1593 (when (re-search-forward "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)" limit 'move) 1608 (let ((prop 'ruby-expansion-match-data) pos value)
1594 (or (ruby-in-ppss-context-p 'string) 1609 (when (and (setq pos (next-single-char-property-change (point) prop
1595 (ruby-match-expression-expansion limit)))) 1610 nil limit))
1611 (> pos (point)))
1612 (goto-char pos)
1613 (or (and (setq value (get-text-property pos prop))
1614 (progn (set-match-data value) t))
1615 (ruby-match-expression-expansion limit)))))
1596 1616
1597;;;###autoload 1617;;;###autoload
1598(define-derived-mode ruby-mode prog-mode "Ruby" 1618(define-derived-mode ruby-mode prog-mode "Ruby"
diff --git a/test/ChangeLog b/test/ChangeLog
index 5a796408a3b..f11325d0318 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -3,6 +3,10 @@
3 * automated/ruby-mode-tests.el (ruby-indent-singleton-class): Pass. 3 * automated/ruby-mode-tests.el (ruby-indent-singleton-class): Pass.
4 (ruby-indent-inside-heredoc-after-operator) 4 (ruby-indent-inside-heredoc-after-operator)
5 (ruby-indent-inside-heredoc-after-space): New tests. 5 (ruby-indent-inside-heredoc-after-space): New tests.
6 Change direct font-lock face references to var references.
7 (ruby-interpolation-suppresses-syntax-inside): New test.
8 (ruby-interpolation-inside-percent-literal-with-paren): New
9 failing test.
6 10
72012-11-13 Dmitry Gutov <dgutov@yandex.ru> 112012-11-13 Dmitry Gutov <dgutov@yandex.ru>
8 12
diff --git a/test/automated/ruby-mode-tests.el b/test/automated/ruby-mode-tests.el
index 7d633be0f53..ad48413b030 100644
--- a/test/automated/ruby-mode-tests.el
+++ b/test/automated/ruby-mode-tests.el
@@ -80,7 +80,7 @@ VALUES-PLIST is a list with alternating index and value elements."
80 80
81(ert-deftest ruby-heredoc-font-lock () 81(ert-deftest ruby-heredoc-font-lock ()
82 (let ((s "foo <<eos.gsub('^ *', '')")) 82 (let ((s "foo <<eos.gsub('^ *', '')"))
83 (ruby-assert-face s 9 'font-lock-string-face) 83 (ruby-assert-face s 9 font-lock-string-face)
84 (ruby-assert-face s 10 nil))) 84 (ruby-assert-face s 10 nil)))
85 85
86(ert-deftest ruby-singleton-class-no-heredoc-font-lock () 86(ert-deftest ruby-singleton-class-no-heredoc-font-lock ()
@@ -262,19 +262,35 @@ VALUES-PLIST is a list with alternating index and value elements."
262 (should (string= "foo do |b|\n b + 1\nend" (buffer-string))))) 262 (should (string= "foo do |b|\n b + 1\nend" (buffer-string)))))
263 263
264(ert-deftest ruby-recognize-symbols-starting-with-at-character () 264(ert-deftest ruby-recognize-symbols-starting-with-at-character ()
265 (ruby-assert-face ":@abc" 3 'font-lock-constant-face)) 265 (ruby-assert-face ":@abc" 3 font-lock-constant-face))
266 266
267(ert-deftest ruby-hash-character-not-interpolation () 267(ert-deftest ruby-hash-character-not-interpolation ()
268 (ruby-assert-face "\"This is #{interpolation}\"" 15 268 (ruby-assert-face "\"This is #{interpolation}\"" 15
269 'font-lock-variable-name-face) 269 font-lock-variable-name-face)
270 (ruby-assert-face "\"This is \\#{no interpolation} despite the #\"" 270 (ruby-assert-face "\"This is \\#{no interpolation} despite the #\""
271 15 'font-lock-string-face) 271 15 font-lock-string-face)
272 (ruby-assert-face "\n#@comment, not ruby code" 5 'font-lock-comment-face) 272 (ruby-assert-face "\n#@comment, not ruby code" 5 font-lock-comment-face)
273 (ruby-assert-state "\n#@comment, not ruby code" 4 t) 273 (ruby-assert-state "\n#@comment, not ruby code" 4 t)
274 (ruby-assert-face "# A comment cannot have #{an interpolation} in it" 274 (ruby-assert-face "# A comment cannot have #{an interpolation} in it"
275 30 'font-lock-comment-face) 275 30 font-lock-comment-face)
276 (ruby-assert-face "# #{comment}\n \"#{interpolation}\"" 16 276 (ruby-assert-face "# #{comment}\n \"#{interpolation}\"" 16
277 'font-lock-variable-name-face)) 277 font-lock-variable-name-face))
278
279(ert-deftest ruby-interpolation-suppresses-syntax-inside ()
280 (let ((s "\"<ul><li>#{@files.join(\"</li><li>\")}</li></ul>\""))
281 (ruby-assert-state s 8 nil)
282 (ruby-assert-face s 9 font-lock-string-face)
283 (ruby-assert-face s 10 font-lock-variable-name-face)
284 (ruby-assert-face s 41 font-lock-string-face)))
285
286(ert-deftest ruby-interpolation-inside-percent-literal-with-paren ()
287 :expected-result :failed
288 (let ((s "%(^#{\")\"}^)"))
289 (ruby-assert-face s 3 font-lock-string-face)
290 (ruby-assert-face s 4 font-lock-variable-name-face)
291 (ruby-assert-face s 10 font-lock-string-face)
292 ;; It's confused by the closing paren in the middle.
293 (ruby-assert-state s 8 nil)))
278 294
279(ert-deftest ruby-add-log-current-method-examples () 295(ert-deftest ruby-add-log-current-method-examples ()
280 (let ((pairs '(("foo" . "#foo") 296 (let ((pairs '(("foo" . "#foo")