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
pyruby.rb
( updated 29/05/2007 )
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 )