diff options
author | Dmitry Gutov <dgutov@yandex.ru> | 2012-11-14 16:17:21 +0400 |
---|---|---|
committer | Dmitry Gutov <dgutov@yandex.ru> | 2012-11-14 16:17:21 +0400 |
commit | c62792e7dfa403db8c36cb92f32fb69258a199ef (patch) | |
tree | b66f89060cd2f882a04b508896cbbbd424b08412 | |
parent | 710f581278f6eaea5dbc5c0bcc7c206be9690746 (diff) | |
download | emacs-c62792e7dfa403db8c36cb92f32fb69258a199ef.tar.gz emacs-c62792e7dfa403db8c36cb92f32fb69258a199ef.tar.bz2 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/ChangeLog | 9 | ||||
-rw-r--r-- | lisp/progmodes/ruby-mode.el | 32 | ||||
-rw-r--r-- | test/ChangeLog | 4 | ||||
-rw-r--r-- | test/automated/ruby-mode-tests.el | 30 |
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 @@ * progmodes/ruby-mode.el (ruby-expr-beg): Make heredoc detection more strict. Add docstring. + (ruby-expression-expansion-re): Extract from + `ruby-match-expression-expansion'. + (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): Use 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. 2012-11-14 Stefan Monnier <monnier@iro.umontreal.ca> 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 @@ (eval-and-compile (defconst ruby-here-doc-beg-re "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" - "Regexp to match the beginning of a heredoc.")) + "Regexp to match the beginning of a heredoc.") + + (defconst ruby-expression-expansion-re + "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)")) (defun ruby-here-doc-end-match () "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.")) ;; Handle percent literals: %w(), %q{}, etc. ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re) (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) - (point) end)) + (point) end) + (remove-text-properties start end '(ruby-expansion-match-data)) + (goto-char start) + ;; Find all expression expansions and + ;; - set the syntax of all text inside to whitespace, + ;; - save the match data to a text property, for font-locking later. + (while (re-search-forward ruby-expression-expansion-re end 'move) + (when (ruby-in-ppss-context-p 'string) + (put-text-property (match-beginning 2) (match-end 2) + 'syntax-table (string-to-syntax "-")) + (put-text-property (match-beginning 2) (1+ (match-beginning 2)) + 'ruby-expansion-match-data + (match-data))))) (defun ruby-syntax-propertize-heredoc (limit) (let ((ppss (syntax-ppss)) @@ -1582,7 +1597,7 @@ See `font-lock-syntax-table'.") '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face) ;; expression expansion '(ruby-match-expression-expansion - 0 font-lock-variable-name-face t) + 2 font-lock-variable-name-face t) ;; warn lower camel case ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" ; 0 font-lock-warning-face) @@ -1590,9 +1605,14 @@ See `font-lock-syntax-table'.") "Additional expressions to highlight in Ruby mode.") (defun ruby-match-expression-expansion (limit) - (when (re-search-forward "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)" limit 'move) - (or (ruby-in-ppss-context-p 'string) - (ruby-match-expression-expansion limit)))) + (let ((prop 'ruby-expansion-match-data) pos value) + (when (and (setq pos (next-single-char-property-change (point) prop + nil limit)) + (> pos (point))) + (goto-char pos) + (or (and (setq value (get-text-property pos prop)) + (progn (set-match-data value) t)) + (ruby-match-expression-expansion limit))))) ;;;###autoload (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 @@ * automated/ruby-mode-tests.el (ruby-indent-singleton-class): Pass. (ruby-indent-inside-heredoc-after-operator) (ruby-indent-inside-heredoc-after-space): New tests. + 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. 2012-11-13 Dmitry Gutov <dgutov@yandex.ru> 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." (ert-deftest ruby-heredoc-font-lock () (let ((s "foo <<eos.gsub('^ *', '')")) - (ruby-assert-face s 9 'font-lock-string-face) + (ruby-assert-face s 9 font-lock-string-face) (ruby-assert-face s 10 nil))) (ert-deftest ruby-singleton-class-no-heredoc-font-lock () @@ -262,19 +262,35 @@ VALUES-PLIST is a list with alternating index and value elements." (should (string= "foo do |b|\n b + 1\nend" (buffer-string))))) (ert-deftest ruby-recognize-symbols-starting-with-at-character () - (ruby-assert-face ":@abc" 3 'font-lock-constant-face)) + (ruby-assert-face ":@abc" 3 font-lock-constant-face)) (ert-deftest ruby-hash-character-not-interpolation () (ruby-assert-face "\"This is #{interpolation}\"" 15 - 'font-lock-variable-name-face) + font-lock-variable-name-face) (ruby-assert-face "\"This is \\#{no interpolation} despite the #\"" - 15 'font-lock-string-face) - (ruby-assert-face "\n#@comment, not ruby code" 5 'font-lock-comment-face) + 15 font-lock-string-face) + (ruby-assert-face "\n#@comment, not ruby code" 5 font-lock-comment-face) (ruby-assert-state "\n#@comment, not ruby code" 4 t) (ruby-assert-face "# A comment cannot have #{an interpolation} in it" - 30 'font-lock-comment-face) + 30 font-lock-comment-face) (ruby-assert-face "# #{comment}\n \"#{interpolation}\"" 16 - 'font-lock-variable-name-face)) + font-lock-variable-name-face)) + +(ert-deftest ruby-interpolation-suppresses-syntax-inside () + (let ((s "\"<ul><li>#{@files.join(\"</li><li>\")}</li></ul>\"")) + (ruby-assert-state s 8 nil) + (ruby-assert-face s 9 font-lock-string-face) + (ruby-assert-face s 10 font-lock-variable-name-face) + (ruby-assert-face s 41 font-lock-string-face))) + +(ert-deftest ruby-interpolation-inside-percent-literal-with-paren () + :expected-result :failed + (let ((s "%(^#{\")\"}^)")) + (ruby-assert-face s 3 font-lock-string-face) + (ruby-assert-face s 4 font-lock-variable-name-face) + (ruby-assert-face s 10 font-lock-string-face) + ;; It's confused by the closing paren in the middle. + (ruby-assert-state s 8 nil))) (ert-deftest ruby-add-log-current-method-examples () (let ((pairs '(("foo" . "#foo") |