[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r112637: * lisp/progmodes/ruby-mode.e
From: |
Dmitry Gutov |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r112637: * lisp/progmodes/ruby-mode.el (ruby-expression-expansion-re): Allow to |
Date: |
Sun, 19 May 2013 10:01:23 +0400 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 112637
committer: Dmitry Gutov <address@hidden>
branch nick: trunk
timestamp: Sun 2013-05-19 10:01:23 +0400
message:
* lisp/progmodes/ruby-mode.el (ruby-expression-expansion-re): Allow to
start at point, so that expansion starting right after opening
slash in a regexp is recognized.
(ruby-syntax-before-regexp-re): New defvar, extracted from
ruby-syntax-propertize-function. Since the value of this regexp
is looked up at runtime now, we should be able to turn
`ruby-syntax-methods-before-regexp' into a defcustom later.
(ruby-syntax-propertize-function): Split regexp matching into two
parts, for opening and closing slashes. That allows us to skip
over string interpolations and support multiline regexps.
Don't call `ruby-syntax-propertize-expansions', instead use another rule
for them, which calls `ruby-syntax-propertize-expansion'.
(ruby-syntax-propertize-expansions): Move `remove-text-properties'
call to `ruby-syntax-propertize-function'.
(ruby-syntax-propertize-expansion): Extracted from
`ruby-syntax-propertize-expansions'. Handles one expansion.
(ruby-syntax-propertize-heredoc): Explicitly call
`ruby-syntax-propertize-expansions'.
(ruby-syntax-propertize-percent-literal): Leave point right after
the percent symbol, so that the expression expansion rule can
propertize the contents.
* test/automated/ruby-mode-tests.el (ruby-heredoc-highlights-interpolations)
(ruby-regexp-skips-over-interpolation)
(ruby-regexp-continues-till-end-when-unclosed)
(ruby-regexp-can-be-multiline)
(ruby-interpolation-inside-percent-literal): New tests.
* test/indent/ruby.rb: Add multiline regexp example.
modified:
lisp/ChangeLog
lisp/progmodes/ruby-mode.el
test/ChangeLog
test/automated/ruby-mode-tests.el
test/indent/ruby.rb
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog 2013-05-18 23:18:16 +0000
+++ b/lisp/ChangeLog 2013-05-19 06:01:23 +0000
@@ -1,3 +1,27 @@
+2013-05-19 Dmitry Gutov <address@hidden>
+
+ * progmodes/ruby-mode.el (ruby-expression-expansion-re): Allow to
+ start at point, so that expansion starting right after opening
+ slash in a regexp is recognized.
+ (ruby-syntax-before-regexp-re): New defvar, extracted from
+ ruby-syntax-propertize-function. Since the value of this regexp
+ is looked up at runtime now, we should be able to turn
+ `ruby-syntax-methods-before-regexp' into a defcustom later.
+ (ruby-syntax-propertize-function): Split regexp matching into two
+ parts, for opening and closing slashes. That allows us to skip
+ over string interpolations and support multiline regexps.
+ Don't call `ruby-syntax-propertize-expansions', instead use another rule
+ for them, which calls `ruby-syntax-propertize-expansion'.
+ (ruby-syntax-propertize-expansions): Move `remove-text-properties'
+ call to `ruby-syntax-propertize-function'.
+ (ruby-syntax-propertize-expansion): Extracted from
+ `ruby-syntax-propertize-expansions'. Handles one expansion.
+ (ruby-syntax-propertize-heredoc): Explicitly call
+ `ruby-syntax-propertize-expansions'.
+ (ruby-syntax-propertize-percent-literal): Leave point right after
+ the percent symbol, so that the expression expansion rule can
+ propertize the contents.
+
2013-05-18 Juri Linkov <address@hidden>
* man.el (Man-default-man-entry): Remove `-' from the end
=== modified file 'lisp/progmodes/ruby-mode.el'
--- a/lisp/progmodes/ruby-mode.el 2013-05-08 20:25:57 +0000
+++ b/lisp/progmodes/ruby-mode.el 2013-05-19 06:01:23 +0000
@@ -113,7 +113,7 @@
"Regexp to match the beginning of a heredoc.")
(defconst ruby-expression-expansion-re
-
"[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)"))
+
"\\(?:[^\\]\\|\\=\\)\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)"))
(defun ruby-here-doc-end-match ()
"Return a regexp to find the end of a heredoc.
@@ -1360,11 +1360,26 @@
'("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match"
"assert_match" "Given" "Then" "When")
"Methods that can take regexp as the first argument.
-It will be properly highlighted even when the call omits parens."))
+It will be properly highlighted even when the call omits parens.")
+
+ (defvar ruby-syntax-before-regexp-re
+ (concat
+ ;; Special tokens that can't be followed by a division operator.
+ "\\(^\\|[[=(,~?:;<>]"
+ ;; Control flow keywords and operators following bol or whitespace.
+ "\\|\\(?:^\\|\\s \\)"
+ (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
+ "or" "not" "&&" "||"))
+ ;; Method name from the list.
+ "\\|\\_<"
+ (regexp-opt ruby-syntax-methods-before-regexp)
+ "\\)\\s *")
+ "Regexp to match text that can be followed by a regular
expression."))
(defun ruby-syntax-propertize-function (start end)
"Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
(goto-char start)
+ (remove-text-properties start end '(ruby-expansion-match-data))
(ruby-syntax-propertize-heredoc end)
(ruby-syntax-enclosing-percent-literal end)
(funcall
@@ -1376,25 +1391,26 @@
;; Not within a string.
(nth 3 (syntax-ppss (match-beginning 0))))
(string-to-syntax "\\"))))
- ;; Regexps: regexps are distinguished from division because
- ;; of the keyword, symbol, or method name before them.
- ((concat
- ;; Special tokens that can't be followed by a division operator.
- "\\(^\\|[[=(,~?:;<>]"
- ;; Control flow keywords and operators following bol or whitespace.
- "\\|\\(?:^\\|\\s \\)"
- (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
- "or" "not" "&&" "||"))
- ;; Method name from the list.
- "\\|\\_<"
- (regexp-opt ruby-syntax-methods-before-regexp)
- "\\)\\s *"
- ;; The regular expression itself.
- "\\(/\\)[^/\n\\\\]*\\(?:\\\\.[^/\n\\\\]*\\)*\\(/\\)")
- (3 (unless (nth 3 (syntax-ppss (match-beginning 2)))
- (put-text-property (match-beginning 2) (match-end 2)
- 'syntax-table (string-to-syntax "\"/"))
- (string-to-syntax "\"/"))))
+ ;; Regular expressions. Start with matching unescaped slash.
+ ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)"
+ (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1)))))
+ (when (or
+ ;; Beginning of a regexp.
+ (and (null (nth 8 state))
+ (save-excursion
+ (forward-char -1)
+ (looking-back ruby-syntax-before-regexp-re
+ (point-at-bol))))
+ ;; End of regexp. We don't match the whole
+ ;; regexp at once because it can have
+ ;; string interpolation inside, or span
+ ;; several lines.
+ (eq ?/ (nth 3 state)))
+ (string-to-syntax "\"/")))))
+ ;; Expression expansions in strings. We're handling them
+ ;; here, so that the regexp rule never matches inside them.
+ (ruby-expression-expansion-re
+ (0 (ignore (ruby-syntax-propertize-expansion))))
("^=en\\(d\\)\\_>" (1 "!"))
("^\\(=\\)begin\\_>" (1 "!"))
;; Handle here documents.
@@ -1406,8 +1422,7 @@
;; Handle percent literals: %w(), %q{}, etc.
((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re)
(1 (prog1 "|" (ruby-syntax-propertize-percent-literal end)))))
- (point) end)
- (ruby-syntax-propertize-expansions start end))
+ (point) end))
(defun ruby-syntax-propertize-heredoc (limit)
(let ((ppss (syntax-ppss))
@@ -1432,7 +1447,9 @@
'syntax-table (string-to-syntax "\""))))
;; Make extra sure we don't move back, lest we could fall into an
;; inf-loop.
- (if (< (point) start) (goto-char start))))))
+ (if (< (point) start)
+ (goto-char start)
+ (ruby-syntax-propertize-expansions start (point)))))))
(defun ruby-syntax-enclosing-percent-literal (limit)
(let ((state (syntax-ppss))
@@ -1453,44 +1470,47 @@
(cl (or (cdr (aref (syntax-table) op))
(cdr (assoc op '((?< . ?>))))))
parse-sexp-lookup-properties)
- (condition-case nil
- (progn
- (if cl ; Paired delimiters.
- ;; Delimiter pairs of the same kind can be nested
- ;; inside the literal, as long as they are balanced.
- ;; Create syntax table that ignores other characters.
- (with-syntax-table (make-char-table 'syntax-table nil)
- (modify-syntax-entry op (concat "(" (char-to-string
cl)))
- (modify-syntax-entry cl (concat ")" ops))
- (modify-syntax-entry ?\\ "\\")
- (save-restriction
- (narrow-to-region (point) limit)
- (forward-list))) ; skip to the paired character
- ;; Single character delimiter.
- (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
- (regexp-quote ops)) limit nil))
- ;; Found the closing delimiter.
- (put-text-property (1- (point)) (point) 'syntax-table
- (string-to-syntax "|")))
- ;; Unclosed literal, leave the following text unpropertized.
- ((scan-error search-failed) (goto-char limit))))))
+ (save-excursion
+ (condition-case nil
+ (progn
+ (if cl ; Paired delimiters.
+ ;; Delimiter pairs of the same kind can be nested
+ ;; inside the literal, as long as they are balanced.
+ ;; Create syntax table that ignores other characters.
+ (with-syntax-table (make-char-table 'syntax-table nil)
+ (modify-syntax-entry op (concat "(" (char-to-string
cl)))
+ (modify-syntax-entry cl (concat ")" ops))
+ (modify-syntax-entry ?\\ "\\")
+ (save-restriction
+ (narrow-to-region (point) limit)
+ (forward-list))) ; skip to the paired character
+ ;; Single character delimiter.
+ (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
+ (regexp-quote ops)) limit
nil))
+ ;; Found the closing delimiter.
+ (put-text-property (1- (point)) (point) 'syntax-table
+ (string-to-syntax "|")))
+ ;; Unclosed literal, do nothing.
+ ((scan-error search-failed)))))))
+
+ (defun ruby-syntax-propertize-expansion ()
+ ;; Save the match data to a text property, for font-locking later.
+ ;; Set the syntax of all double quotes and backticks to punctuation.
+ (let ((beg (match-beginning 2))
+ (end (match-end 2)))
+ (when (and beg (save-excursion (nth 3 (syntax-ppss beg))))
+ (put-text-property beg (1+ beg) 'ruby-expansion-match-data
+ (match-data))
+ (goto-char beg)
+ (while (re-search-forward "[\"`]" end 'move)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'syntax-table (string-to-syntax "."))))))
(defun ruby-syntax-propertize-expansions (start end)
- (remove-text-properties start end '(ruby-expansion-match-data))
- (goto-char start)
- ;; Find all expression expansions and
- ;; - save the match data to a text property, for font-locking later,
- ;; - set the syntax of all double quotes and backticks to punctuation.
- (while (re-search-forward ruby-expression-expansion-re end 'move)
- (let ((beg (match-beginning 2))
- (end (match-end 2)))
- (when (and beg (save-excursion (nth 3 (syntax-ppss beg))))
- (put-text-property beg (1+ beg) 'ruby-expansion-match-data
- (match-data))
- (goto-char beg)
- (while (re-search-forward "[\"`]" end 'move)
- (put-text-property (match-beginning 0) (match-end 0)
- 'syntax-table (string-to-syntax ".")))))))
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward ruby-expression-expansion-re end 'move)
+ (ruby-syntax-propertize-expansion))))
)
;; For Emacsen where syntax-propertize-rules is not (yet) available,
=== modified file 'test/ChangeLog'
--- a/test/ChangeLog 2013-05-08 20:25:57 +0000
+++ b/test/ChangeLog 2013-05-19 06:01:23 +0000
@@ -1,3 +1,13 @@
+2013-05-19 Dmitry Gutov <address@hidden>
+
+ * indent/ruby.rb: Add multiline regexp example.
+
+ * automated/ruby-mode-tests.el (ruby-heredoc-highlights-interpolations)
+ (ruby-regexp-skips-over-interpolation)
+ (ruby-regexp-continues-till-end-when-unclosed)
+ (ruby-regexp-can-be-multiline)
+ (ruby-interpolation-inside-percent-literal): New tests.
+
2013-05-08 Stefan Monnier <address@hidden>
* indent/ruby.rb: Fix indentation after =; add more cases.
=== modified file 'test/automated/ruby-mode-tests.el'
--- a/test/automated/ruby-mode-tests.el 2013-04-15 23:07:14 +0000
+++ b/test/automated/ruby-mode-tests.el 2013-05-19 06:01:23 +0000
@@ -84,6 +84,9 @@
(ert-deftest ruby-singleton-class-no-heredoc-font-lock ()
(ruby-assert-face "class<<a" 8 nil))
+(ert-deftest ruby-heredoc-highlights-interpolations ()
+ (ruby-assert-face "s = <<EOS\n #{foo}\nEOS" 15
font-lock-variable-name-face))
+
(ert-deftest ruby-deep-indent ()
(let ((ruby-deep-arglist nil)
(ruby-deep-indent-paren '(?\( ?\{ ?\[ ?\] t)))
@@ -109,6 +112,15 @@
(ert-deftest ruby-regexp-starts-after-string ()
(ruby-assert-state "'(/', /\d+/" 3 ?/ 8))
+(ert-deftest ruby-regexp-skips-over-interpolation ()
+ (ruby-assert-state "/#{foobs.join('/')}/" 3 nil))
+
+(ert-deftest ruby-regexp-continues-till-end-when-unclosed ()
+ (ruby-assert-state "/bars" 3 ?/))
+
+(ert-deftest ruby-regexp-can-be-multiline ()
+ (ruby-assert-state "/bars\ntees # toots \nfoos/" 3 nil))
+
(ert-deftest ruby-indent-simple ()
(ruby-should-indent-buffer
"if foo
@@ -325,6 +337,13 @@
(search-forward "tee")
(should (string= (thing-at-point 'symbol) "tee")))))
+(ert-deftest ruby-interpolation-inside-percent-literal ()
+ (let ((s "%( #{boo} )"))
+ (ruby-assert-face s 1 font-lock-string-face)
+ (ruby-assert-face s 4 font-lock-variable-name-face)
+ (ruby-assert-face s 10 font-lock-string-face)
+ (ruby-assert-state s 8 nil)))
+
(ert-deftest ruby-interpolation-inside-percent-literal-with-paren ()
:expected-result :failed
(let ((s "%(^#{\")\"}^)"))
=== modified file 'test/indent/ruby.rb'
--- a/test/indent/ruby.rb 2013-05-08 20:25:57 +0000
+++ b/test/indent/ruby.rb 2013-05-19 06:01:23 +0000
@@ -21,6 +21,11 @@
# Highlight the regexp after "if".
x = toto / foo if /do bar/ =~ "dobar"
+# Multiline regexp.
+/bars
+ tees # toots
+ nfoos/
+
def test1(arg)
puts "hello"
end
@@ -47,6 +52,8 @@
case a
when "a"
6
+ # Support for this syntax was removed in Ruby 1.9, so we
+ # probably don't need to handle it either.
# when "b" :
# 7
# when "c" : 2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] /srv/bzr/emacs/trunk r112637: * lisp/progmodes/ruby-mode.el (ruby-expression-expansion-re): Allow to,
Dmitry Gutov <=