unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Dmitry Gutov <dgutov@yandex.ru>
To: Aaron Jensen <aaronjensen@gmail.com>
Cc: 54702@debbugs.gnu.org
Subject: bug#54702: 29.0.50; ruby-mode indentation: endless methods
Date: Fri, 16 Dec 2022 18:15:36 +0200	[thread overview]
Message-ID: <0d8a9e9d-2c8f-6282-63da-e4af020fea8d@yandex.ru> (raw)
In-Reply-To: <CAHyO48yDW6+9R8-0ZTnUDBbFhDsY7rY6cjDfwV5_rSfEQo3Caw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 775 bytes --]

On 16/12/2022 15:12, Aaron Jensen wrote:
> On Fri, Dec 16, 2022 at 7:31 AM Dmitry Gutov <dgutov@yandex.ru> wrote:
>>
>> Right, thanks. See the attached updated patch.
> 
> That works. I found another inconsistency related to the other issue I
> just opened:
> 
> def foo(
>        baz,
>        bar
> ) = what
> 
> def foo(
>        baz,
>        bar
>      )
>    hello
> end
> 
> I don't know who is savage enough to do a multi-line endless method
> like that, but when it's done the closing paren should probably be
> consistent w/ the regular method closing paren.

Thank you, savage indeed.

Okay, here's an alternative version -- this was a pain to implement.

Would be much easier if we just decided to change the args indentation 
without support for the current one.

[-- Attachment #2: ruby-endless-methods-v2.diff --]
[-- Type: text/x-patch, Size: 5108 bytes --]

diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 4ac289d529..295a2a67e9 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -134,6 +134,12 @@ ruby-symbol-chars
 (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 @@ ruby-smie-grammar
        (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 @@ ruby-smie--forward-token
               (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 @@ ruby-smie--backward-token
             (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,13 @@ ruby-smie-rules
                      (not (ruby-smie--bosp)))
            (forward-char -1))
          (smie-indent-virtual))
+        ((and (smie-rule-parent-p " @ ")
+              (save-excursion
+                (goto-char (nth 1 (smie-indent--parent)))
+                (and
+                 (smie-rule-prev-p "def=")
+                 (smie-indent-backward-token)
+                 (smie-indent-virtual)))))
         (t (smie-rule-parent))))))
     (`(:after . ,(or "(" "[" "{"))
      ;; FIXME: Shouldn't this be the default behavior of
@@ -672,6 +692,11 @@ ruby-smie-rules
      (and (smie-rule-parent-p ";" nil)
           (smie-indent--hanging-p)
           ruby-indent-level))
+    (`(:before . "=")
+     (when (smie-rule-parent-p " @ ")
+       (goto-char (nth 1 (smie-indent--parent)))
+       (smie-indent-backward-token)
+       (cons 'column (+ (smie-indent-virtual) ruby-indent-level))))
     (`(:after . ,(or "?" ":")) ruby-indent-level)
     (`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords)))
      (when (not (ruby--at-indentation-p))
@@ -1631,7 +1656,7 @@ ruby-add-log-current-method
                   (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 f39489071e..9d9b46fa31 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -500,3 +500,41 @@ def resolve(**args)
 
   member.call(**args)
 end
+
+# Endless methods.
+class Bar
+  def foo(abc) =
+    bar +
+    bar
+      .baz
+
+  def self.bar =
+    123 +
+    4
+
+  def request_params = {
+    headers: request_headers,
+    body: request_body
+  }
+
+  foo a = 5,
+      b
+
+  def foo(
+        baz,
+        bar
+      ) =
+    what
+
+  def foo(
+        baz,
+        bar
+      )
+    hello
+  end
+end
+
+class Foo
+  def foo(...) = z
+  def bar = y
+end
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index e90a9e4075..9be01dc78f 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -605,6 +605,18 @@ ruby-add-log-current-method-after-inner-class-outside-methods-with-text
     (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

  reply	other threads:[~2022-12-16 16:15 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-04  2:03 bug#54702: 29.0.50; ruby-mode indentation: endless methods Aaron Jensen
2022-04-27  2:44 ` Dmitry Gutov
2022-04-27 23:58   ` Aaron Jensen
2022-12-16  0:33     ` Dmitry Gutov
2022-12-16  5:07       ` Aaron Jensen
2022-12-16 12:31         ` Dmitry Gutov
2022-12-16 12:40           ` Dmitry Gutov
2022-12-16 14:49             ` Eli Zaretskii
2022-12-18 12:06               ` Dmitry Gutov
2022-12-18 15:42                 ` Aaron Jensen
2022-12-16 13:12           ` Aaron Jensen
2022-12-16 16:15             ` Dmitry Gutov [this message]
2022-12-16 16:24               ` Aaron Jensen
2022-12-16 17:49                 ` Dmitry Gutov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0d8a9e9d-2c8f-6282-63da-e4af020fea8d@yandex.ru \
    --to=dgutov@yandex.ru \
    --cc=54702@debbugs.gnu.org \
    --cc=aaronjensen@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).