From: Dmitry Gutov Date: Sun, 18 Dec 2022 12:01:47 +0000 (+0200) Subject: ruby-mode: Support endless methods (bug#54702) X-Git-Tag: emacs-29.0.90~1080 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6f88de109c8;p=emacs.git 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. --- diff --git a/etc/NEWS b/etc/NEWS index 25148dc2fdc..cded60cca63 100644 --- a/etc/NEWS +++ b/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 +++ diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 2b1db598069..ed6044280ea 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -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) diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb index 43f8bebcfc2..5636a4fc0e2 100644 --- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb +++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb @@ -177,6 +177,9 @@ qux :+, 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 diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el index e90a9e40753..9be01dc78f9 100644 --- a/test/lisp/progmodes/ruby-mode-tests.el +++ b/test/lisp/progmodes/ruby-mode-tests.el @@ -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