Skip to content

Instantly share code, notes, and snippets.

@gilliek
Last active August 29, 2015 13:58
Show Gist options
  • Save gilliek/9950754 to your computer and use it in GitHub Desktop.
Save gilliek/9950754 to your computer and use it in GitHub Desktop.
Simple (and not very robust) script that maps the View items of an Android activity layout to an Activity class.
#!/usr/bin/env ruby
=begin
_ ____ _
| | __ _ _ _|___ \ __ _ ___| |_
| |/ _` | | | | __) / _` |/ __| __|
| | (_| | |_| |/ __/ (_| | (__| |_
|_|\__,_|\__, |_____\__,_|\___|\__|
|___/
lay2act aims to be a very simple (and not very robust) script that maps the View
items of an Android activity layout to an Activity class. This script does not
fix imports, your IDE has to do it itself.
LICENSE
"THE BEER-WARE LICENSE" (Revision 42):
<[email protected]> wrote this file. As long as you retain
this notice you can do whatever you want with this stuff. If we meet some
day, and you think this stuff is worth it, you can buy me a beer in return
Kevin Gillieron
DEPENDENCIES
- ruby (it should work with any version of Ruby)
- nokogiri (gem install nokogiri)
USAGE
ruby lay2act ANDROID_LAYOUT ANDROID_ACTIVITY
where ANDROID_LAYOUT is the path to the Android layout file and
ANDROID_ACTIVITY is the path to the Android Activity class file.
=end
require 'nokogiri'
require 'fileutils'
class View
attr_reader :type, :id
def initialize(type="", id="")
@type = type
@id = id
end
end
class String
def to_camel
# http://stackoverflow.com/a/11411200/1061579
self.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
end
end
def parse_id(id="")
id.sub("@+id/", "")
end
def get_views(xml="")
doc = Nokogiri.XML(xml)
views = []
doc.traverse do |node|
id = node["android:id"]
next if id == nil
views << View.new(node.name, parse_id(id))
end
views
end
def fmt_attr(view)
"\tprivate #{view.type} #{view.id.to_camel};"
end
def gen_attrs(views)
views.inject([]){ |buffer, v| buffer << fmt_attr(v) }.sort.join("\n")
end
def fmt_assign(view)
"\t\tthis.#{view.id.to_camel} = (#{view.type}) this.findViewById(R.id.#{view.id});"
end
def gen_assign(views)
views.inject([]){ |buffer, v| buffer << fmt_assign(v) }.sort.join("\n")
end
def usage(status=1)
puts "usage: #{File.basename($0)} [ANDROID_LAYOUT] [ANDROID_ACTIVITY]"
exit status
end
begin
if ARGV.length == 1 && ["-h", "--help"].include?(ARGV[0])
usage(0)
# NOTREACHED
elsif ARGV.length != 2
STDERR.puts "Invalid # of arguments!"
usage
# NOTREACHED
end
layout = ARGV[0]
activity = ARGV[1]
xml = File.open(layout).readlines.join
views = get_views(xml)
tmpFilename = activity + ".tmp"
output = File.new(tmpFilename, "w")
begin
re = Regexp.new("(this\\.)setContentView\\(R\\.layout\\.#{File.basename(layout, ".xml")}\\);")
File.open(activity).readlines.each do |line|
output.puts(line)
if line =~ /^public class \w+Activity/i
output.puts(gen_attrs(views) + "\n\n")
elsif re.match(line)
output.puts("\n" + gen_assign(views))
end
end
ensure
output.close
end
FileUtils.mv(tmpFilename, activity)
end
# vim: set ts=2 sw=2 noet:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment