Commit 0ba2d4b6 authored by Dmitry Gutov's avatar Dmitry Gutov
Browse files

* lisp/progmodes/ruby-mode.el (ruby-indent-beg-re): Add pieces from

ruby-beginning-of-indent, simplify, allow all keywords to have
indentation before them.
(ruby-beginning-of-indent): Adjust for above.  Search until the
found point is not inside a string or comment.
(ruby-font-lock-keywords): Allow symbols to start with "@"
character, give them higher priority than variables.
(ruby-syntax-propertize-function)
(ruby-font-lock-syntactic-keywords): Remove the "not comments"
matchers.  Expression expansions are not comments when inside a
string, and there comment syntax status is irrelevant.
(ruby-match-expression-expansion): New function.  Check that
expression expansion is inside a string, and it's not escaped.
(ruby-font-lock-keywords): Use it.

* test/automated/ruby-mode-tests.el: New tests (Bug#11613).
parent 1d43a35f
...@@ -51,6 +51,23 @@ ...@@ -51,6 +51,23 @@
Let-bind `isearch-word' to the argument `delimited-flag'. Let-bind `isearch-word' to the argument `delimited-flag'.
(Bug#10885, bug#10887) (Bug#10885, bug#10887)
   
2012-09-07 Dmitry Gutov <dgutov@yandex.ru>
* progmodes/ruby-mode.el (ruby-indent-beg-re): Add pieces from
ruby-beginning-of-indent, simplify, allow all keywords to have
indentation before them.
(ruby-beginning-of-indent): Adjust for above. Search until the
found point is not inside a string or comment.
(ruby-font-lock-keywords): Allow symbols to start with "@"
character, give them higher priority than variables.
(ruby-syntax-propertize-function)
(ruby-font-lock-syntactic-keywords): Remove the "not comments"
matchers. Expression expansions are not comments when inside a
string, and there comment syntax status is irrelevant.
(ruby-match-expression-expansion): New function. Check that
expression expansion is inside a string, and it's not escaped.
(ruby-font-lock-keywords): Use it.
2012-09-05 Martin Rudalics <rudalics@gmx.at> 2012-09-05 Martin Rudalics <rudalics@gmx.at>
   
* help.el (temp-buffer-max-height): New default value. * help.el (temp-buffer-max-height): New default value.
......
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
"Regexp to match keywords that nest without blocks.") "Regexp to match keywords that nest without blocks.")
(defconst ruby-indent-beg-re (defconst ruby-indent-beg-re
(concat "\\(\\s *" (regexp-opt '("class" "module" "def") t) "\\)\\|" (concat "^\\s *" (regexp-opt '("class" "module" "def" "if" "unless" "case"
(regexp-opt '("if" "unless" "case" "while" "until" "for" "begin"))) "while" "until" "for" "begin")) "\\_>")
"Regexp to match where the indentation gets deeper.") "Regexp to match where the indentation gets deeper.")
(defconst ruby-modifier-beg-keywords (defconst ruby-modifier-beg-keywords
...@@ -848,19 +848,18 @@ move forward." ...@@ -848,19 +848,18 @@ move forward."
With ARG, move forward multiple defuns. Negative ARG means With ARG, move forward multiple defuns. Negative ARG means
move backward." move backward."
(interactive "p") (interactive "p")
(and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)") (and (re-search-forward ruby-indent-beg-re nil 'move (or arg 1))
nil 'move (or arg 1))
(beginning-of-line)) (beginning-of-line))
(forward-line 1)) (forward-line 1))
(defun ruby-beginning-of-indent () (defun ruby-beginning-of-indent ()
"TODO: document" "Backtrack to a line which can be used as a reference for
;; I don't understand this function. calculating indentation on the lines after it."
;; It seems like it should move to the line where indentation should deepen, (while (and (re-search-backward ruby-indent-beg-re nil 'move)
;; but ruby-indent-beg-re only accounts for whitespace before class, module and def, (if (ruby-in-ppss-context-p 'anything)
;; so this will only match other block beginners at the beginning of the line. t
(and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\_>") nil 'move) ;; We can stop, then.
(beginning-of-line))) (beginning-of-line)))))
(defun ruby-move-to-block (n) (defun ruby-move-to-block (n)
"Move to the beginning (N < 0) or the end (N > 0) of the current block "Move to the beginning (N < 0) or the end (N > 0) of the current block
...@@ -1171,8 +1170,6 @@ It will be properly highlighted even when the call omits parens.")) ...@@ -1171,8 +1170,6 @@ It will be properly highlighted even when the call omits parens."))
(ruby-syntax-enclosing-percent-literal end) (ruby-syntax-enclosing-percent-literal end)
(funcall (funcall
(syntax-propertize-rules (syntax-propertize-rules
;; #{ }, #$hoge, #@foo are not comments.
("\\(#\\)[{$@]" (1 "."))
;; $' $" $` .... are variables. ;; $' $" $` .... are variables.
;; ?' ?" ?` are ascii codes. ;; ?' ?" ?` are ascii codes.
("\\([?$]\\)[#\"'`]" ("\\([?$]\\)[#\"'`]"
...@@ -1304,8 +1301,7 @@ This should only be called after matching against `ruby-here-doc-end-re'." ...@@ -1304,8 +1301,7 @@ This should only be called after matching against `ruby-here-doc-end-re'."
(concat "-?\\([\"']\\|\\)" contents "\\1")))))) (concat "-?\\([\"']\\|\\)" contents "\\1"))))))
(defconst ruby-font-lock-syntactic-keywords (defconst ruby-font-lock-syntactic-keywords
`( ;; #{ }, #$hoge, #@foo are not comments `(
("\\(#\\)[{$@]" 1 (1 . nil))
;; the last $', $", $` in the respective string is not variable ;; the last $', $", $` in the respective string is not variable
;; the last ?', ?", ?` in the respective string is not ascii code ;; the last ?', ?", ?` in the respective string is not ascii code
("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)" ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
...@@ -1527,6 +1523,9 @@ See `font-lock-syntax-table'.") ...@@ -1527,6 +1523,9 @@ See `font-lock-syntax-table'.")
;; variables ;; variables
'("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>" '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
2 font-lock-variable-name-face) 2 font-lock-variable-name-face)
;; symbols
'("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
2 font-lock-reference-face)
;; variables ;; variables
'("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
1 font-lock-variable-name-face) 1 font-lock-variable-name-face)
...@@ -1535,12 +1534,9 @@ See `font-lock-syntax-table'.") ...@@ -1535,12 +1534,9 @@ See `font-lock-syntax-table'.")
;; constants ;; constants
'("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)" '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
2 font-lock-type-face) 2 font-lock-type-face)
;; symbols
'("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
2 font-lock-reference-face)
'("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face) '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face)
;; expression expansion ;; expression expansion
'("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)" '(ruby-match-expression-expansion
0 font-lock-variable-name-face t) 0 font-lock-variable-name-face t)
;; warn lower camel case ;; warn lower camel case
;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
...@@ -1548,6 +1544,10 @@ See `font-lock-syntax-table'.") ...@@ -1548,6 +1544,10 @@ See `font-lock-syntax-table'.")
) )
"Additional expressions to highlight in Ruby mode.") "Additional expressions to highlight in Ruby mode.")
(defun ruby-match-expression-expansion (limit)
(when (re-search-forward "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)" limit 'move)
(ruby-in-ppss-context-p 'string)))
;;;###autoload ;;;###autoload
(define-derived-mode ruby-mode prog-mode "Ruby" (define-derived-mode ruby-mode prog-mode "Ruby"
"Major mode for editing Ruby scripts. "Major mode for editing Ruby scripts.
......
2012-09-07 Dmitry Gutov <dgutov@yandex.ru>
* automated/ruby-mode-tests.el: New tests (Bug#11613).
2012-08-28 Chong Yidong <cyd@gnu.org> 2012-08-28 Chong Yidong <cyd@gnu.org>
* automated/files.el: Test every combination of values for * automated/files.el: Test every combination of values for
......
...@@ -57,6 +57,13 @@ VALUES-PLIST is a list with alternating index and value elements." ...@@ -57,6 +57,13 @@ VALUES-PLIST is a list with alternating index and value elements."
(cadr values-plist))) (cadr values-plist)))
(setq values-plist (cddr values-plist))))) (setq values-plist (cddr values-plist)))))
(defun ruby-assert-face (content pos face)
(with-temp-buffer
(insert content)
(ruby-mode)
(font-lock-fontify-buffer)
(should (eq face (get-text-property pos 'face)))))
(ert-deftest ruby-indent-after-symbol-made-from-string-interpolation () (ert-deftest ruby-indent-after-symbol-made-from-string-interpolation ()
"It can indent the line after symbol made using string interpolation." "It can indent the line after symbol made using string interpolation."
(ruby-should-indent "def foo(suffix)\n :\"bar#{suffix}\"\n" (ruby-should-indent "def foo(suffix)\n :\"bar#{suffix}\"\n"
...@@ -84,6 +91,11 @@ VALUES-PLIST is a list with alternating index and value elements." ...@@ -84,6 +91,11 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby-should-indent "foo = {\na: b" ruby-indent-level) (ruby-should-indent "foo = {\na: b" ruby-indent-level)
(ruby-should-indent "foo(\na" ruby-indent-level))) (ruby-should-indent "foo(\na" ruby-indent-level)))
(ert-deftest ruby-indent-after-keyword-in-a-string ()
(ruby-should-indent "a = \"abc\nif\"\n " 0)
(ruby-should-indent "a = %w[abc\n def]\n " 0)
(ruby-should-indent "a = \"abc\n def\"\n " 0))
(ert-deftest ruby-indent-simple () (ert-deftest ruby-indent-simple ()
(ruby-should-indent-buffer (ruby-should-indent-buffer
"if foo "if foo
...@@ -217,6 +229,19 @@ VALUES-PLIST is a list with alternating index and value elements." ...@@ -217,6 +229,19 @@ VALUES-PLIST is a list with alternating index and value elements."
(should (string= "foo {|b|\n}\n" (buffer-substring-no-properties (should (string= "foo {|b|\n}\n" (buffer-substring-no-properties
(point-min) (point-max)))))) (point-min) (point-max))))))
(ert-deftest ruby-recognize-symbols-starting-with-at-character ()
(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)
(ruby-assert-face "\"This is \\#{no interpolation} despite the #\""
15 'font-lock-string-face)
(ruby-assert-face "#@comment, not ruby code" 3 'font-lock-comment-face)
(ruby-assert-state "#@comment, not ruby code" 4 t)
(ruby-assert-face "# A comment cannot have #{an interpolation} in it"
30 'font-lock-comment-face))
(provide 'ruby-mode-tests) (provide 'ruby-mode-tests)
;;; ruby-mode-tests.el ends here ;;; ruby-mode-tests.el ends here
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment