Python style Ruby.

Following from a thread on comp.lang.ruby I wondered what it would take to make Ruby more like Python. Yuk you say! Well probably but here is a start.

I updated the code after reading Giles Bowkett's" response to my post about needing the *.pyrb files. After a little poking around and finding hyphen-ruby I discovered a smarter way to do this.

I also made some other improvements to allow deeper dedenting. 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.

Also you only need the __END__ thingie in the first file that is loaded. All subsequent loads will do the preprocessing automatically.



test.pyrb

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




pyruby.rb

module PyRuby
    public


    def self.require(base_name)
        if $".include? base_name
            return false
        else
            file = find_file base_name
            if file
                load(file)
                $" << base_name
                return true
            end
        end
    end

    def self.load(file)
        if file
            txt = PyRuby.pyrb_convert file
            begin
                Object.module_eval txt, file, 1
            rescue SyntaxError => e
                $stderr.print "Preprocessing Fail: " + $!
                $stderr.print "-----------------------------------\n"
                $stderr.print txt
                raise
            end
            return true
        end
        false
    end

    def self.find_file(fname)
        if FileTest.exist?(fname)
            return fname
        else
            $:.each do |path|
                path = File.join(path, fname)
                for ext in [ '.rb' ] do
                    p = path + ext
                    return p if FileTest.exist?(p)
                end
            end
        end
    end

    def self.pyrb_convert file
        txt = ""
        stack = []
        found_pyrb_req = false
        do_preprocess = false

        File.open file do |fh|


            fh.each_line do |l|
                l.chomp!
                if l =~ /^require\s*'pyrb.rb'\s*$/
                    found_pyrb_req = true
                end
                if l =~ /^__END__\s*$/ && found_pyrb_req
                    do_preprocess = true
                    txt = ''
                elsif do_preprocess

                    # Do the indent preprocessing
                    indent = (l.gsub /\S.*/,'').length
                    stack.reverse.each do |pindent|
                        if indent <= pindent
                            case l.gsub /^\s*/,''
                            when /(else|end|rescue).*/
                            else
                                txt << (" " * pindent) + "end\n"
                            end
                            stack.pop
                        end
                    end
                    if l =~ /:\s*$/
                        stack.push indent
                        l.gsub! /:\s*$/,''
                    end
                    txt << l << "\n"


                else
                    # Treat the code as normal Ruby code
                    # and pass straight through.
                    txt << l << "\n"
                end
            end
        end
        if do_preprocess
            while not stack.empty?
                txt << (" " * stack.pop) + "end\n"
            end
        end
        txt
    end
end

alias __pyrb_load load

def load base_name
    PyRuby.load base_name
end

def require base_name
    PyRuby.require base_name
end

PyRuby.load $0



( updated 29/05/2007 )




Sponsored by

Sole Central

Your one stop shop for Birkenstock and Crocs shoes and sandles.