rucola 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +628 -0
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +106 -0
- data/README.txt +126 -0
- data/Rakefile +32 -0
- data/TODO +28 -0
- data/app_generators/rucola/USAGE +6 -0
- data/app_generators/rucola/rucola_generator.rb +112 -0
- data/app_generators/rucola/templates/Rakefile.erb +12 -0
- data/app_generators/rucola/templates/Rakefile.erb.old +156 -0
- data/app_generators/rucola/templates/app/controllers/application_controller.rb +22 -0
- data/app_generators/rucola/templates/config/Info.plist.erb +28 -0
- data/app_generators/rucola/templates/config/boot.rb +2 -0
- data/app_generators/rucola/templates/config/environment.rb +11 -0
- data/app_generators/rucola/templates/config/environments/debug.rb +3 -0
- data/app_generators/rucola/templates/config/environments/release.rb +3 -0
- data/app_generators/rucola/templates/config/environments/test.rb +3 -0
- data/app_generators/rucola/templates/config/ib_external_class_defs.yml +13 -0
- data/app_generators/rucola/templates/misc/English.lproj/InfoPlist.strings.erb +3 -0
- data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/classes.nib +40 -0
- data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/info.nib +18 -0
- data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/keyedobjects.nib +0 -0
- data/app_generators/rucola/templates/misc/main.m.erb +15 -0
- data/app_generators/rucola/templates/misc/rb_main.rb.erb +13 -0
- data/app_generators/rucola/templates/project.pbxproj.erb +299 -0
- data/app_generators/rucola/templates/script/plugin +84 -0
- data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +10 -0
- data/app_generators/rucola/templates/test/test_helper.rb +10 -0
- data/bin/rucola +12 -0
- data/config/hoe.rb +71 -0
- data/config/requirements.rb +17 -0
- data/lib/rucola.rb +3 -0
- data/lib/rucola/info_plist.rb +37 -0
- data/lib/rucola/initializer.rb +313 -0
- data/lib/rucola/nib.rb +99 -0
- data/lib/rucola/rucola_support.rb +9 -0
- data/lib/rucola/rucola_support/controllers.rb +2 -0
- data/lib/rucola/rucola_support/controllers/rc_controller.rb +7 -0
- data/lib/rucola/rucola_support/controllers/rc_window_controller.rb +12 -0
- data/lib/rucola/rucola_support/core_ext.rb +2 -0
- data/lib/rucola/rucola_support/core_ext/objc.rb +4 -0
- data/lib/rucola/rucola_support/core_ext/objc/nsobject.rb +22 -0
- data/lib/rucola/rucola_support/core_ext/ruby.rb +4 -0
- data/lib/rucola/rucola_support/core_ext/ruby/string.rb +21 -0
- data/lib/rucola/rucola_support/initialize_hooks.rb +21 -0
- data/lib/rucola/rucola_support/models.rb +1 -0
- data/lib/rucola/rucola_support/models/rc_document.rb +10 -0
- data/lib/rucola/rucola_support/notifications.rb +1 -0
- data/lib/rucola/rucola_support/notifications/notifications.rb +146 -0
- data/lib/rucola/rucola_support/rc_app.rb +101 -0
- data/lib/rucola/tasks/freeze.rake +44 -0
- data/lib/rucola/tasks/interface_builder.rake +80 -0
- data/lib/rucola/tasks/main.rake +29 -0
- data/lib/rucola/tasks/xcode.rake +43 -0
- data/lib/rucola/test_helper.rb +57 -0
- data/lib/rucola/version.rb +9 -0
- data/lib/rucola/xcode.rb +148 -0
- data/log/debug.log +0 -0
- data/rucola_generators/controller/USAGE +5 -0
- data/rucola_generators/controller/controller_generator.rb +84 -0
- data/rucola_generators/controller/templates/controller_template.rb.erb +5 -0
- data/rucola_generators/controller/templates/test_controller_template.rb.erb +10 -0
- data/rucola_generators/document_model/USAGE +5 -0
- data/rucola_generators/document_model/document_model_generator.rb +67 -0
- data/rucola_generators/document_model/templates/document_model_template.rb.erb +27 -0
- data/rucola_generators/document_model/templates/test_document_model_template.rb.erb +10 -0
- data/rucola_generators/window_controller/USAGE +6 -0
- data/rucola_generators/window_controller/templates/Window.nib/classes.nib.erb +35 -0
- data/rucola_generators/window_controller/templates/Window.nib/info.nib +16 -0
- data/rucola_generators/window_controller/templates/Window.nib/keyedobjects.nib +0 -0
- data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +10 -0
- data/rucola_generators/window_controller/templates/window_controller_template.rb.erb +19 -0
- data/rucola_generators/window_controller/window_controller_generator.rb +74 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +27 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/fixtures/Info.plist +28 -0
- data/test/fixtures/MainMenu.nib/classes.nib +32 -0
- data/test/fixtures/MainMenu.nib/info.nib +18 -0
- data/test/fixtures/MainMenu.nib/keyedobjects.nib +0 -0
- data/test/test_controller_generator.rb +75 -0
- data/test/test_core_ext.rb +15 -0
- data/test/test_document_model_generator.rb +64 -0
- data/test/test_generator_helper.rb +20 -0
- data/test/test_helper.rb +13 -0
- data/test/test_info_plist.rb +31 -0
- data/test/test_nib.rb +73 -0
- data/test/test_notifications.rb +75 -0
- data/test/test_objc_core_ext.rb +37 -0
- data/test/test_rc_app.rb +63 -0
- data/test/test_rc_document.rb +18 -0
- data/test/test_rc_window_controller.rb +13 -0
- data/test/test_rucola.rb +11 -0
- data/test/test_rucola_generator.rb +87 -0
- data/test/test_window_controller_generator.rb +50 -0
- data/test/test_xcode.rb +128 -0
- data/website/index.html +199 -0
- data/website/index.txt +126 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.rhtml +48 -0
- metadata +189 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
namespace :rc do
|
2
|
+
|
3
|
+
namespace :freeze do
|
4
|
+
|
5
|
+
RUBYCOCOA_FRAMEWORK_PATH_CURRENT = 'vendor/rubycocoa'
|
6
|
+
desc "Freezes the current used version of RubyCocoa in #{RUBYCOCOA_FRAMEWORK}"
|
7
|
+
task :current do
|
8
|
+
mkdir_p RUBYCOCOA_FRAMEWORK_PATH_CURRENT unless File.exist? RUBYCOCOA_FRAMEWORK_PATH_CURRENT
|
9
|
+
puts "Copying framework."
|
10
|
+
cp_r RUBYCOCOA_FRAMEWORK, RUBYCOCOA_FRAMEWORK_PATH_CURRENT
|
11
|
+
# add the new RubyCocoa framework to the project and bundle it when building the application
|
12
|
+
Rake::Task['rc:freeze:bundle'].invoke
|
13
|
+
end
|
14
|
+
|
15
|
+
RUBYCOCOA_FRAMEWORK_PATH_EDGE = 'vendor/rubycocoa/framework/build/Default'
|
16
|
+
desc 'Freezes the current edge version of RubyCocoa'
|
17
|
+
task :edge do
|
18
|
+
if File.exist? 'vendor/rubycocoa'
|
19
|
+
sh 'cd vendor/rubycocoa && svn up'
|
20
|
+
else
|
21
|
+
mkdir 'vendor' unless File.exist? 'vendor'
|
22
|
+
sh 'cd vendor && svn co https://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/trunk/src rubycocoa'
|
23
|
+
end
|
24
|
+
sh 'cd vendor/rubycocoa && rake'
|
25
|
+
|
26
|
+
# add the new RubyCocoa framework to the project and bundle it when building the application
|
27
|
+
Rake::Task['rc:freeze:bundle'].invoke
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Bundle the frozen RubyCocoa framework with the application'
|
31
|
+
task :bundle do
|
32
|
+
if File.exist? RUBYCOCOA_FRAMEWORK_PATH_EDGE
|
33
|
+
framework_location = RUBYCOCOA_FRAMEWORK_PATH_EDGE
|
34
|
+
else
|
35
|
+
framework_location = RUBYCOCOA_FRAMEWORK_PATH_CURRENT
|
36
|
+
end
|
37
|
+
project = Rucola::Xcode.new File.join(SOURCE_ROOT, "#{APPNAME}.xcodeproj")
|
38
|
+
project.change_rubycocoa_framework_location "#{framework_location}/RubyCocoa.framework"
|
39
|
+
project.bundle_rubycocoa_framework
|
40
|
+
project.save
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
namespace :ib do
|
4
|
+
RB_NIB_TOOL = "#{RUBYCOCOA_FRAMEWORK}/Versions/Current/Tools/rb_nibtool.rb"
|
5
|
+
|
6
|
+
def helper_file
|
7
|
+
"/tmp/#{APPNAME}_helper.rb.tmp"
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_tmp_helper_file
|
11
|
+
# get all the Rucola controller class definition files
|
12
|
+
class_defs = FileList["#{File.expand_path('../../rucola_support/controllers', __FILE__)}/*.rb"]
|
13
|
+
|
14
|
+
# get the optional ib_external_class_defs.yml file in which a user can specify any other
|
15
|
+
# classes that might need to be incuded for IB to recognize them.
|
16
|
+
user_class_def_string = ''
|
17
|
+
user_class_def_file = File.join(SOURCE_ROOT, 'config/ib_external_class_defs.yml')
|
18
|
+
user_class_defs = YAML.load_file(user_class_def_file)
|
19
|
+
if user_class_defs
|
20
|
+
user_class_def_string = create_class_stubs(user_class_defs)
|
21
|
+
end
|
22
|
+
|
23
|
+
# write the Rucola controllers and the optional ib_external_class_defs.yml to a tmp file
|
24
|
+
File.open(helper_file, 'w') do |file|
|
25
|
+
file.write class_defs.map{ |class_def| File.read(class_def) }.join("\n\n") << user_class_def_string
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_class_stubs(klasses, prev_super = '')
|
30
|
+
class_defs = ''
|
31
|
+
klasses.each do |klass, subklass|
|
32
|
+
unless prev_super == ''
|
33
|
+
class_defs += "class #{klass} < #{prev_super}; end\n"
|
34
|
+
end
|
35
|
+
if subklass.is_a?(Array)
|
36
|
+
subklass.each do |sub|
|
37
|
+
if sub.is_a?(Hash)
|
38
|
+
create_class_stubs(sub, klass)
|
39
|
+
else
|
40
|
+
class_defs += "class #{sub} < #{klass}; end\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return class_defs
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_tmp_controller_file(controller_name)
|
49
|
+
tmp_file = "/tmp/#{controller_name.snake_case}.rb.tmp"
|
50
|
+
File.open(tmp_file, 'w') do |file|
|
51
|
+
file.write( File.read(helper_file) + "\n\n" + File.read("app/controllers/#{controller_name.snake_case}.rb") )
|
52
|
+
end
|
53
|
+
tmp_file
|
54
|
+
end
|
55
|
+
|
56
|
+
def name_for_controller(controller_path)
|
57
|
+
File.basename(controller_path)[0..-4].camel_case
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'Updates the nibs from their corresponding ruby source files'
|
61
|
+
task :update do
|
62
|
+
create_tmp_helper_file
|
63
|
+
|
64
|
+
controllers = FileList["#{SOURCE_ROOT}/app/controllers/*.rb"]
|
65
|
+
nibs = FileList["#{SOURCE_ROOT}/app/views/*.nib", "#{SOURCE_ROOT}/misc/English.lproj/MainMenu.nib"].reject {|file| File.extname(file) != '.nib' or file.include? '~' }
|
66
|
+
|
67
|
+
controllers.each do |controller_path|
|
68
|
+
controller_name = name_for_controller(controller_path)
|
69
|
+
nibs.each do |nib|
|
70
|
+
if Rucola::Nib::Classes.open("#{nib}/classes.nib").has_class? controller_name
|
71
|
+
@tmp_file ||= create_tmp_controller_file(controller_name)
|
72
|
+
puts " update #{nib[(SOURCE_ROOT.length + 1)..-1]}: #{controller_name}"
|
73
|
+
`ruby #{RB_NIB_TOOL} --update --nib #{nib} --file #{@tmp_file}`
|
74
|
+
end
|
75
|
+
end
|
76
|
+
@tmp_file = nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
require 'osx/cocoa'
|
4
|
+
require 'rucola/xcode'
|
5
|
+
require 'rucola/nib'
|
6
|
+
require 'rucola/rucola_support'
|
7
|
+
|
8
|
+
# set the env, default to debug if we are running a rake task.
|
9
|
+
RUBYCOCOA_ENV = ENV['RUBYCOCOA_ENV'].nil? ? 'debug' : ENV['RUBYCOCOA_ENV']
|
10
|
+
RUBYCOCOA_ROOT = ENV['RUBYCOCOA_ROOT'].nil? ? SOURCE_ROOT : ENV['RUBYCOCOA_ROOT']
|
11
|
+
puts "RUNNING IN MODE: #{RUBYCOCOA_ENV.upcase}\n\n"
|
12
|
+
|
13
|
+
# FIXME: We also need to check if the user uses a frozen rc framework
|
14
|
+
RUBYCOCOA_FRAMEWORK = OSX::NSBundle.bundleWithIdentifier('com.apple.rubycocoa').bundlePath.to_s
|
15
|
+
|
16
|
+
# TASKS
|
17
|
+
|
18
|
+
# Get all the tasks
|
19
|
+
Dir["#{File.dirname(__FILE__)}/*.rake"].each {|file| load file unless File.basename(file) == 'main.rake' }
|
20
|
+
|
21
|
+
task :default => 'xcode:build'
|
22
|
+
|
23
|
+
desc 'Runs all the clean tasks'
|
24
|
+
task :clean => 'xcode:clean'
|
25
|
+
|
26
|
+
Rake::TestTask.new do |t|
|
27
|
+
t.test_files = FileList['test/*/test_*.rb']
|
28
|
+
t.verbose = true
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
namespace :xcode do
|
2
|
+
|
3
|
+
def config
|
4
|
+
RUBYCOCOA_ENV.capitalize
|
5
|
+
end
|
6
|
+
|
7
|
+
def build_dir
|
8
|
+
# get the users build dir
|
9
|
+
prefs = OSX::NSUserDefaults.standardUserDefaults
|
10
|
+
prefs.addSuiteNamed 'com.apple.xcode'
|
11
|
+
prefs['PBXApplicationwideBuildSettings']['SYMROOT'] || './build'
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_root
|
15
|
+
File.expand_path("#{build_dir}/#{config}/#{TARGET}")
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Builds the application'
|
19
|
+
task :build do
|
20
|
+
executable = "#{build_root}/Contents/MacOS/#{APPNAME}"
|
21
|
+
|
22
|
+
unless File.exists?(executable)
|
23
|
+
sh "xcodebuild -configuration #{config}"
|
24
|
+
else
|
25
|
+
puts "Build already exists, skipping. (Use clean if you really really want a new build.)\n\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Make sure the app is brought to the front once launched.
|
29
|
+
Thread.new do
|
30
|
+
sleep 0.025 until OSX::NSWorkspace.sharedWorkspace.launchedApplications.any? {|dict| dict['NSApplicationName'] == APPNAME }
|
31
|
+
`osascript -e 'tell application "#{executable}" to activate'`
|
32
|
+
end
|
33
|
+
|
34
|
+
# launch app with the correct env set
|
35
|
+
sh "RUBYCOCOA_ENV='#{RUBYCOCOA_ENV}' RUBYCOCOA_ROOT='#{RUBYCOCOA_ROOT}' #{executable}"
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Removes the build'
|
39
|
+
task :clean do
|
40
|
+
puts "Removing #{build_root}"
|
41
|
+
FileUtils.rm_rf build_root
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'osx/cocoa'
|
2
|
+
|
3
|
+
module OSX
|
4
|
+
# Allows methods to be overriden with a different arity.
|
5
|
+
#
|
6
|
+
# TODO: Check with Laurent if this is bad?
|
7
|
+
# Otherwise we should maybe override the stub method to set this to true
|
8
|
+
# when the object is a subclass of OSX::NSObject and set it to false again after the stubbing.
|
9
|
+
def self._ignore_ns_override; true; end
|
10
|
+
|
11
|
+
class NSObject
|
12
|
+
# A Mocha helper method which allows to stub alloc.init and return a mock.
|
13
|
+
#
|
14
|
+
# it "should init and return an instance" do
|
15
|
+
# obj_mock = mock("NSObject mock")
|
16
|
+
# OSX::NSObject.expects_alloc_init_returns(obj_mock) # performs 2 assertions
|
17
|
+
# OSX::NSObject.alloc.init.should == obj_mock
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Results in:
|
21
|
+
# 1 tests, 3 assertions, 0 failures, 0 errors
|
22
|
+
def self.expects_alloc_init_returns(mock)
|
23
|
+
mock.expects(:init).returns(mock)
|
24
|
+
self.expects(:alloc).returns(mock)
|
25
|
+
end
|
26
|
+
|
27
|
+
# A Mocha helper method which allocs an instance, yields it and then calls init.
|
28
|
+
#
|
29
|
+
# class Monkey < OSX::NSObject
|
30
|
+
# def init
|
31
|
+
# if super_init
|
32
|
+
# self.foo
|
33
|
+
# self.bar
|
34
|
+
# return self
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# it "should alloc, yield and return an instance" do
|
40
|
+
# obj = OSX::Monkey.during_init do |instance|
|
41
|
+
# instance.expects(:foo)
|
42
|
+
# instance.expects(:bar)
|
43
|
+
# end
|
44
|
+
# p obj # => #<Monkey:0x1a7566 class='Monkey' id=0x1b30a70>
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# Results in:
|
48
|
+
# 1 tests, 2 assertions, 0 failures, 0 errors
|
49
|
+
def self.during_init(&block)
|
50
|
+
obj = self.alloc
|
51
|
+
yield obj
|
52
|
+
res = obj.init
|
53
|
+
warn " warning: #{self.class.name}#init did not return an instance." if res.nil?
|
54
|
+
res
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/rucola/xcode.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'osx/cocoa'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module Rucola
|
5
|
+
class Xcode
|
6
|
+
# FIXME: We should probably generate random id keys!
|
7
|
+
|
8
|
+
attr_reader :project
|
9
|
+
attr_reader :project_path
|
10
|
+
attr_reader :project_data
|
11
|
+
|
12
|
+
def initialize(project_path)
|
13
|
+
@project_path = Pathname.new(project_path)
|
14
|
+
@project = @project_path.basename.to_s.sub(/\.xcodeproj$/, '')
|
15
|
+
@project_path_data = @project_path + 'project.pbxproj'
|
16
|
+
@project_data = OSX::NSDictionary.dictionaryWithContentsOfFile(@project_path_data.to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Saves the project data atomically.
|
20
|
+
# Returns +false+ if it failed.
|
21
|
+
def save
|
22
|
+
# FIXME: Because we use non generated id's atm (which is bad!)
|
23
|
+
# we should first make a bakup of the project.
|
24
|
+
unless $TESTING
|
25
|
+
puts "\n========================================================================="
|
26
|
+
puts "Backing up project #{@project}.xcodeproj to /tmp/#{@project}.xcodeproj.bak"
|
27
|
+
puts "Please retrieve that one if for some reason the project was damaged!\n"
|
28
|
+
end
|
29
|
+
backup = "/tmp/#{@project}.xcodeproj.bak"
|
30
|
+
Kernel.system("rm -rf #{backup}") if File.exists?(backup)
|
31
|
+
Kernel.system("cp -R #{project_path} #{backup}")
|
32
|
+
|
33
|
+
# this writes the plist as a new xml style plist,
|
34
|
+
# but luckily xcode recognizes it as well and
|
35
|
+
# writes it back out as an old style plist.
|
36
|
+
@project_data.writeToFile_atomically(@project_path_data.to_s, true)
|
37
|
+
end
|
38
|
+
|
39
|
+
def nil_if_empty(result)
|
40
|
+
result.empty? ? nil : result
|
41
|
+
end
|
42
|
+
private :nil_if_empty
|
43
|
+
|
44
|
+
# Get's the id & values for a object which name is the one passed to this method.
|
45
|
+
# Returns an array: [id, values]
|
46
|
+
def object_for_name(name)
|
47
|
+
nil_if_empty @project_data['objects'].select { |object| object.last['name'] == name }.flatten
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get's the id & values for a object which type and name is the one passed to this method.
|
51
|
+
# Returns an array: [id, values]
|
52
|
+
def object_for_type_and_name(type, name)
|
53
|
+
nil_if_empty @project_data['objects'].select { |object| object.last['isa'] == type and object.last['name'] == name }.flatten
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the object that represents this projects target.
|
57
|
+
# Returns an array: [id, values]
|
58
|
+
def object_for_project_target
|
59
|
+
nil_if_empty object_for_type_and_name('PBXNativeTarget', @project)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the object for a given name.
|
63
|
+
# Returns an array: [id, values]
|
64
|
+
def object_for_id(object_id)
|
65
|
+
@project_data['objects'][object_id].nil? ? nil : [object_id, @project_data['objects'][object_id]]
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds an object to the objects.
|
69
|
+
def add_object(object_id, object_values)
|
70
|
+
@project_data['objects'][object_id] = object_values
|
71
|
+
end
|
72
|
+
|
73
|
+
# Adds a build phase specified by +object_id+ to the build phases of the project target.
|
74
|
+
def add_build_phase_to_project_target(object_id)
|
75
|
+
# Add the new build phase to the main project target if it doesn't already exist
|
76
|
+
build_target_id, build_target_values = object_for_project_target
|
77
|
+
build_target_values['buildPhases'].push(object_id) unless build_target_values['buildPhases'].include?(object_id)
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_object_to_build_phase(object_id, build_phase_id)
|
81
|
+
build_phase = object_for_id(build_phase_id).last
|
82
|
+
build_phase['files'].push(object_id) unless build_phase['files'].include?(object_id)
|
83
|
+
end
|
84
|
+
|
85
|
+
NEW_COPY_FRAMEWORKS_BUILD_PHASE = ['519A79DB0CC8AE6B00CBE85D', {
|
86
|
+
'name' => 'Copy Frameworks',
|
87
|
+
'isa' => 'PBXCopyFilesBuildPhase',
|
88
|
+
'buildActionMask' => '2147483647',
|
89
|
+
'dstPath' => '',
|
90
|
+
'dstSubfolderSpec' => 10, # TODO: is 10 the number for the location popup choice: Frameworks
|
91
|
+
'runOnlyForDeploymentPostprocessing' => 0,
|
92
|
+
'files' => []
|
93
|
+
}]
|
94
|
+
# Creates a new framework copy build phase.
|
95
|
+
# It does not add it to the objects nor the build phases,
|
96
|
+
# do this with +add_object+ and +add_build_phase_to_project_target+.
|
97
|
+
#
|
98
|
+
# FIXME: Need to generate the id's instead of static.
|
99
|
+
def new_framework_copy_build_phase
|
100
|
+
NEW_COPY_FRAMEWORKS_BUILD_PHASE
|
101
|
+
end
|
102
|
+
|
103
|
+
# Changes the path of the framework +framework_name+ to the path +new_path_to_framework+.
|
104
|
+
def change_framework_location(framework_name, new_path_to_framework)
|
105
|
+
framework_id, framework_values = object_for_name(framework_name)
|
106
|
+
framework_values['path'] = new_path_to_framework
|
107
|
+
framework_values['sourceTree'] = '<group>'
|
108
|
+
end
|
109
|
+
|
110
|
+
# Changes the path of the RubyCocoa framework to +new_path_to_framework+.
|
111
|
+
def change_rubycocoa_framework_location(new_path_to_framework)
|
112
|
+
change_framework_location 'RubyCocoa.framework', new_path_to_framework
|
113
|
+
end
|
114
|
+
|
115
|
+
# Bundles the given framework in the application.
|
116
|
+
def bundle_framework(framework_name)
|
117
|
+
framework_id, framework_values = object_for_name(framework_name)
|
118
|
+
|
119
|
+
# create a new file wrapper for in the copy build phase
|
120
|
+
framework_in_build_phase_id = '511E98590CC8C5940003DED9'
|
121
|
+
framework_in_build_phase_values = {
|
122
|
+
'isa' => 'PBXBuildFile',
|
123
|
+
'fileRef' => framework_id
|
124
|
+
}
|
125
|
+
add_object(framework_in_build_phase_id, framework_in_build_phase_values)
|
126
|
+
|
127
|
+
# get or define the Copy Frameworks build phase
|
128
|
+
build_phase = object_for_name('Copy Frameworks')
|
129
|
+
if build_phase.nil?
|
130
|
+
build_phase_id, build_phase_values = new_framework_copy_build_phase
|
131
|
+
# add the new build phase to the objects
|
132
|
+
add_object(build_phase_id, build_phase_values)
|
133
|
+
|
134
|
+
# add the new build phase to the project target
|
135
|
+
add_build_phase_to_project_target(build_phase_id)
|
136
|
+
else
|
137
|
+
build_phase_id, build_phase_values = build_phase
|
138
|
+
end
|
139
|
+
# add the framework to the build phase
|
140
|
+
add_object_to_build_phase(framework_in_build_phase_id, build_phase_id)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Bundles the RubyCocoa framework in the application.
|
144
|
+
def bundle_rubycocoa_framework
|
145
|
+
bundle_framework 'RubyCocoa.framework'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/log/debug.log
ADDED
File without changes
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rucola/rucola_support'
|
3
|
+
require 'rucola/nib'
|
4
|
+
|
5
|
+
class ControllerGenerator < RubiGen::Base
|
6
|
+
|
7
|
+
default_options :author => nil
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
def initialize(runtime_args, runtime_options = {})
|
12
|
+
super
|
13
|
+
usage if args.empty?
|
14
|
+
@name = args.shift
|
15
|
+
@nibs_to_update = args
|
16
|
+
extract_options
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_class_to_classes_nib(controller_name, nib_path)
|
20
|
+
nib = Rucola::Nib::Classes.open(File.expand_path(destination_path(nib_path)))
|
21
|
+
nib.add_class(controller_name)
|
22
|
+
nib.save
|
23
|
+
end
|
24
|
+
|
25
|
+
def manifest
|
26
|
+
record do |m|
|
27
|
+
# Ensure appropriate folder(s) exists
|
28
|
+
controller_dir = 'app/controllers'
|
29
|
+
test_dir = 'test/controllers'
|
30
|
+
|
31
|
+
m.directory controller_dir
|
32
|
+
m.directory test_dir
|
33
|
+
|
34
|
+
# Create stubs
|
35
|
+
m.template 'controller_template.rb.erb', "#{controller_dir}/#{@name.snake_case}_controller.rb"
|
36
|
+
m.template 'test_controller_template.rb.erb', "#{test_dir}/test_#{@name.snake_case}_controller.rb"
|
37
|
+
|
38
|
+
# Optionally add the class to a nib
|
39
|
+
controller_name = "#{@name.camel_case}Controller"
|
40
|
+
if @nibs_to_update.empty?
|
41
|
+
print "\nWould you like me to add the class #{controller_name} to MainMenu.nib? [Y/n]: " unless $TESTING
|
42
|
+
result = Kernel.gets.strip
|
43
|
+
if result.empty? or result.downcase == 'y'
|
44
|
+
add_class_to_classes_nib(controller_name, 'misc/English.lproj/MainMenu.nib/classes.nib')
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@nibs_to_update.each do |nib|
|
48
|
+
if nib.camel_case == 'MainMenu'
|
49
|
+
add_class_to_classes_nib(controller_name, 'misc/English.lproj/MainMenu.nib/classes.nib')
|
50
|
+
else
|
51
|
+
add_class_to_classes_nib(controller_name, "app/views/#{nib.camel_case}.nib/classes.nib")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
def banner
|
60
|
+
<<-EOS
|
61
|
+
Creates a ...
|
62
|
+
|
63
|
+
USAGE: #{$0} #{spec.name} name"
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_options!(opts)
|
68
|
+
# opts.separator ''
|
69
|
+
# opts.separator 'Options:'
|
70
|
+
# For each option below, place the default
|
71
|
+
# at the top of the file next to "default_options"
|
72
|
+
# opts.on("-a", "--author=\"Your Name\"", String,
|
73
|
+
# "Some comment about this option",
|
74
|
+
# "Default: none") { |options[:author]| }
|
75
|
+
# opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
76
|
+
end
|
77
|
+
|
78
|
+
def extract_options
|
79
|
+
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
80
|
+
# Templates can access these value via the attr_reader-generated methods, but not the
|
81
|
+
# raw instance variable value.
|
82
|
+
# @author = options[:author]
|
83
|
+
end
|
84
|
+
end
|