How to adopt "Python Style" indentation for Ruby

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.blogspot.com
Portfolio: http://www.gilesgoatboy.org

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.

···

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.

Giles Bowkett wrote:

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.

Another version of pyrb.rb has been written that allows proper
multilevel dedenting and removes the requirement for a separate
.pyrb file

You can now do in test.rb

···

#####################################
require 'pyrb.rb'
__END__

def foo:
     [1,2,3,4].each do |i|:
         puts i
         [1,2,3,4].each do |j|:
             puts i
         if i == 2 :
             puts "foo"
         else:
             puts "bar"

foo
#####################################

http://xtargets.com/snippets/posts/show/68

Disclaimer : The above library in no way whatsoever should be taken as a suggestion that the author thinks Python is better than Ruby or
vice versa. All suggestions to that effect are purely fictional and
the author is in no way responsible for flame wars that may ensue
from use or misuse of the library. The author wrote the library
because it could be done and for no other reason.

--
Brad Phelan
http://xtargets.com

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

···

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?" -

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

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.

···

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.

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.blogspot.com
Portfolio: http://www.gilesgoatboy.org

> 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

Another version of pyrb.rb has been written that allows proper
multilevel dedenting and removes the requirement for a separate
.pyrb file

This is absurdly cool. How does it work?

Oh I get it:

The trick to the new version is to use the __END__ keyword
to block the Ruby scanner and then reload the current file after
doing the preprocessing.

That's awesome! Sick and wrong in the best possible way. And **simple!**

···

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org

It is already written

http://lazibi.rubyforge.org/

···

Dnia 29-05-2007 o 18:50:16 Brad Phelan <bradphelan@xtargets.com> napisał(a):

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?

--
Jarosław Zabiełło
http://blog.zabiello.com

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://xtargets.com/snippets/posts/show/68

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://xtargets.com

This is absurdly cool. How does it work?

Oh I get it:

The trick to the new version is to use the __END__ keyword
to block the Ruby scanner and then reload the current file after
doing the preprocessing.

That's awesome! Sick and wrong in the best possible way. And **simple!**

Sick, wrong and simple but unfortunately not my idea. There is a library hanging around called hyphen-ruby which showed me the dark path.

B

···

--
Brad Phelan
http://xtargets.com/snippets

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.blogspot.com
Portfolio: http://www.gilesgoatboy.org

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.

···

On 5/21/07, Brad Phelan <phelan@tttech.ttt> wrote:

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

http://xtargets.com/snippets/posts/show/68

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.

Actually you can do this without even using the __END__. pyrb.rb can
exit the process so it will never reach the rest of the original file.

T.

···

On May 29, 3:50 pm, Brad Phelan <bradphe...@xtargets.com> wrote:

> This is absurdly cool. How does it work?

> Oh I get it:

>> The trick to the new version is to use the __END__ keyword
>> to block the Ruby scanner and then reload the current file after
>> doing the preprocessing.

> That's awesome! Sick and wrong in the best possible way. And **simple!**

Sick, wrong and simple but unfortunately not my idea. There is a library
hanging around called hyphen-ruby which showed me the dark path.

B

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.

···

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.blogspot.com
Portfolio:http://www.gilesgoatboy.org

Eric Mahurin wrote:

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

http://xtargets.com/snippets/posts/show/68

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 :

···

On 5/21/07, Brad Phelan <phelan@tttech.ttt> wrote:

--
Brad Phelan
http://xtargets.com

But then again, why bother? Just make a new executable called
'pyruby'. And use that to run your .pyrb scripts.

T.

···

On May 29, 7:37 pm, Trans <transf...@gmail.com> wrote:

Actually you can do this without even using the __END__. pyrb.rb can
exit the process so it will never reach the rest of the original file.

Trans wrote:

This is absurdly cool. How does it work?
Oh I get it:

The trick to the new version is to use the __END__ keyword
to block the Ruby scanner and then reload the current file after
doing the preprocessing.

That's awesome! Sick and wrong in the best possible way. And **simple!**

Sick, wrong and simple but unfortunately not my idea. There is a library
hanging around called hyphen-ruby which showed me the dark path.

B

Actually you can do this without even using the __END__. pyrb.rb can
exit the process so it will never reach the rest of the original file.

T.

I don't think that will work. I believe that Ruby will syntax check the entire file before trying to execute any of it.

···

On May 29, 3:50 pm, Brad Phelan <bradphe...@xtargets.com> wrote:

--
Brad Phelan
http://xtargets.com

:: 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 ||".

···

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 :

Ah, right. Did something like this myself once but I had overlooked
the fact that my variant code still passed for valid ruby. In any
case, using a separate 'pyruby' runner would be the best way
regardless.

T.

···

On May 30, 1:00 am, Brad Phelan <bradphe...@xtargets.com> wrote:

> Actually you can do this without even using the __END__. pyrb.rb can
> exit the process so it will never reach the rest of the original file.

> T.

I don't think that will work. I believe that Ruby will syntax check the
entire file before trying to execute any of it.

Why do I get the impression that this thread is trying to develop a
new language called FrankenRuPy? <G>

···

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/