6

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?

  • 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
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
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.