]> git.eshelyaron.com Git - emacs.git/commitdiff
ruby-mode: Support endless methods (bug#54702)
authorDmitry Gutov <dgutov@yandex.ru>
Sun, 18 Dec 2022 12:01:47 +0000 (14:01 +0200)
committerDmitry Gutov <dgutov@yandex.ru>
Sun, 18 Dec 2022 12:04:17 +0000 (14:04 +0200)
* 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.

etc/NEWS
lisp/progmodes/ruby-mode.el
test/lisp/progmodes/ruby-mode-resources/ruby.rb
test/lisp/progmodes/ruby-mode-tests.el

index 25148dc2fdc8cf5bc7204404debb33ab1472dbbe..cded60cca631f3279e8d32ced03994d0a2ff4717 100644 (file)
--- 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
 
 +++
index 2b1db5980691492352c0ec3e4fbbdffffe682ab2..ed6044280ea5d19aaeabe17c75ca083d09ede476 100644 (file)
@@ -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)
index 43f8bebcfc2e54b24e29ff6cfa5e986595226967..5636a4fc0e2e233245beb426a2ad058fc7634102 100644 (file)
@@ -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
index e90a9e407531ac86894d86243ec62c5eacd18c5f..9be01dc78f9014185f6d3df68a2aee7a6113ada3 100644 (file)
@@ -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