* 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.
This commit is contained in:
parent
710f581278
commit
c62792e7df
4 changed files with 62 additions and 13 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Reference in a new issue