From: Dmitry Gutov Date: Fri, 7 Sep 2012 04:15:56 +0000 (+0400) Subject: * lisp/progmodes/ruby-mode.el (ruby-indent-beg-re): Add pieces from X-Git-Tag: emacs-24.2.90~391 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0ba2d4b6465b0b66d34e6ef47c151bd5920fbe54;p=emacs.git * 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). --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 37064b6680b..2f7dac68467 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -51,6 +51,23 @@ Let-bind `isearch-word' to the argument `delimited-flag'. (Bug#10885, bug#10887) +2012-09-07 Dmitry Gutov + + * 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 * help.el (temp-buffer-max-height): New default value. diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 3f93ffa84ba..bcebada5e86 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -64,8 +64,8 @@ "Regexp to match keywords that nest without blocks.") (defconst ruby-indent-beg-re - (concat "\\(\\s *" (regexp-opt '("class" "module" "def") t) "\\)\\|" - (regexp-opt '("if" "unless" "case" "while" "until" "for" "begin"))) + (concat "^\\s *" (regexp-opt '("class" "module" "def" "if" "unless" "case" + "while" "until" "for" "begin")) "\\_>") "Regexp to match where the indentation gets deeper.") (defconst ruby-modifier-beg-keywords @@ -848,19 +848,18 @@ move forward." With ARG, move forward multiple defuns. Negative ARG means move backward." (interactive "p") - (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)") - nil 'move (or arg 1)) + (and (re-search-forward ruby-indent-beg-re nil 'move (or arg 1)) (beginning-of-line)) (forward-line 1)) (defun ruby-beginning-of-indent () - "TODO: document" - ;; I don't understand this function. - ;; It seems like it should move to the line where indentation should deepen, - ;; but ruby-indent-beg-re only accounts for whitespace before class, module and def, - ;; so this will only match other block beginners at the beginning of the line. - (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\_>") nil 'move) - (beginning-of-line))) + "Backtrack to a line which can be used as a reference for +calculating indentation on the lines after it." + (while (and (re-search-backward ruby-indent-beg-re nil 'move) + (if (ruby-in-ppss-context-p 'anything) + t + ;; We can stop, then. + (beginning-of-line))))) (defun ruby-move-to-block (n) "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.")) (ruby-syntax-enclosing-percent-literal end) (funcall (syntax-propertize-rules - ;; #{ }, #$hoge, #@foo are not comments. - ("\\(#\\)[{$@]" (1 ".")) ;; $' $" $` .... are variables. ;; ?' ?" ?` are ascii codes. ("\\([?$]\\)[#\"'`]" @@ -1304,8 +1301,7 @@ This should only be called after matching against `ruby-here-doc-end-re'." (concat "-?\\([\"']\\|\\)" contents "\\1")))))) (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 ascii code ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)" @@ -1527,6 +1523,9 @@ See `font-lock-syntax-table'.") ;; variables '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>" 2 font-lock-variable-name-face) + ;; symbols + '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" + 2 font-lock-reference-face) ;; variables '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" 1 font-lock-variable-name-face) @@ -1535,12 +1534,9 @@ See `font-lock-syntax-table'.") ;; constants '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)" 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) ;; expression expansion - '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)" + '(ruby-match-expression-expansion 0 font-lock-variable-name-face t) ;; warn lower camel case ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" @@ -1548,6 +1544,10 @@ 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) + (ruby-in-ppss-context-p 'string))) + ;;;###autoload (define-derived-mode ruby-mode prog-mode "Ruby" "Major mode for editing Ruby scripts. diff --git a/test/ChangeLog b/test/ChangeLog index f523f6f59a9..541937ec4e7 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2012-09-07 Dmitry Gutov + + * automated/ruby-mode-tests.el: New tests (Bug#11613). + 2012-08-28 Chong Yidong * automated/files.el: Test every combination of values for diff --git a/test/automated/ruby-mode-tests.el b/test/automated/ruby-mode-tests.el index df51aa0d15a..1adc4acdfa0 100644 --- a/test/automated/ruby-mode-tests.el +++ b/test/automated/ruby-mode-tests.el @@ -57,6 +57,13 @@ VALUES-PLIST is a list with alternating index and value elements." (cadr 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 () "It can indent the line after symbol made using string interpolation." (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." (ruby-should-indent "foo = {\na: b" 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 () (ruby-should-indent-buffer "if foo @@ -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 (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) ;;; ruby-mode-tests.el ends here