diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 1f3e9b6ae7b..542c8ac02f1 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -285,6 +285,11 @@ ruby-method-params-indent :safe (lambda (val) (or (memq val '(t nil)) (numberp val))) :version "29.1") +(defcustom ruby-indent-simplified nil + "Foo bar." + :type 'boolean + :safe 'booleanp) + (defcustom ruby-deep-arglist t "Deep indent lists in parenthesis when non-nil. Also ignores spaces after parenthesis when `space'. @@ -416,6 +421,7 @@ ruby-smie-grammar '((right "=") (right "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" "<<=" ">>=" "&&=" "||=") + (right "?") (nonassoc ".." "...") (left "&&" "||") (nonassoc "<=>") @@ -608,10 +614,10 @@ ruby-smie--backward-token "def=") (t tok))))))) -(defun ruby-smie--indent-to-stmt () +(defun ruby-smie--indent-to-stmt (&optional offset) (save-excursion (smie-backward-sexp ";") - (cons 'column (smie-indent-virtual)))) + (cons 'column (+ (smie-indent-virtual) (or offset 0))))) (defun ruby-smie--indent-to-stmt-p (keyword) (or (eq t ruby-align-to-stmt-keywords) @@ -642,7 +648,9 @@ ruby-smie-rules (forward-comment -1) (not (eq (preceding-char) ?:)))) ;; Curly block opener. - (ruby-smie--indent-to-stmt)) + (if ruby-indent-simplified + (cons 'column (current-indentation)) + (ruby-smie--indent-to-stmt))) ((smie-rule-hanging-p) ;; Treat purely syntactic block-constructs as being part of their parent, ;; when the opening token is hanging and the parent is not an @@ -683,7 +691,10 @@ ruby-smie-rules (skip-chars-forward " \t") (cons 'column (current-column))) (smie-rule-parent (or ruby-method-params-indent 0)))) - ('(:before . "do") (ruby-smie--indent-to-stmt)) + ('(:before . "do") + (if ruby-indent-simplified + (cons 'column (current-indentation)) + (ruby-smie--indent-to-stmt))) ('(:before . ".") (if (smie-rule-sibling-p) (when ruby-align-chained-calls @@ -696,8 +707,10 @@ ruby-smie-rules (not (smie-rule-bolp))))) (cons 'column (current-column))) (smie-backward-sexp ".") - (cons 'column (+ (current-column) - ruby-indent-level)))) + (if ruby-indent-simplified + (ruby-smie--indent-to-stmt ruby-indent-level) + (cons 'column (+ (current-column) + ruby-indent-level))))) (`(:before . ,(or "else" "then" "elsif" "rescue" "ensure")) (smie-rule-parent)) (`(:before . ,(or "when" "in")) @@ -710,14 +723,16 @@ ruby-smie-rules "<<=" ">>=" "&&=" "||=" "and" "or")) (and (smie-rule-parent-p ";" nil) (smie-indent--hanging-p) - ruby-indent-level)) + (if ruby-indent-simplified + (ruby-smie--indent-to-stmt ruby-indent-level) + 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) + (`(:after . ,(or "?" ":")) (unless ruby-indent-simplified ruby-indent-level)) (`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords))) (when (not (ruby--at-indentation-p)) (if (ruby-smie--indent-to-stmt-p token) @@ -725,7 +740,17 @@ ruby-smie-rules (cons 'column (current-column))))) ('(:before . "iuwu-mod") (smie-rule-parent ruby-indent-level)) - )) + (`(:before . ,_) + (when (and ruby-indent-simplified + (not (or (member token '(",")) + (smie-rule-prev-p ";")))) + (let* ((stmt-beg (save-excursion + (smie-backward-sexp ";") + (point))) + (nls (1- (count-lines stmt-beg (point))))) + (when (smie-indent--hanging-p) + (cl-incf nls)) + (ruby-smie--indent-to-stmt (if (> nls 0) ruby-indent-level 0))))))) (defun ruby--at-indentation-p (&optional point) (save-excursion diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-indent-simplified.rb b/test/lisp/progmodes/ruby-mode-resources/ruby-indent-simplified.rb new file mode 100644 index 00000000000..9f1fb0edd80 --- /dev/null +++ b/test/lisp/progmodes/ruby-mode-resources/ruby-indent-simplified.rb @@ -0,0 +1,62 @@ +4 + + 5 + + 6 + + 7 + +foo = obj.bar { |m| tee(m) } + + obj.qux { |m| hum(m) } + +foo. + bar + .baz + +qux = foo.fee ? + bar : + tee + +foo2 = + subject. + update( + 2 + ) + +m1 = foo + .asdasd + .proc do |**args| + p(**args) + end + +m2 = foo + .asdasd + .proc { |**args| + p(**args) + } + +bar.foo do + bar +end + +bar.foo(tee) do + bar +end + +bar.foo(tee) { + bar +} + +# Endless methods. +class Bar + def foo(abc) = bar + + baz +end + +x.foo do + foo +end.bar do + bar +end + +# Local Variables: +# ruby-method-params-indent: t +# ruby-indent-simplified: t +# End: diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb index 6a69d9db78a..d0ee8f8f52b 100644 --- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb +++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb @@ -226,6 +226,7 @@ def begin foo. bar + .baz # https://github.com/rails/rails/blob/17f5d8e062909f1fcae25351834d8e89967b645e/activesupport/lib/active_support/time_with_zone.rb#L206 foo # comment intended to confuse the tokenizer @@ -380,6 +381,18 @@ def bar i + 1 end +m1 = foo + .asdasd + .proc do |**args| + p(**args) +end + +m2 = foo + .asdasd + .proc { |**args| + p(**args) +} + bar.foo do bar end @@ -398,6 +411,12 @@ def bar end end +x.foo do + foo +end.bar do + bar +end + foo | bar @@ -541,4 +560,5 @@ def baz.full_name = "#{bar} 3" # Local Variables: # ruby-method-params-indent: t +# ruby-indent-simplified: nil # End: diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el index 560f780285a..4a86492b137 100644 --- a/test/lisp/progmodes/ruby-mode-tests.el +++ b/test/lisp/progmodes/ruby-mode-tests.el @@ -957,6 +957,7 @@ ruby-deftest-indent (ruby-deftest-indent "ruby.rb") (ruby-deftest-indent "ruby-method-params-indent.rb") +(ruby-deftest-indent "ruby-indent-simplified.rb") (ert-deftest ruby--test-chained-indentation () (with-temp-buffer