From: Stefan Monnier <monnier@iro.umontreal.ca>
Date: Thu, 9 Sep 2021 14:24:57 +0000 (+0200)
Subject: Change ruby-align-chained-calls indendation
X-Git-Tag: emacs-28.0.90~1093
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8c023e5ea159c6756c92fd02643983aa449e0da9;p=emacs.git

Change ruby-align-chained-calls indendation

* lisp/progmodes/ruby-mode.el (ruby-smie-rules): Align with the
first sibling on the previous line instead of the last (bug#32496).

That is, before it used to be

one.two.three
       .four

and now it is

one.two.three
   .four
---

diff --git a/etc/NEWS b/etc/NEWS
index 7a924a860fd..ff4908af47b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2785,6 +2785,19 @@ different timezone causing a difference in the date.
 Instead you need to do "emacs -f dun-batch" to start the game in
 batch mode.
 
+** Ruby Mode
+
+---
+** 'ruby-use-smie' is declared obsolete.
+SMIE is now always enabled and 'ruby-use-smie' only controls whether
+indentation is done using SMIE or with the old ad-hoc code.
+
+---
+** Indentation has changed when 'ruby-align-chained-calls' is non-nil.
+This previously used to align subsequent lines with the last sibling,
+but it now aligns with the first sibling (which is the preferred style
+in Ruby).
+
 
 * New Modes and Packages in Emacs 28.1
 
@@ -3108,11 +3121,6 @@ back in Emacs 23.1.  The affected functions are: 'make-obsolete',
 'replace-regexp-in-string', 'catch', 'throw', 'error', 'signal'
 and 'play-sound-file'.
 
----
-** 'ruby-use-smie' is declared obsolete.
-SMIE is now always enabled and 'ruby-use-smie' only controls whether
-indentation is done using SMIE or with the old ad-hoc code.
-
 ---
 ** 'sql-*-statement-starters' are no longer user options.
 These variables describe facts about the SQL standard and
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index c09f007a5ee..d3e40770694 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -640,7 +640,15 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
     ('(:before . "do") (ruby-smie--indent-to-stmt))
     ('(:before . ".")
      (if (smie-rule-sibling-p)
-         (and ruby-align-chained-calls 0)
+         (when ruby-align-chained-calls
+           (while
+               (let ((pos (point))
+                     (parent (smie-backward-sexp ".")))
+                 (if (not (equal (nth 2 parent) "."))
+                     (progn (goto-char pos) nil)
+                   (goto-char (nth 1 parent))
+                   (not (smie-rule-bolp)))))
+           (cons 'column (current-column)))
        (smie-backward-sexp ".")
        (cons 'column (+ (current-column)
                         ruby-indent-level))))
@@ -828,6 +836,7 @@ The style of the comment is controlled by `ruby-encoding-magic-comment-style'."
 ;; `ruby-calculate-indent' in user init files still call it.
 (defun ruby-current-indentation ()
   "Return the indentation level of current line."
+  (declare (obsolete nil "28.1"))
   (save-excursion
     (beginning-of-line)
     (back-to-indentation)
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index 8bdfdc310f3..2168b38484e 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -357,7 +357,7 @@ VALUES-PLIST is a list with alternating index and value elements."
   (let ((ruby-align-chained-calls t))
     (ruby-should-indent-buffer
      "one.two.three
-     |       .four
+     |   .four
      |
      |my_array.select { |str| str.size > 5 }
      |        .map    { |str| str.downcase }"
@@ -908,6 +908,33 @@ VALUES-PLIST is a list with alternating index and value elements."
             (should (equal (buffer-string) orig))))
       (kill-buffer buf))))
 
+(ert-deftest ruby--test-chained-indentation ()
+  (with-temp-buffer
+    (ruby-mode)
+    (setq-local ruby-align-chained-calls t)
+    (insert "some_variable.where
+.not(x: nil)
+.where(y: 2)
+")
+    (indent-region (point-min) (point-max))
+    (should (equal (buffer-string)
+                   "some_variable.where
+             .not(x: nil)
+             .where(y: 2)
+")))
+
+  (with-temp-buffer
+    (ruby-mode)
+    (setq-local ruby-align-chained-calls t)
+    (insert "some_variable.where.not(x: nil)
+.where(y: 2)
+")
+    (indent-region (point-min) (point-max))
+    (should (equal (buffer-string)
+                   "some_variable.where.not(x: nil)
+             .where(y: 2)
+"))))
+
 (provide 'ruby-mode-tests)
 
 ;;; ruby-mode-tests.el ends here