ruby-mode: Support endless methods (bug#54702)
* lisp/progmodes/ruby-mode.el (ruby-endless-method-head-re): New constant. (ruby-smie-grammar): New token. (ruby-smie--forward-token, ruby-smie--backward-token): Recognize it. (ruby-smie-rules): Indentation support. (ruby-add-log-current-method): Support here too. * test/lisp/progmodes/ruby-mode-tests.el (ruby-add-log-current-method-after-endless-method): New test. * test/lisp/progmodes/ruby-mode-resources/ruby.rb: New examples.
This commit is contained in:
parent
91dd893e34
commit
6f88de109c
4 changed files with 74 additions and 2 deletions
3
etc/NEWS
3
etc/NEWS
|
@ -2758,6 +2758,9 @@ project-dedicated or global) is specified by the new
|
|||
---
|
||||
*** New user option 'ruby-toggle-block-space-before-parameters'.
|
||||
|
||||
---
|
||||
*** Support for endless methods.
|
||||
|
||||
** Eshell
|
||||
|
||||
+++
|
||||
|
|
|
@ -134,6 +134,12 @@ This should only be called after matching against `ruby-here-doc-beg-re'."
|
|||
(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]")
|
||||
"Regexp to match symbols.")
|
||||
|
||||
(defconst ruby-endless-method-head-re
|
||||
(format " *\\(self\\.\\)?%s+[?!]? *\\(([^()]*)\\)? +=" ruby-symbol-re)
|
||||
"Regexp to match the beginning of an endless method definition.
|
||||
|
||||
It should match the part after \"def\" and until \"=\".")
|
||||
|
||||
(defvar ruby-use-smie t)
|
||||
(make-obsolete-variable 'ruby-use-smie nil "28.1")
|
||||
|
||||
|
@ -351,7 +357,8 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(exp (exp1) (exp "," exp) (exp "=" exp)
|
||||
(id " @ " exp))
|
||||
(exp1 (exp2) (exp2 "?" exp1 ":" exp1))
|
||||
(exp2 (exp3) (exp3 "." exp3))
|
||||
(exp2 (exp3) (exp3 "." exp3)
|
||||
(exp3 "def=" exp3))
|
||||
(exp3 ("def" insts "end")
|
||||
("begin" insts-rescue-insts "end")
|
||||
("do" insts "end")
|
||||
|
@ -528,6 +535,9 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(ruby-smie--forward-token)) ;Fully redundant.
|
||||
(t ";")))
|
||||
((equal tok "&.") ".")
|
||||
((and (equal tok "def")
|
||||
(looking-at ruby-endless-method-head-re))
|
||||
"def=")
|
||||
(t tok)))))))))
|
||||
|
||||
(defun ruby-smie--backward-token ()
|
||||
|
@ -575,6 +585,9 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(ruby-smie--backward-token)) ;Fully redundant.
|
||||
(t ";")))
|
||||
((equal tok "&.") ".")
|
||||
((and (equal tok "def")
|
||||
(looking-at (concat "def" ruby-endless-method-head-re)))
|
||||
"def=")
|
||||
(t tok)))))))
|
||||
|
||||
(defun ruby-smie--indent-to-stmt ()
|
||||
|
@ -629,6 +642,11 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(not (ruby-smie--bosp)))
|
||||
(forward-char -1))
|
||||
(smie-indent-virtual))
|
||||
((save-excursion
|
||||
(and (smie-rule-parent-p " @ ")
|
||||
(goto-char (nth 1 (smie-indent--parent)))
|
||||
(smie-rule-prev-p "def=")
|
||||
(cons 'column (- (current-column) 3)))))
|
||||
(t (smie-rule-parent))))))
|
||||
(`(:after . ,(or "(" "[" "{"))
|
||||
;; FIXME: Shouldn't this be the default behavior of
|
||||
|
@ -672,6 +690,12 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(and (smie-rule-parent-p ";" nil)
|
||||
(smie-indent--hanging-p)
|
||||
ruby-indent-level))
|
||||
(`(:before . "=")
|
||||
(save-excursion
|
||||
(and (smie-rule-parent-p " @ ")
|
||||
(goto-char (nth 1 (smie-indent--parent)))
|
||||
(smie-rule-prev-p "def=")
|
||||
(cons 'column (+ (current-column) ruby-indent-level -3)))))
|
||||
(`(:after . ,(or "?" ":")) ruby-indent-level)
|
||||
(`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords)))
|
||||
(when (not (ruby--at-indentation-p))
|
||||
|
@ -1632,7 +1656,7 @@ See `add-log-current-defun-function'."
|
|||
(while (and (re-search-backward definition-re nil t)
|
||||
(if (if (string-equal "def" (match-string 1))
|
||||
;; We're inside a method.
|
||||
(if (ruby-block-contains-point start)
|
||||
(if (ruby-block-contains-point (1- start))
|
||||
t
|
||||
;; Try to match a method only once.
|
||||
(setq definition-re module-re)
|
||||
|
|
|
@ -177,6 +177,9 @@ def test2 (arg)
|
|||
zzz @abc,
|
||||
4
|
||||
|
||||
foo a = 5,
|
||||
b
|
||||
|
||||
b = $:
|
||||
c = ??
|
||||
|
||||
|
@ -503,3 +506,33 @@ def resolve(**args)
|
|||
|
||||
member.call(**args)
|
||||
end
|
||||
|
||||
# Endless methods.
|
||||
class Bar
|
||||
def foo(abc) = bar +
|
||||
baz
|
||||
|
||||
def self.bar =
|
||||
123 +
|
||||
4
|
||||
|
||||
def foo(...) = z
|
||||
|
||||
def request_params = {
|
||||
headers: request_headers,
|
||||
body: request_body
|
||||
}
|
||||
|
||||
def self.foo(
|
||||
baz,
|
||||
bar
|
||||
) =
|
||||
what
|
||||
|
||||
def foo=(
|
||||
baz,
|
||||
bar
|
||||
)
|
||||
hello
|
||||
end
|
||||
end
|
||||
|
|
|
@ -605,6 +605,18 @@ VALUES-PLIST is a list with alternating index and value elements."
|
|||
(search-backward "FOO")
|
||||
(should (string= (ruby-add-log-current-method) "M::C"))))
|
||||
|
||||
(ert-deftest ruby-add-log-current-method-after-endless-method ()
|
||||
(ruby-with-temp-buffer (ruby-test-string
|
||||
"module M
|
||||
| class C
|
||||
| def foo =
|
||||
| 4_
|
||||
| end
|
||||
|end")
|
||||
(search-backward "_")
|
||||
(delete-char 1)
|
||||
(should (string= (ruby-add-log-current-method) "M::C#foo"))))
|
||||
|
||||
(defvar ruby-block-test-example
|
||||
(ruby-test-string
|
||||
"class C
|
||||
|
|
Loading…
Add table
Reference in a new issue