From e2a67bd08ea194da1b338c69c4da6e539782cb14 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Fri, 31 Jan 2014 19:13:49 +0200 Subject: [PATCH] Implement user option ruby-align-chained-calls * lisp/progmodes/ruby-mode.el (ruby-align-chained-calls): New option. (ruby-smie-grammar): Make "." right-associative. Make its priority lower than the ternary and all binary operators. (ruby-smie-rules): Indent "(" relative to the first non-"." parent, or the first "." parent at indentation. Use `ruby-align-chained-calls' for indentation of "." tokens. * test/automated/ruby-mode-tests.el (ruby-align-chained-calls): New test. Fixes: debbugs:16593 --- lisp/ChangeLog | 10 ++++++++++ lisp/progmodes/ruby-mode.el | 38 +++++++++++++++++++++++++++++++------- test/ChangeLog | 5 +++++ test/automated/ruby-mode-tests.el | 14 ++++++++++++++ test/indent/ruby.rb | 8 ++++---- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0a609682d62..90c00963ad4 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2014-01-31 Dmitry Gutov + + * progmodes/ruby-mode.el (ruby-align-chained-calls): New option. + (ruby-smie-grammar): Make "." right-associative. Make its priority + lower than the ternary and all binary operators. + (ruby-smie-rules): Indent "(" relative to the first non-"." + parent, or the first "." parent at indentation. Use + `ruby-align-chained-calls' for indentation of "." tokens. + (Bug#16593) + 2014-01-31 Juri Linkov * sort.el (delete-duplicate-lines): Remove `:weakness 'key' diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index f0a9da80ea4..17e16217ccb 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -264,6 +264,15 @@ Only has effect when `ruby-use-smie' is t. :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. + +Only has effect when `ruby-use-smie' is t." + :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 +359,10 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." ;; 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 +389,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (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 +408,8 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (nonassoc ">" ">=" "<" "<=") (nonassoc "==" "===" "!=") (nonassoc "=~" "!~") - (left "<<" ">>")))))) + (left "<<" ">>") + (right ".")))))) (defun ruby-smie--bosp () (save-excursion (skip-chars-backward " \t") @@ -609,7 +619,18 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." ;; 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 +643,10 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (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)) diff --git a/test/ChangeLog b/test/ChangeLog index 50ffd7c3957..5afc9890aff 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,8 @@ +2014-01-31 Dmitry Gutov + + * automated/ruby-mode-tests.el (ruby-align-chained-calls): + New test. + 2014-01-27 Michael Albinus * automated/file-notify-tests.el (file-notify--deftest-remote): diff --git a/test/automated/ruby-mode-tests.el b/test/automated/ruby-mode-tests.el index aa8032bb870..f6fddb5ef4c 100644 --- a/test/automated/ruby-mode-tests.el +++ b/test/automated/ruby-mode-tests.el @@ -333,6 +333,20 @@ VALUES-PLIST is a list with alternating index and value elements." | 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) diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index a0116fef18e..49ed92f8fdc 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb @@ -257,8 +257,8 @@ foo ^ bar foo_bar_tee(1, 2, 3) - .qux - .bar + .qux.bar + .tee foo do bar @@ -338,7 +338,7 @@ end %^abc^ ddd -qux = foo ? +qux = foo.fee ? bar : tee @@ -348,7 +348,7 @@ zoo.keep.bar!( zoo .lose( - q, p) + q, p) foo(bar: tee) -- 2.11.4.GIT