Skip to content

Instantly share code, notes, and snippets.

@kattrali
Forked from andreif/bridge.rb
Created May 8, 2012 22:26

Revisions

  1. @andreif andreif created this gist May 8, 2012.
    110 changes: 110 additions & 0 deletions bridge.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@
    require "hpricot"
    require "fileutils"

    module BridgeSupport
    class Parser
    def initialize(path_from, path_to)
    @doc = open(path_from) {|f| Hpricot(f).search('signatures').first}
    if @doc and @doc.children
    FileUtils.mkdir_p File.dirname(path_to)
    o = open(path_to, 'w')
    o.write(@doc.children.collect do |el|
    next if el.is_a?(Hpricot::Text)
    case el.name
    when 'class' then ClassDef.new(el).write('%s/%s.rb' % [File.dirname(path_to),el.attributes['name']])
    when 'function' then FunctionDef.new(el).to_s
    when 'enum' then ConstantDef.new(el).to_s
    else BaseDef.new(el).to_s
    end
    end.compact.join("\n\n"))
    o.close
    end
    end
    end
    class BaseDef
    def initialize(el)
    @el = el
    end
    def to_s
    '# ' + @el.to_s.gsub("\n","\n# ")
    end
    def attr(key)
    @el.attributes[key]
    end
    def indent(str, n=2)
    n = ' '*n if n.is_a? Fixnum
    str = str.join("\n\n") if str.is_a? Array
    n + str.gsub("\n", "\n"+n)
    end
    end
    class ClassDef < BaseDef
    def to_s
    "class %s < NSObject\n%s\n\n%s\nend" % [attr('name'), indent(methods_def), indent(super)]
    end
    def methods_def
    @el.children.collect do |c|
    if c.name == 'method'
    BridgeSupport::MethodDef.new(c).to_s
    end
    end.compact
    end
    def write(path)
    FileUtils.mkdir_p(File.dirname(path))
    open(path,'w') {|f| f.write(to_s)}
    end
    end
    class FunctionDef < BaseDef
    def retval
    r = @el.search('retval').first
    "%s [ %s ]" % [r.attributes['declared_type'], r.attributes['type']]
    end
    def to_s
    "def %s(%s) # => %s\n%s\nend" % [name, args.join(', '), retval, indent(super)]
    end
    def name
    attr('name')
    end
    def args
    @el.children.collect do |c|
    c.attributes['name'] if c.name == 'arg'
    end.compact
    end
    end
    class MethodDef < FunctionDef
    def to_s
    arg = args.join(', ')
    "def self.#{name}(#{arg}) end\n%s" % super
    end
    def messages
    attr('selector')[0..-1].split(':')
    end
    def name
    messages.first
    end
    def args
    msg = messages
    arg = @el.children.collect do |c|
    c.attributes['name'] if c.name == 'arg'
    end.compact
    arg.collect.with_index do |a,i|
    if i > 0 and msg and msg[i]
    "%s:%s" % [msg[i], a]
    else
    a
    end
    end
    end
    end
    class ConstantDef < BaseDef
    def to_s
    "%s = %s\n%s" % [attr('name'), attr('value'), super]
    end
    end
    end

    source_dir = '/Library/RubyMotion/data/5.1/BridgeSupport'
    destination_dir = '/Users/andrei/DropboxAndrei/Dropbox/Projects/iOS/BridgeSupport'
    Dir[source_dir + '/*.bridgesupport'].each do |f|
    p f
    BridgeSupport::Parser.new(f, destination_dir + '/%s/framework.rb' % File.basename(f,'.bridgesupport'))
    end