[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to adopt "Python Style" indentation for Ruby

Giles Bowkett

5/21/2007 6:53:00 AM

Obviously based on the earlier thread. I think this is actually an
utterly terrible idea. Haven't you heard that song by Loverboy? "Pig
and elephant DNA just don't mix"? But I think the **implementation**
would be fascinating.

What would it take to write a Ruby pre-processor which parsed Ruby
written in a Pythonic style and turned it into actual valid Ruby? Or
even a Ruby library like Xavier's Perl example, which allows you to
code Ruby as if it were Python after just requiring the library? The
original post's main argument was that indentation is a stable,
consistent shorthand for Ruby's end statements. If all you're looking
to do is use tabs as syntactic sugar, then it should be pretty easy to
just write something which knows how to translate a sequence of tabs
in and tabs out into a series of end statements at the end.

Is this only doable in Perl, because Perl has source filtering? Would
you have to encase the Pythonic "Ruby" in a string and then run that
string through a processor after the fact, or could it "just work"
without any obvious prep on the user's part? If you did it as a
string, it should be as easy as counting tabs. But source filtering,
that sounds like the better way.

--
Giles Bowkett

I'm running a time management experiment: I'm only checking e-mail
twice per day, at 11am and 5pm. If you need to get in touch quicker
than that, call me on my cell.

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...

36 Answers

Brian Candler

5/21/2007 7:33:00 AM

0

On Mon, May 21, 2007 at 03:53:25PM +0900, Giles Bowkett wrote:
> What would it take to write a Ruby pre-processor which parsed Ruby
> written in a Pythonic style and turned it into actual valid Ruby? Or
> even a Ruby library like Xavier's Perl example, which allows you to
> code Ruby as if it were Python after just requiring the library? The
> original post's main argument was that indentation is a stable,
> consistent shorthand for Ruby's end statements. If all you're looking
> to do is use tabs as syntactic sugar, then it should be pretty easy to
> just write something which knows how to translate a sequence of tabs
> in and tabs out into a series of end statements at the end.

Actually, I'd happily settle for something simpler: a pretty-printer which
just reads (normal) Ruby and re-outputs it with standard indentation.

This would immediately solve the problem of "where did I miss out an 'end'
statement?" - you'd just pipe it into this utility and inspect. In the past
I've had to resort to binary chops to solve this: copy source.rb to x.rb and
remove chunks of method definitions until I find the offending one. This is
painful.

As an alternative: the existing Ruby parser could be modified to spit out a
warning whenever it sees non-standard nesting, e.g. "end at line <x> doesn't
align with start of block/method at line <y>". It only need do this for an
'end' which is at the start of a line.

Regards,

Brian.

Rick DeNatale

5/21/2007 11:47:00 AM

0

On 5/21/07, Brian Candler <B.Candler@pobox.com> wrote:
> On Mon, May 21, 2007 at 03:53:25PM +0900, Giles Bowkett wrote:
> > What would it take to write a Ruby pre-processor which parsed Ruby
> > written in a Pythonic style and turned it into actual valid Ruby?

> Actually, I'd happily settle for something simpler: a pretty-printer which
> just reads (normal) Ruby and re-outputs it with standard indentation.
>
> This would immediately solve the problem of "where did I miss out an 'end'
> statement?" -

In vim, I find that ggVG= does that job well enough.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Bernard Kenik

5/21/2007 3:39:00 PM

0

On May 21, 3:32 am, Brian Candler <B.Cand...@pobox.com> wrote:
> On Mon, May 21, 2007 at 03:53:25PM +0900, Giles Bowkett wrote:
> > What would it take to write a Ruby pre-processor which parsed Ruby
> > written in a Pythonic style and turned it into actual valid Ruby? Or
> > even a Ruby library like Xavier's Perl example, which allows you to
> > code Ruby as if it were Python after just requiring the library? The
> > original post's main argument was that indentation is a stable,
> > consistent shorthand for Ruby's end statements. If all you're looking
> > to do is use tabs as syntactic sugar, then it should be pretty easy to
> > just write something which knows how to translate a sequence of tabs
> > in and tabs out into a series of end statements at the end.
>
> Actually, I'd happily settle for something simpler: a pretty-printer which
> just reads (normal) Ruby and re-outputs it with standard indentation.
>
> This would immediately solve the problem of "where did I miss out an 'end'
> statement?" - you'd just pipe it into this utility and inspect. In the past
> I've had to resort to binary chops to solve this: copy source.rb to x.rb and
> remove chunks of method definitions until I find the offending one. This is
> painful.
>
> As an alternative: the existing Ruby parser could be modified to spit out a
> warning whenever it sees non-standard nesting, e.g. "end at line <x> doesn't
> align with start of block/method at line <y>". It only need do this for an
> 'end' which is at the start of a line.
>
> Regards,
>
> Brian.

I use Arachono Ruby IDE. Its editor has a feature whereby I can select
a number of lines to comment out or uncomment the lines. This makes
finding the missing end fairly easier.

I find python indentation much harder to read. For my use, I rather
stick with the "end"s.

Brad Phelan

5/21/2007 3:50:00 PM

0

bbiker wrote:
> On May 21, 3:32 am, Brian Candler <B.Cand...@pobox.com> wrote:
>> On Mon, May 21, 2007 at 03:53:25PM +0900, Giles Bowkett wrote:
>>> What would it take to write a Ruby pre-processor which parsed Ruby
>>> written in a Pythonic style and turned it into actual valid Ruby? Or
>>> even a Ruby library like Xavier's Perl example, which allows you to
>>> code Ruby as if it were Python after just requiring the library? The
>>> original post's main argument was that indentation is a stable,
>>> consistent shorthand for Ruby's end statements. If all you're looking
>>> to do is use tabs as syntactic sugar, then it should be pretty easy to
>>> just write something which knows how to translate a sequence of tabs
>>> in and tabs out into a series of end statements at the end.
>> Actually, I'd happily settle for something simpler: a pretty-printer which
>> just reads (normal) Ruby and re-outputs it with standard indentation.
>>
>> This would immediately solve the problem of "where did I miss out an 'end'
>> statement?" - you'd just pipe it into this utility and inspect. In the past
>> I've had to resort to binary chops to solve this: copy source.rb to x.rb and
>> remove chunks of method definitions until I find the offending one. This is
>> painful.
>>
>> As an alternative: the existing Ruby parser could be modified to spit out a
>> warning whenever it sees non-standard nesting, e.g. "end at line <x> doesn't
>> align with start of block/method at line <y>". It only need do this for an
>> 'end' which is at the start of a line.
>>
>> Regards,
>>
>> Brian.
>
> I use Arachono Ruby IDE. Its editor has a feature whereby I can select
> a number of lines to comment out or uncomment the lines. This makes
> finding the missing end fairly easier.
>
> I find python indentation much harder to read. For my use, I rather
> stick with the "end"s.
>

I've tried posting several times without success ... here again.

http://xt.../snippets/pos...

shows a partial solution to your challenge by overloading require. It is
a quick hack but shows you how to write your own pre-processor. The
new require checks to find files of type .pyrb and then coverts them
to .rb files before loading them.

--
Brad Phelan
http://xt...

Giles Bowkett

5/21/2007 4:36:00 PM

0

> Actually, I'd happily settle for something simpler: a pretty-printer which
> just reads (normal) Ruby and re-outputs it with standard indentation.

This already exists, and was written by somebody on this list, but I'm
having a hard time googling it.

--
Giles Bowkett

I'm running a time management experiment: I'm only checking e-mail
twice per day, at 11am and 5pm. If you need to get in touch quicker
than that, call me on my cell.

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...

Giles Bowkett

5/21/2007 4:43:00 PM

0

> shows a partial solution to your challenge by overloading require. It is
> a quick hack but shows you how to write your own pre-processor. The
> new require checks to find files of type .pyrb and then coverts them
> to .rb files before loading them.

Neat! So all you do is write .pyrb files and you're good to go. And it
works basically by putting the tabs on a stack and using that to drive
the number of ends.

--
Giles Bowkett

I'm running a time management experiment: I'm only checking e-mail
twice per day, at 11am and 5pm. If you need to get in touch quicker
than that, call me on my cell.

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...

Eric Mahurin

5/21/2007 5:47:00 PM

0

On 5/21/07, Brad Phelan <phelan@tttech.ttt> wrote:
> I've tried posting several times without success ... here again.
>
> http://xtargets.com/snippets/pos...
>
> shows a partial solution to your challenge by overloading require. It is
> a quick hack but shows you how to write your own pre-processor. The
> new require checks to find files of type .pyrb and then coverts them
> to .rb files before loading them.

If you change this:

if l =~ /:\s*$/
stack.push indent
l.gsub! /:\s*$/,''
end

to this:

if l.sub!(/(\|[^\|]*\|)\s*:\s*$/,' do \1') or l.sub!(/:\s*$/,'')
stack.push indent
end

your example won't need the do's:

def foo:
[1,2,3,4].each |i|:
puts i
[1,2,3,4].each |i|:
puts i

Unfortunately, this isn't too easy to implement in a formal parser
though, since the "|" after each initially looks ambiguous with the
"|" operator. The ":" to start the indentation style block should
probaly be where the "do" or "{" used to. You could even get rid of
the || by using ":" to start the args and "\n" to end the args (you'd
need an exlicit * to mean don't care about the args):

def foo :
[1,2,3,4].each : i
puts i
[1,2,3,4].each : i
puts i

In this example, you get rid of 3 lines and 9 symbols/identifiers (and
add the 3 ":"s) compared to the original ruby.

All of these ":" solutions would have potential incompatibilities with
the ? : operator and :symbol.

bradphelan

5/21/2007 6:27:00 PM

0

On May 21, 6:42 pm, "Giles Bowkett" <gil...@gmail.com> wrote:
> > shows a partial solution to your challenge by overloading require. It is
> > a quick hack but shows you how to write your own pre-processor. The
> > new require checks to find files of type .pyrb and then coverts them
> > to .rb files before loading them.
>
> Neat! So all you do is write .pyrb files and you're good to go. And it
> works basically by putting the tabs on a stack and using that to drive
> the number of ends.
>
> --
> Giles Bowkett
>
> I'm running a time management experiment: I'm only checking e-mail
> twice per day, at 11am and 5pm. If you need to get in touch quicker
> than that, call me on my cell.
>
> Blog:http://gilesbowkett.bl...
> Portfolio:http://www.gilesg...

Google groups seems to be broken. My posts do not appear. Just seeing
if this gets throught. My other post was via a different news agent.

Brad Phelan

5/21/2007 6:42:00 PM

0

Eric Mahurin wrote:
> On 5/21/07, Brad Phelan <phelan@tttech.ttt> wrote:
>> I've tried posting several times without success ... here again.
>>
>> http://xt.../snippets/pos...
>>
>> shows a partial solution to your challenge by overloading require. It is
>> a quick hack but shows you how to write your own pre-processor. The
>> new require checks to find files of type .pyrb and then coverts them
>> to .rb files before loading them.
>
> If you change this:
>
> if l =~ /:\s*$/
> stack.push indent
> l.gsub! /:\s*$/,''
> end
>
> to this:
>
> if l.sub!(/(\|[^\|]*\|)\s*:\s*$/,' do \1') or
> l.sub!(/:\s*$/,'')
> stack.push indent
> end
>
> your example won't need the do's:
>
> def foo:
> [1,2,3,4].each |i|:
> puts i
> [1,2,3,4].each |i|:
> puts i
>
> Unfortunately, this isn't too easy to implement in a formal parser
> though, since the "|" after each initially looks ambiguous with the
> "|" operator. The ":" to start the indentation style block should
> probaly be where the "do" or "{" used to. You could even get rid of
> the || by using ":" to start the args and "\n" to end the args (you'd
> need an exlicit * to mean don't care about the args):
>
> def foo :
> [1,2,3,4].each : i
> puts i
> [1,2,3,4].each : i
> puts i
>
> In this example, you get rid of 3 lines and 9 symbols/identifiers (and
> add the 3 ":"s) compared to the original ruby.
>
> All of these ":" solutions would have potential incompatibilities with
> the ? : operator and :symbol.
>

I think I would prefer the leaving the 'do' in and keeping the rubish
syntax. It will avoid the potential for the conflicts that you describe.

though I do like the economy of

> def foo :
> [1,2,3,4].each : i
> puts i
> [1,2,3,4].each : i
> puts i

Perhapps another symbol other than :

--
Brad Phelan
http://xt...

Eric Mahurin

5/21/2007 7:59:00 PM

0

On 5/21/07, Brad Phelan <bradphelan@xtargets.com> wrote:
> though I do like the economy of
>
> > def foo :
> > [1,2,3,4].each : i
> > puts i
> > [1,2,3,4].each : i
> > puts i
>
> Perhaps another symbol other than :

:: could work. As long as it is not followed by an identifier
character it shouldn't collide. You could use this code for starting
the block:

if l.sub!(/::\s*$/,'') or l.sub!(/::\s+(.*)$/,' do |\1|')
stack.push indent
end

and then this should work:

def foo ::
[1,2,3,4].each :: i
puts i
[1,2,3,4].each :: i
puts i

With this code, to do the equivalent of do...end w/o args you'd need
an explicit do before the :: . This could be fixed in a real parser
since it would know whether the block is for a builtin
def/while/if/class statement versus a standard lambda block. In the
lambda block context maybe you'd want "::\n" to mean "do ||" and use
":: *\n" to mean "do |*|" (which is equivalent to a block without
args). Otherwise you couldn't get the equivalent of "do ||".