GNU bug report logs - #60321
29.0.60; ruby-mode indentation of hash or array as first arg in multiline method call

Previous Next

Package: emacs;

Reported by: Dmitry Gutov <dgutov <at> yandex.ru>

Date: Sun, 25 Dec 2022 21:30:02 UTC

Severity: normal

Found in version 29.0.60

To reply to this bug, email your comments to 60321 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to aaronjensen <at> gmail.com, bug-gnu-emacs <at> gnu.org:
bug#60321; Package emacs. (Sun, 25 Dec 2022 21:30:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Dmitry Gutov <dgutov <at> yandex.ru>:
New bug report received and forwarded. Copy sent to aaronjensen <at> gmail.com, bug-gnu-emacs <at> gnu.org. (Sun, 25 Dec 2022 21:30:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dmitry Gutov <dgutov <at> yandex.ru>
To: bug-gnu-emacs <at> gnu.org
Subject: 29.0.60; ruby-mode indentation of hash or array as first arg in
 multiline method call
Date: Sun, 25 Dec 2022 23:29:21 +0200
X-Debbugs-CC: aaronjensen <at> gmail.com

Splitting off from debbugs#60186, second try.

Since this setting also seems orthogonal to the "simplified" preference, 
and it'll require some more work.

For future reference, here are the relevant Rubocop settings:

https://docs.rubocop.org/rubocop/cops_layout.html#layoutfirsthashelementindentation
https://docs.rubocop.org/rubocop/cops_layout.html#layoutfirstarrayelementindentation

On 25/12/2022 02:12, Aaron Jensen wrote:
>> We could also discuss cases like
>>
>>     foo = bar({
>>                 tee: 1,
>>                 qux: 2
>>              })
>>
>>     baz([
>>           1,
>>           2,
>>           3
>>         ])
>>
>> but those would be an orthogonal feature. And I don't see them much in
>> the wild, for some reason.
> The same logic would apply. It doesn't matter how many indent starters
> there are in a line, the indentation should only increase by one:
> 
> 
> foo = bar({
>    tee: 1,
>    qux: 2
> })
> 
> baz([
>    1,
>    2,
>    3
> ])
> 
> Of course, that begs the question what happens if you do this:
> 
> baz([
>    1,
>    2,
>    3
> ]
> )

Here are a couple trickier examples:

takes_multi_pairs_hash(x: {
  a: 1,
  b: 2
})

and_in_a_method_call({
  no: :difference
},
foo,
bar)

AFAICT even Rubocop doesn't have a setting which would indent the second 
one somewhat reasonably, while keeping two-space indent before "no".

> And, I think again, the answer is a social one, rather than a technical one.
> 
> enh-ruby-mode and vim both do this this:
> 
> baz([
>    1,
>    2,
>    3
> ]
>     )

Yup, that looks pretty bizarre. OTOH, I don't see why a developer would 
put a newline between "]" and ")" in this case.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#60321; Package emacs. (Sun, 25 Dec 2022 23:47:02 GMT) Full text and rfc822 format available.

Message #8 received at 60321 <at> debbugs.gnu.org (full text, mbox):

From: Aaron Jensen <aaronjensen <at> gmail.com>
To: Dmitry Gutov <dgutov <at> yandex.ru>
Cc: 60321 <at> debbugs.gnu.org
Subject: Re: bug#60321: 29.0.60; ruby-mode indentation of hash or array as
 first arg in multiline method call
Date: Sun, 25 Dec 2022 18:46:07 -0500
On Sun, Dec 25, 2022 at 4:30 PM Dmitry Gutov <dgutov <at> yandex.ru> wrote:
>
> X-Debbugs-CC: aaronjensen <at> gmail.com
>
> Splitting off from debbugs#60186, second try.
>
> Since this setting also seems orthogonal to the "simplified" preference,
> and it'll require some more work.
>
> For future reference, here are the relevant Rubocop settings:
>
> https://docs.rubocop.org/rubocop/cops_layout.html#layoutfirsthashelementindentation
> https://docs.rubocop.org/rubocop/cops_layout.html#layoutfirstarrayelementindentation
>
> On 25/12/2022 02:12, Aaron Jensen wrote:
> >> We could also discuss cases like
> >>
> >>     foo = bar({
> >>                 tee: 1,
> >>                 qux: 2
> >>              })
> >>
> >>     baz([
> >>           1,
> >>           2,
> >>           3
> >>         ])
> >>
> >> but those would be an orthogonal feature. And I don't see them much in
> >> the wild, for some reason.
> > The same logic would apply. It doesn't matter how many indent starters
> > there are in a line, the indentation should only increase by one:
> >
> >
> > foo = bar({
> >    tee: 1,
> >    qux: 2
> > })
> >
> > baz([
> >    1,
> >    2,
> >    3
> > ])
> >
> > Of course, that begs the question what happens if you do this:
> >
> > baz([
> >    1,
> >    2,
> >    3
> > ]
> > )
>
> Here are a couple trickier examples:
>
> takes_multi_pairs_hash(x: {
>    a: 1,
>    b: 2
> })

enh-ruby-mode and vim do the same thing, which I think is fine:

takes_multi_pairs_hash(x: {
  a: 1,
  b: 2
})

Though again, the best answer imo is "don't do this".


>
> and_in_a_method_call({
>    no: :difference
> },
> foo,
> bar)

enh-ruby-mode:

and_in_a_method_call({
  no: :difference
},
                     foo,
                     bar)


Vim:

and_in_a_method_call({
  no: :difference
},
foo,
bar)

I think this falls under something I wouldn't put too much effort into
fixing. I would write it like this:

and_in_a_method_call(
  {
    no: :difference
  },
  foo,
  bar
)

Which indents in a straightforward manner.

If I had to type it as above, I would probably indent it like this:

and_in_a_method_call({
    no: :difference
  },
  foo,
  bar)

But I can't imagine that would be easy to implement at all, so I
wouldn't bother.


> AFAICT even Rubocop doesn't have a setting which would indent the second
> one somewhat reasonably, while keeping two-space indent before "no".
>
> > And, I think again, the answer is a social one, rather than a technical one.
> >
> > enh-ruby-mode and vim both do this this:
> >
> > baz([
> >    1,
> >    2,
> >    3
> > ]
> >     )
>
> Yup, that looks pretty bizarre. OTOH, I don't see why a developer would
> put a newline between "]" and ")" in this case.

Exactly, that's what I meant by a social problem. We have a (somewhat
harsh) saying for stuff like this: you get what you deserve. That's
actually why I don't mind enh-ruby-mode's behavior here. It's clearly
undefined/out of bounds, so that tells a person they are currently out
of bounds and they should get back in bounds.

Aaron




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#60321; Package emacs. (Tue, 27 Dec 2022 01:17:02 GMT) Full text and rfc822 format available.

Message #11 received at 60321 <at> debbugs.gnu.org (full text, mbox):

From: Dmitry Gutov <dgutov <at> yandex.ru>
To: Aaron Jensen <aaronjensen <at> gmail.com>
Cc: 60321 <at> debbugs.gnu.org
Subject: Re: bug#60321: 29.0.60; ruby-mode indentation of hash or array as
 first arg in multiline method call
Date: Tue, 27 Dec 2022 03:16:27 +0200
On 26/12/2022 01:46, Aaron Jensen wrote:

> enh-ruby-mode and vim do the same thing, which I think is fine:
> 
> takes_multi_pairs_hash(x: {
>    a: 1,
>    b: 2
> })

Makes sense to me, I just wanted to keep this case in the bug report 
because it will likely need a separate indentation rule or a separate 
clause.

>> and_in_a_method_call({
>>     no: :difference
>> },
>> foo,
>> bar)
> 
> enh-ruby-mode:
> 
> and_in_a_method_call({
>    no: :difference
> },
>                       foo,
>                       bar)
> 
> 
> Vim:
> 
> and_in_a_method_call({
>    no: :difference
> },
> foo,
> bar)

Vim's choice looks saner to my eye. Probably comes down to the choice of 
indentation algorithm, though.

> I think this falls under something I wouldn't put too much effort into
> fixing. I would write it like this:
> 
> and_in_a_method_call(
>    {
>      no: :difference
>    },
>    foo,
>    bar
> )
> 
> Which indents in a straightforward manner.

Indeed. But this works already, no changes required.

> If I had to type it as above, I would probably indent it like this:
> 
> and_in_a_method_call({
>      no: :difference
>    },
>    foo,
>    bar)
> 
> But I can't imagine that would be easy to implement at all, so I
> wouldn't bother.

The indentation logic itself might be not that difficult to write, but 
the fact that the expression will have to be reindented as soon as the 
method call grows a second argument (after the user types the comma?), 
makes it a hard sell usability-wise.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#60321; Package emacs. (Tue, 27 Dec 2022 01:39:01 GMT) Full text and rfc822 format available.

Message #14 received at 60321 <at> debbugs.gnu.org (full text, mbox):

From: Aaron Jensen <aaronjensen <at> gmail.com>
To: Dmitry Gutov <dgutov <at> yandex.ru>
Cc: 60321 <at> debbugs.gnu.org
Subject: Re: bug#60321: 29.0.60; ruby-mode indentation of hash or array as
 first arg in multiline method call
Date: Mon, 26 Dec 2022 20:38:03 -0500
On Mon, Dec 26, 2022 at 8:16 PM Dmitry Gutov <dgutov <at> yandex.ru> wrote:
>
> Vim's choice looks saner to my eye. Probably comes down to the choice of
> indentation algorithm, though.

Agreed, though it's hard to pick which is more sane when all the
options start with insanity.

> > If I had to type it as above, I would probably indent it like this:
> >
> > and_in_a_method_call({
> >      no: :difference
> >    },
> >    foo,
> >    bar)
> >
> > But I can't imagine that would be easy to implement at all, so I
> > wouldn't bother.
>
> The indentation logic itself might be not that difficult to write, but
> the fact that the expression will have to be reindented as soon as the
> method call grows a second argument (after the user types the comma?),
> makes it a hard sell usability-wise.

Right, I think that's just more of the same thing... We are looking at
ways of writing code that are out of the realm of reason. It's a
challenge to define behavior when the behavior could very well be
undefined. But, if we must define it, then what are our guiding
principles? Not having to reindent preceding lines when adding a new
line may be a very reasonable one. In that case, the only two options
I could think of would be:

and_in_a_method_call({
  no: :difference
  },
  foo,
  bar)

or

and_in_a_method_call({
  no: :difference
  },
foo,
bar)

The difference being if we decide to dedent upon the last closing
indent-requiring-token or the first.

I think a reasonable rule of thumb for a human might be: "If you open
N indents on one line, you must close N indents on one line". Any time
you stray away from this, behavior becomes... not ideal.

Aaron




This bug report was last modified 1 year and 120 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.