rucola 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/ChangeLog +628 -0
  2. data/History.txt +4 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +106 -0
  5. data/README.txt +126 -0
  6. data/Rakefile +32 -0
  7. data/TODO +28 -0
  8. data/app_generators/rucola/USAGE +6 -0
  9. data/app_generators/rucola/rucola_generator.rb +112 -0
  10. data/app_generators/rucola/templates/Rakefile.erb +12 -0
  11. data/app_generators/rucola/templates/Rakefile.erb.old +156 -0
  12. data/app_generators/rucola/templates/app/controllers/application_controller.rb +22 -0
  13. data/app_generators/rucola/templates/config/Info.plist.erb +28 -0
  14. data/app_generators/rucola/templates/config/boot.rb +2 -0
  15. data/app_generators/rucola/templates/config/environment.rb +11 -0
  16. data/app_generators/rucola/templates/config/environments/debug.rb +3 -0
  17. data/app_generators/rucola/templates/config/environments/release.rb +3 -0
  18. data/app_generators/rucola/templates/config/environments/test.rb +3 -0
  19. data/app_generators/rucola/templates/config/ib_external_class_defs.yml +13 -0
  20. data/app_generators/rucola/templates/misc/English.lproj/InfoPlist.strings.erb +3 -0
  21. data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/classes.nib +40 -0
  22. data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/info.nib +18 -0
  23. data/app_generators/rucola/templates/misc/English.lproj/MainMenu.nib/keyedobjects.nib +0 -0
  24. data/app_generators/rucola/templates/misc/main.m.erb +15 -0
  25. data/app_generators/rucola/templates/misc/rb_main.rb.erb +13 -0
  26. data/app_generators/rucola/templates/project.pbxproj.erb +299 -0
  27. data/app_generators/rucola/templates/script/plugin +84 -0
  28. data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +10 -0
  29. data/app_generators/rucola/templates/test/test_helper.rb +10 -0
  30. data/bin/rucola +12 -0
  31. data/config/hoe.rb +71 -0
  32. data/config/requirements.rb +17 -0
  33. data/lib/rucola.rb +3 -0
  34. data/lib/rucola/info_plist.rb +37 -0
  35. data/lib/rucola/initializer.rb +313 -0
  36. data/lib/rucola/nib.rb +99 -0
  37. data/lib/rucola/rucola_support.rb +9 -0
  38. data/lib/rucola/rucola_support/controllers.rb +2 -0
  39. data/lib/rucola/rucola_support/controllers/rc_controller.rb +7 -0
  40. data/lib/rucola/rucola_support/controllers/rc_window_controller.rb +12 -0
  41. data/lib/rucola/rucola_support/core_ext.rb +2 -0
  42. data/lib/rucola/rucola_support/core_ext/objc.rb +4 -0
  43. data/lib/rucola/rucola_support/core_ext/objc/nsobject.rb +22 -0
  44. data/lib/rucola/rucola_support/core_ext/ruby.rb +4 -0
  45. data/lib/rucola/rucola_support/core_ext/ruby/string.rb +21 -0
  46. data/lib/rucola/rucola_support/initialize_hooks.rb +21 -0
  47. data/lib/rucola/rucola_support/models.rb +1 -0
  48. data/lib/rucola/rucola_support/models/rc_document.rb +10 -0
  49. data/lib/rucola/rucola_support/notifications.rb +1 -0
  50. data/lib/rucola/rucola_support/notifications/notifications.rb +146 -0
  51. data/lib/rucola/rucola_support/rc_app.rb +101 -0
  52. data/lib/rucola/tasks/freeze.rake +44 -0
  53. data/lib/rucola/tasks/interface_builder.rake +80 -0
  54. data/lib/rucola/tasks/main.rake +29 -0
  55. data/lib/rucola/tasks/xcode.rake +43 -0
  56. data/lib/rucola/test_helper.rb +57 -0
  57. data/lib/rucola/version.rb +9 -0
  58. data/lib/rucola/xcode.rb +148 -0
  59. data/log/debug.log +0 -0
  60. data/rucola_generators/controller/USAGE +5 -0
  61. data/rucola_generators/controller/controller_generator.rb +84 -0
  62. data/rucola_generators/controller/templates/controller_template.rb.erb +5 -0
  63. data/rucola_generators/controller/templates/test_controller_template.rb.erb +10 -0
  64. data/rucola_generators/document_model/USAGE +5 -0
  65. data/rucola_generators/document_model/document_model_generator.rb +67 -0
  66. data/rucola_generators/document_model/templates/document_model_template.rb.erb +27 -0
  67. data/rucola_generators/document_model/templates/test_document_model_template.rb.erb +10 -0
  68. data/rucola_generators/window_controller/USAGE +6 -0
  69. data/rucola_generators/window_controller/templates/Window.nib/classes.nib.erb +35 -0
  70. data/rucola_generators/window_controller/templates/Window.nib/info.nib +16 -0
  71. data/rucola_generators/window_controller/templates/Window.nib/keyedobjects.nib +0 -0
  72. data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +10 -0
  73. data/rucola_generators/window_controller/templates/window_controller_template.rb.erb +19 -0
  74. data/rucola_generators/window_controller/window_controller_generator.rb +74 -0
  75. data/script/destroy +14 -0
  76. data/script/generate +14 -0
  77. data/script/txt2html +74 -0
  78. data/setup.rb +1585 -0
  79. data/tasks/deployment.rake +27 -0
  80. data/tasks/environment.rake +7 -0
  81. data/tasks/website.rake +17 -0
  82. data/test/fixtures/Info.plist +28 -0
  83. data/test/fixtures/MainMenu.nib/classes.nib +32 -0
  84. data/test/fixtures/MainMenu.nib/info.nib +18 -0
  85. data/test/fixtures/MainMenu.nib/keyedobjects.nib +0 -0
  86. data/test/test_controller_generator.rb +75 -0
  87. data/test/test_core_ext.rb +15 -0
  88. data/test/test_document_model_generator.rb +64 -0
  89. data/test/test_generator_helper.rb +20 -0
  90. data/test/test_helper.rb +13 -0
  91. data/test/test_info_plist.rb +31 -0
  92. data/test/test_nib.rb +73 -0
  93. data/test/test_notifications.rb +75 -0
  94. data/test/test_objc_core_ext.rb +37 -0
  95. data/test/test_rc_app.rb +63 -0
  96. data/test/test_rc_document.rb +18 -0
  97. data/test/test_rc_window_controller.rb +13 -0
  98. data/test/test_rucola.rb +11 -0
  99. data/test/test_rucola_generator.rb +87 -0
  100. data/test/test_window_controller_generator.rb +50 -0
  101. data/test/test_xcode.rb +128 -0
  102. data/website/index.html +199 -0
  103. data/website/index.txt +126 -0
  104. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  105. data/website/stylesheets/screen.css +138 -0
  106. data/website/template.rhtml +48 -0
  107. 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
@@ -0,0 +1,9 @@
1
+ module Rucola #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -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
File without changes
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Generate a controller that inherits from NSObject.
3
+
4
+ Usage:
5
+ script/generate controller articles
@@ -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