7

When using the newly added ruby formatting functionality I face the following problem:

I would really like for my rspec code to be formatted like the following:

it do
  is_expected.to match(/\[Error\]/)
    .and match(/#{result}/)
    .and match(/-+$/)
end

This is what I get when having ruby-use-smie set to nil.

When I have the variable ruby-use-smie set to non-nil however, the code gets formatted like the following:

it do
  is_expected.to match(/\[Error\]/)
                  .and match(/#{result}/)
                        .and match(/-+$/)
end

I have fiddled with the following variables:

ruby-align-chained-calls
ruby-align-to-stmt-keywords
ruby-deep-indent-paren
ruby-deep-indent-paren-style

And yet have not found a way to have the desired formatting when using ruby-smie. I'm really in love with the s-expression navigation functionality provided by smie.

Am I missing some configuration ? Is it impossible for me to achieve the first form while using ruby smie?

T. Verron
  • 4,233
  • 1
  • 22
  • 55
Renan Ranelli
  • 1,379
  • 10
  • 17
  • 1
    This seems to be a bug. Ruby SMIE indentation code is still young, and it still has problems, I guess especially with paren-less style. For now, it seems the best you can do it wrap each `match` expression in parens. And please report the bugs to the Emacs tracker. – Dmitry Dec 16 '14 at 11:05

2 Answers2

0

Upon further consideration, the indentation by SMIE makes sense. How it will look in Emacs 25.1:

it do
  is_expected.to match(/\[Error\]/)
                   .and match(/#{result}/)
                          .and match(/-+$/)
end

There is a small change due to a recent fix, and it helps to show that the indentation reflects the expression's evaluation order. Which is right-to-left in this case.

Not to say we couldn't add a variable that would recognize this as a special case and do something different, but so far I don't know what would differentiate it from a simple case of paren-less function call with continuation in its first argument, like this:

foo.bar tee
          .qux,
        aaa
          .bbb

The non-SMIE indentation engine misindents this case. From what I have of the user feedback, it's more important than the infrequently-used compound expectations in RSpec.

But you can write them just a bit differently, and the indentation will become nicer:

it do
  is_expected.to(match(/\[Error\]/))
    .and(match(/#{result}/))
    .and(match(/-+$/))
end

or

it do
  is_expected.to match(/\[Error\]/) &
                 match(/#{result}/) &
                 match(/-+$/)
end
Dmitry
  • 3,508
  • 15
  • 20
0

You should check out enhanced-ruby-mode. It uses ripper to parse the ruby, and overall in my experience indents better than ruby-mode (SMIE or not). Your snippet indents like this for me in enhanced-ruby-mode:

it do
  is_expected.to match(/\[Error\]/)
    .and match(/#{result}/)
    .and match(/-+$/)
end

Make sure you install the most recent version as there have been indentation fixes recently.

Muir
  • 311
  • 2
  • 5