Vim's Ruby indenting

Hi to all the vim users,

I have always used Vim to edit my Ruby code, and I've always been very
grateful that Ruby had both indenting and syntax files. However, the
indenting has started to irritate me lately. It doesn't always indent
the way it should.

In Emacs, when you want to write method(foo, bar, baz) with foo, bar
and baz on separate lines, bar and baz will align themselves with foo.

method(foo,
       bar,
       baz)

However, with vim, bar will align itself with method not with foo, and
baz will align itself with bar. So you end up with:

method(foo,
bar,
baz)

And you have to manually align the parameters. It's annyoing,
especially if you then decide to reindent the whole file with =G, then
you just ruin the alignment you made and you either need to do it again
or put up with bad style.

Similar bad indenting happens with multiple-lines arrays, hashes,
assignements to the result of an expression such as if or case[1], and
probably other case I'm not thinking of right now.

Does anyone have experience in vim indent files hacking who could maybe
fix those issues, or point me to a good reference on how to fix this?
This is starting to seriously annoy me.

Vincent.

[1]
foo = case bar
when 1: 2
when 2: 3
end

instead of
foo = case bar
      when 1: 2
      when 2: 3
      end

[snip]

Does anyone have experience in vim indent files hacking who could maybe
fix those issues, or point me to a good reference on how to fix this?
This is starting to seriously annoy me.

I just came over from emacs to vim, and this is also the main thing
that annoys me.
With hashes you can get away with
a = {
  b => c,
  d => e
}

But I don't know about the rest

Best regards,

Brian

···

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

method(foo,
       bar,
       baz)

However, with vim, bar will align itself with method not with foo, and
baz will align itself with bar. So you end up with:

method(foo,
bar,
baz)

Do you use vim-ruby's indent file?

" Language: Ruby
" Maintainer: Gavin Sinclair <gsinclair at soyabean.com.au>
" Developer: Nikolai Weibull <lone-star at home.se>
" Info: $Id: ruby.vim,v 1.21 2003/10/20 01:02:13 pcp Exp $
" URL: http://vim-ruby.rubyforge.org/

Cheers,
Thomas.

Yes, I do. And I have this version installed.

Ah no, I did not. Thought I did. I used the new version and it fixed
the method parameters problem. However, the myvar = case foo still
breaks on the next line.

Vincent Foley wrote:

However, the myvar = case foo still breaks on the next line.

I’ll add support for this at a later time. Until then, consider
rethinking writing code that uses the case statement in this manner,
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

I like this kind of code.

a = case b
   when 1: 10
   when 2: 20
   else 50
   end

makes it clear that something is assigned to a. While

case b
when 1: a = 10
when 2: a = 20
else a = 50
end

does not make this important fact as clear on first sight.

best regards,

Brian

···

On 23/05/05, Nikolai Weibull <mailing-lists.ruby-talk@rawuncut.elitemail.org> wrote:

Vincent Foley wrote:

> However, the myvar = case foo still breaks on the next line.

I'll add support for this at a later time. Until then, consider
rethinking writing code that uses the case statement in this manner,
        nikolai

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

Brian Schröder wrote:

> > However, the myvar = case foo still breaks on the next line.

> I'll add support for this at a later time. Until then, consider
> rethinking writing code that uses the case statement in this manner,

I like this kind of code.

a = case b
   when 1: 10
   when 2: 20
   else 50
   end

makes it clear that something is assigned to a.

Sure, but tell me a reasonable way to indent it and provide me with the
code to do it and I’ll add it immediately. Adding something like this
will require changes that will ripple through the whole indentation
code. People seem to think that indentation is a simple matter.
Perhaps they should give it a try sometime. Coming up with a reasonable
Ruby indentation definition took me two weeks of hard work and heavy
thinking. Neither Ruby nor Vim is very friendly to do this kind of
stuff for. Another deterrent thing is that people complain when it
doesn’t work but keep very quiet when it does,
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Brian Schröder wrote:

I like this kind of code.

a = case b
   when 1: 10
   when 2: 20
   else 50
   end

makes it clear that something is assigned to a. While

case b
when 1: a = 10
when 2: a = 20
else a = 50
end

does not make this important fact as clear on first sight.

The following code indents properly and is what I use.

  a =
    case b
    when 1: 10
    when 2: 20
    else 50
    end

To follow up Vincent's comments: to try your hand at this, there's no
shortcut; just read the Vim help files on indenting and general Vim
programming (it's fugly), and hack around with the existing
highlighting code. I don't understand it myself. Indenting Ruby is
Hard with a capital H. Writing the logic in the 10th-rate programming
language that is VimScript (or whatever they call it) is insane, but
Nikolai has done a great job.

I doubt it will ever improve to the point that gg=G is advisable on a
large file, though. I always indent one unit-of-code (e.g.
block/method/class) at a time.

Cheers,
Gavin

Quoting gsinclair@gmail.com, on Tue, May 24, 2005 at 08:30:17AM +0900:

To follow up Vincent's comments: to try your hand at this, there's no
shortcut; just read the Vim help files on indenting and general Vim
programming (it's fugly), and hack around with the existing
highlighting code. I don't understand it myself. Indenting Ruby is
Hard with a capital H. Writing the logic in the 10th-rate programming
language that is VimScript (or whatever they call it) is insane, but
Nikolai has done a great job.

I wonder whether using Syntax, based on the ruby parser, would allow an
external tool to be written (in ruby...) that would do better. Down side
is it wouldn't indent as you type, upside is you could set indentprg,
and run the whole file through it.

Nikolai has performed miracles, but it almost seems like an excercise in
coding in Brainfuck, or some similar language.

Sam

Oh, don't get me wrong, I definitly appreciate what you did. I once
tried to modify the file, but VimScript is absolutely the worst
language I've ever seen, so kudos to you for doing it.

Sorry Nikolai, I really appreciate your work. It was just that you
proposed changing the code, and I wanted to say that I like this
idiom.

The emacs indenting does it right, but I have no clue about vimscript.
Ultimately I think somehow one would need a real ruby parser to get
indentation always right. And I'm shure nobody would be willing to
write that in vimscript :wink:

thanks for your work,

best regards,

Brian

···

On 24/05/05, Nikolai Weibull <mailing-lists.ruby-talk@rawuncut.elitemail.org> wrote:

Brian Schröder wrote:

> > > However, the myvar = case foo still breaks on the next line.

> > I'll add support for this at a later time. Until then, consider
> > rethinking writing code that uses the case statement in this manner,

> I like this kind of code.

> a = case b
> when 1: 10
> when 2: 20
> else 50
> end

> makes it clear that something is assigned to a.

Sure, but tell me a reasonable way to indent it and provide me with the
code to do it and I'll add it immediately. Adding something like this
will require changes that will ripple through the whole indentation
code. People seem to think that indentation is a simple matter.
Perhaps they should give it a try sometime. Coming up with a reasonable
Ruby indentation definition took me two weeks of hard work and heavy
thinking. Neither Ruby nor Vim is very friendly to do this kind of
stuff for. Another deterrent thing is that people complain when it
doesn't work but keep very quiet when it does,
        nikolai

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

gsinclair@gmail.com wrote:

The following code indents properly and is what I use.

  a =
    case b
    when 1: 10
    when 2: 20
    else 50
    end

The reason that this works and the other form doesn’t is that in this
instance the indentation code sees the = at the end of a line so it
indents one level. Then, the case is seen at the start of the next
line, so it acts like it would without being part of an assignment.
It’ll be quite difficult to fix this properly, but I’ll try.

Thanks for the kind words,
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Sam Roberts wrote:

Quoting gsinclair@gmail.com, on Tue, May 24, 2005 at 08:30:17AM

+0900:

> To follow up Vincent's comments: to try your hand at this, there's

no

> shortcut; just read the Vim help files on indenting and general Vim
> programming (it's fugly), and hack around with the existing
> highlighting code. I don't understand it myself. Indenting Ruby

is

> Hard with a capital H. Writing the logic in the 10th-rate

programming

> language that is VimScript (or whatever they call it) is insane,

but

> Nikolai has done a great job.

I wonder whether using Syntax, based on the ruby parser, would allow

an

external tool to be written (in ruby...) that would do better. Down

side

is it wouldn't indent as you type, upside is you could set indentprg,
and run the whole file through it.

I've proposed a few times that someone write an external indenting tool
in Ruby, but no-one's done it, or even tried, AFAIK. Two upsides that
you didn't mention: once it's (nearly) perfect, it can be translated
into any editor-specific language; and you could use Vim's
embedded-Ruby capability to actually use the Ruby code to indent as you
type.

Getting the indenting logic right is the hard part, and we all that
requires using Ruby!

Cheers,
Gavin

Vincent Foley wrote:

Oh, don't get me wrong, I definitly appreciate what you did. I once
tried to modify the file, but VimScript is absolutely the worst
language I've ever seen, so kudos to you for doing it.

Thanks. It’s nice to hear that people like it more than what becomes
apparent from bug reports :-),
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Brian Schröder wrote:

> Brian Schröder wrote:
>
> > > > However, the myvar = case foo still breaks on the next line.
>
> > > I'll add support for this at a later time. Until then, consider
> > > rethinking writing code that uses the case statement in this manner,
>
> > I like this kind of code.
>
> > a = case b
> > when 1: 10
> > when 2: 20
> > else 50
> > end
>
> > makes it clear that something is assigned to a.
>
> Sure, but tell me a reasonable way to indent it and provide me with the
> code to do it and I'll add it immediately. Adding something like this
> will require changes that will ripple through the whole indentation
> code. People seem to think that indentation is a simple matter.
> Perhaps they should give it a try sometime. Coming up with a reasonable
> Ruby indentation definition took me two weeks of hard work and heavy
> thinking. Neither Ruby nor Vim is very friendly to do this kind of
> stuff for. Another deterrent thing is that people complain when it
> doesn't work but keep very quiet when it does,

Sorry Nikolai, I really appreciate your work. It was just that you
proposed changing the code, and I wanted to say that I like this
idiom.

Thanks. I agree that this kind of thing should work properly. Ruby’s
rather flexible syntax is, however, a very serious issue when trying to
write a simple enough indentation engine for it.

I’ll add this to the list of things that need to be done, but as I have
very little time to spare at the moment, it may take some time before
it’ll be added,
        nikolai

···

On 24/05/05, Nikolai Weibull > <mailing-lists.ruby-talk@rawuncut.elitemail.org> wrote:

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Sam Roberts wrote:

Quoting gsinclair@gmail.com, on Tue, May 24, 2005 at 08:30:17AM +0900:

> To follow up Vincent's comments: to try your hand at this, there's
> no shortcut; just read the Vim help files on indenting and general
> Vim programming (it's fugly), and hack around with the existing
> highlighting code. I don't understand it myself. Indenting Ruby is
> Hard with a capital H. Writing the logic in the 10th-rate
> programming language that is VimScript (or whatever they call it) is
> insane, but Nikolai has done a great job.

I wonder whether using Syntax, based on the ruby parser, would allow an
external tool to be written (in ruby...) that would do better. Down side
is it wouldn't indent as you type, upside is you could set indentprg,
and run the whole file through it.

This has been an idea of mine for some time, but I haven’t had time to
try to implement it. It’d be nice to have something like this, but it
probably requires a lot of work.

Nikolai has performed miracles, but it almost seems like an excercise in
coding in Brainfuck, or some similar language.

Thanks. The main problem is that Vim lacks some tools (i.e., functions
and such) that’d make this kind of stuff a lot easier to do. EMACS is
a lot friendly in this regard,
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}