=== modified file 'lisp/progmodes/ruby-mode.el' --- lisp/progmodes/ruby-mode.el 2014-01-17 03:15:02 +0000 +++ lisp/progmodes/ruby-mode.el 2014-01-31 03:17:28 +0000 @@ -264,6 +264,13 @@ :safe 'listp :version "24.4") +(defcustom ruby-align-chained-calls nil + "If non-nil, chained method calls on multiple lines will be +aligned to the same column." + :type 'boolean + :group 'ruby + :safe 'booleanp) + (defcustom ruby-deep-arglist t "Deep indent lists in parenthesis when non-nil. Also ignores spaces after parenthesis when `space'. @@ -350,10 +357,10 @@ ;; but avoids lots of conflicts: (exp "and" exp) (exp "or" exp)) (exp (exp1) (exp "," exp) (exp "=" exp) - (id " @ " exp) - (exp "." id)) + (id " @ " exp)) (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) - (exp2 ("def" insts "end") + (exp2 (exp3) (exp3 "." exp2)) + (exp3 ("def" insts "end") ("begin" insts-rescue-insts "end") ("do" insts "end") ("class" insts "end") ("module" insts "end") @@ -380,7 +387,7 @@ (ielsei (itheni) (itheni "else" insts)) (if-body (ielsei) (if-body "elsif" if-body))) '((nonassoc "in") (assoc ";") (right " @ ") - (assoc ",") (right "=") (assoc ".")) + (assoc ",") (right "=")) '((assoc "when")) '((assoc "elsif")) '((assoc "rescue" "ensure")) @@ -399,7 +406,8 @@ (nonassoc ">" ">=" "<" "<=") (nonassoc "==" "===" "!=") (nonassoc "=~" "!~") - (left "<<" ">>")))))) + (left "<<" ">>") + (right ".")))))) (defun ruby-smie--bosp () (save-excursion (skip-chars-backward " \t") @@ -609,7 +617,18 @@ ;; When after `.', let's always de-indent, ;; because when `.' is inside the line, the ;; additional indentation from it looks out of place. - ((smie-rule-parent-p ".") (smie-rule-parent (- ruby-indent-level))) + ((smie-rule-parent-p ".") + (let (smie--parent) + (save-excursion + ;; Traverse up the parents until the parent is "." at + ;; indentation, or any other token. + (while (and (progn + (goto-char (1- (cadr (smie-indent--parent)))) + (not (ruby-smie--bosp))) + (progn + (setq smie--parent nil) + (smie-rule-parent-p ".")))) + (smie-rule-parent)))) (t (smie-rule-parent)))))) (`(:after . ,(or `"(" "[" "{")) ;; FIXME: Shouldn't this be the default behavior of @@ -622,7 +641,10 @@ (unless (or (eolp) (forward-comment 1)) (cons 'column (current-column))))) (`(:before . "do") (ruby-smie--indent-to-stmt)) - (`(:before . ".") ruby-indent-level) + (`(:before . ".") + (if (smie-rule-sibling-p) + (and ruby-align-chained-calls 0) + ruby-indent-level)) (`(:after . "=>") ruby-indent-level) (`(:before . ,(or `"else" `"then" `"elsif" `"rescue" `"ensure")) (smie-rule-parent)) === modified file 'test/automated/ruby-mode-tests.el' --- test/automated/ruby-mode-tests.el 2014-01-01 07:43:34 +0000 +++ test/automated/ruby-mode-tests.el 2014-01-30 04:15:02 +0000 @@ -333,6 +333,20 @@ | 42 | end"))) +(ert-deftest ruby-align-chained-calls () + (let ((ruby-align-chained-calls t)) + (ruby-should-indent-buffer + "one.two.three + | .four + | + |my_array.select { |str| str.size > 5 } + | .map { |str| str.downcase }" + "one.two.three + | .four + | + |my_array.select { |str| str.size > 5 } + | .map { |str| str.downcase }"))) + (ert-deftest ruby-move-to-block-stops-at-indentation () (ruby-with-temp-buffer "def f\nend" (beginning-of-line) === modified file 'test/indent/ruby.rb' --- test/indent/ruby.rb 2014-01-17 03:15:02 +0000 +++ test/indent/ruby.rb 2014-01-31 02:55:31 +0000 @@ -257,8 +257,8 @@ bar foo_bar_tee(1, 2, 3) - .qux - .bar + .qux.bar + .tee foo do bar @@ -338,7 +338,7 @@ %^abc^ ddd -qux = foo ? +qux = foo.fee ? bar : tee @@ -348,7 +348,7 @@ zoo .lose( - q, p) + q, p) foo(bar: tee)