tennpipes-init 3.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +163 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes-init +16 -0
  6. data/lib/tennpipes-init.rb +73 -0
  7. data/lib/tennpipes-init/command.rb +18 -0
  8. data/lib/tennpipes-init/generators/actions.rb +630 -0
  9. data/lib/tennpipes-init/generators/app.rb +75 -0
  10. data/lib/tennpipes-init/generators/app/app.rb.tt +72 -0
  11. data/lib/tennpipes-init/generators/app/app.rb.tt~ +72 -0
  12. data/lib/tennpipes-init/generators/cli.rb +57 -0
  13. data/lib/tennpipes-init/generators/component.rb +73 -0
  14. data/lib/tennpipes-init/generators/components/actions.rb +208 -0
  15. data/lib/tennpipes-init/generators/components/mocks/mocha.rb +10 -0
  16. data/lib/tennpipes-init/generators/components/mocks/rr.rb +13 -0
  17. data/lib/tennpipes-init/generators/components/orms/activerecord.rb +201 -0
  18. data/lib/tennpipes-init/generators/components/orms/couchrest.rb +55 -0
  19. data/lib/tennpipes-init/generators/components/orms/datamapper.rb +140 -0
  20. data/lib/tennpipes-init/generators/components/orms/dynamoid.rb +67 -0
  21. data/lib/tennpipes-init/generators/components/orms/minirecord.rb +165 -0
  22. data/lib/tennpipes-init/generators/components/orms/mongoid.rb +113 -0
  23. data/lib/tennpipes-init/generators/components/orms/mongomapper.rb +43 -0
  24. data/lib/tennpipes-init/generators/components/orms/mongomatic.rb +84 -0
  25. data/lib/tennpipes-init/generators/components/orms/ohm.rb +65 -0
  26. data/lib/tennpipes-init/generators/components/orms/ripple.rb +75 -0
  27. data/lib/tennpipes-init/generators/components/orms/sequel.rb +99 -0
  28. data/lib/tennpipes-init/generators/components/renderers/erb.rb +3 -0
  29. data/lib/tennpipes-init/generators/components/renderers/haml.rb +3 -0
  30. data/lib/tennpipes-init/generators/components/renderers/liquid.rb +4 -0
  31. data/lib/tennpipes-init/generators/components/renderers/slim.rb +3 -0
  32. data/lib/tennpipes-init/generators/components/scripts/dojo.rb +10 -0
  33. data/lib/tennpipes-init/generators/components/scripts/extcore.rb +10 -0
  34. data/lib/tennpipes-init/generators/components/scripts/jquery.rb +10 -0
  35. data/lib/tennpipes-init/generators/components/scripts/mootools.rb +10 -0
  36. data/lib/tennpipes-init/generators/components/scripts/prototype.rb +12 -0
  37. data/lib/tennpipes-init/generators/components/scripts/rightjs.rb +10 -0
  38. data/lib/tennpipes-init/generators/components/stylesheets/compass.rb +39 -0
  39. data/lib/tennpipes-init/generators/components/stylesheets/compass/application.scss +43 -0
  40. data/lib/tennpipes-init/generators/components/stylesheets/compass/partials/_base.scss +12 -0
  41. data/lib/tennpipes-init/generators/components/stylesheets/less.rb +25 -0
  42. data/lib/tennpipes-init/generators/components/stylesheets/sass.rb +15 -0
  43. data/lib/tennpipes-init/generators/components/stylesheets/scss.rb +16 -0
  44. data/lib/tennpipes-init/generators/components/tests/bacon.rb +103 -0
  45. data/lib/tennpipes-init/generators/components/tests/cucumber.rb +86 -0
  46. data/lib/tennpipes-init/generators/components/tests/minitest.rb +110 -0
  47. data/lib/tennpipes-init/generators/components/tests/riot.rb +117 -0
  48. data/lib/tennpipes-init/generators/components/tests/rspec.rb +111 -0
  49. data/lib/tennpipes-init/generators/components/tests/shoulda.rb +114 -0
  50. data/lib/tennpipes-init/generators/components/tests/steak.rb +114 -0
  51. data/lib/tennpipes-init/generators/controller.rb +77 -0
  52. data/lib/tennpipes-init/generators/helper.rb +50 -0
  53. data/lib/tennpipes-init/generators/mailer.rb +52 -0
  54. data/lib/tennpipes-init/generators/migration.rb +43 -0
  55. data/lib/tennpipes-init/generators/model.rb +113 -0
  56. data/lib/tennpipes-init/generators/plugin.rb +67 -0
  57. data/lib/tennpipes-init/generators/project.rb +160 -0
  58. data/lib/tennpipes-init/generators/project/config.ru +9 -0
  59. data/lib/tennpipes-init/generators/project/config/apps.rb.tt +35 -0
  60. data/lib/tennpipes-init/generators/project/config/boot.rb +49 -0
  61. data/lib/tennpipes-init/generators/project/public/favicon.ico +0 -0
  62. data/lib/tennpipes-init/generators/project/public/images/booking.com.png +0 -0
  63. data/lib/tennpipes-init/generators/project/public/images/causes.png +0 -0
  64. data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bg.jpg +0 -0
  65. data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bluelogo.png +0 -0
  66. data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bluelogo.svg +68 -0
  67. data/lib/tennpipes-init/generators/project/public/images/ennkeypee_whitelogo.png +0 -0
  68. data/lib/tennpipes-init/generators/project/public/images/ennkeypee_whitelogo.svg +65 -0
  69. data/lib/tennpipes-init/generators/project/public/images/forever21.png +0 -0
  70. data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.eot +0 -0
  71. data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.svg +970 -0
  72. data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.ttf +0 -0
  73. data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.woff +0 -0
  74. data/lib/tennpipes-init/generators/project/public/images/icons/tennpipes-icons.css +598 -0
  75. data/lib/tennpipes-init/generators/project/public/images/image1.jpg +0 -0
  76. data/lib/tennpipes-init/generators/project/public/images/image11.jpg +0 -0
  77. data/lib/tennpipes-init/generators/project/public/images/image2.jpg +0 -0
  78. data/lib/tennpipes-init/generators/project/public/images/image3.jpg +0 -0
  79. data/lib/tennpipes-init/generators/project/public/images/intuit.png +0 -0
  80. data/lib/tennpipes-init/generators/project/public/images/krispykreme.png +0 -0
  81. data/lib/tennpipes-init/generators/project/public/images/placeholders/README.md +302 -0
  82. data/lib/tennpipes-init/generators/project/public/images/placeholders/bower.json +4 -0
  83. data/lib/tennpipes-init/generators/project/public/images/placeholders/composer.json +34 -0
  84. data/lib/tennpipes-init/generators/project/public/images/placeholders/gulpfile.js +92 -0
  85. data/lib/tennpipes-init/generators/project/public/images/placeholders/holder.js +1920 -0
  86. data/lib/tennpipes-init/generators/project/public/images/placeholders/holder.min.js +12 -0
  87. data/lib/tennpipes-init/generators/project/public/images/placeholders/package.json +46 -0
  88. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/holder.js +1411 -0
  89. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/augment.js +27 -0
  90. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/ondomready.js +155 -0
  91. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/polyfills.js +177 -0
  92. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/scenegraph.js +101 -0
  93. data/lib/tennpipes-init/generators/project/public/images/placeholders/src/utils.js +129 -0
  94. data/lib/tennpipes-init/generators/project/public/images/priceline.com.png +0 -0
  95. data/lib/tennpipes-init/generators/project/public/images/stripe.png +0 -0
  96. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes.min.js +6081 -0
  97. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.abide.js +340 -0
  98. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.accordion.js +67 -0
  99. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.alert.js +43 -0
  100. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.clearing.js +556 -0
  101. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.dropdown.js +448 -0
  102. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.equalizer.js +77 -0
  103. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.interchange.js +354 -0
  104. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.joyride.js +932 -0
  105. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.js +703 -0
  106. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.magellan.js +203 -0
  107. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.offcanvas.js +152 -0
  108. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.orbit.js +476 -0
  109. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.reveal.js +471 -0
  110. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.slider.js +263 -0
  111. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.tab.js +237 -0
  112. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.tooltip.js +307 -0
  113. data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.topbar.js +452 -0
  114. data/lib/tennpipes-init/generators/project/public/javascripts/vendor/fastclick.js +8 -0
  115. data/lib/tennpipes-init/generators/project/public/javascripts/vendor/jquery.cookie.js +8 -0
  116. data/lib/tennpipes-init/generators/project/public/javascripts/vendor/jquery.js +26 -0
  117. data/lib/tennpipes-init/generators/project/public/javascripts/vendor/modernizr.js +8 -0
  118. data/lib/tennpipes-init/generators/project/public/javascripts/vendor/placeholder.js +2 -0
  119. data/lib/tennpipes-init/generators/project/public/stylesheets/app.css~ +178 -0
  120. data/lib/tennpipes-init/generators/project/public/stylesheets/app1.css~ +177 -0
  121. data/lib/tennpipes-init/generators/project/public/stylesheets/ennkeypee.css +214 -0
  122. data/lib/tennpipes-init/generators/project/public/stylesheets/ennkeypee.css~ +214 -0
  123. data/lib/tennpipes-init/generators/project/public/stylesheets/normalize.css +427 -0
  124. data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.css +6201 -0
  125. data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.css~ +6201 -0
  126. data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.min.css +1 -0
  127. data/lib/tennpipes-init/generators/runner.rb +139 -0
  128. data/lib/tennpipes-init/generators/task.rb +45 -0
  129. data/lib/tennpipes-init/generators/templates/Gemfile.tt +32 -0
  130. data/lib/tennpipes-init/generators/templates/Rakefile.tt +8 -0
  131. data/lib/tennpipes-init/generators/templates/controller.rb.tt +22 -0
  132. data/lib/tennpipes-init/generators/templates/gem/README.md.tt +29 -0
  133. data/lib/tennpipes-init/generators/templates/gem/gemspec.tt +19 -0
  134. data/lib/tennpipes-init/generators/templates/gem/lib/libname.tt +6 -0
  135. data/lib/tennpipes-init/generators/templates/gem/lib/libname/version.tt +3 -0
  136. data/lib/tennpipes-init/generators/templates/helper.rb.tt +13 -0
  137. data/lib/tennpipes-init/generators/templates/initializer.rb.tt +5 -0
  138. data/lib/tennpipes-init/generators/templates/mailer.rb.tt +54 -0
  139. data/lib/tennpipes-init/generators/templates/project_bin.tt +14 -0
  140. data/lib/tennpipes-init/generators/templates/task.rb.tt +7 -0
  141. data/lib/tennpipes-init/tennpipes-tasks/activerecord.rb +377 -0
  142. data/lib/tennpipes-init/tennpipes-tasks/database.rb +12 -0
  143. data/lib/tennpipes-init/tennpipes-tasks/datamapper.rb +94 -0
  144. data/lib/tennpipes-init/tennpipes-tasks/minirecord.rb +19 -0
  145. data/lib/tennpipes-init/tennpipes-tasks/mongoid.rb +215 -0
  146. data/lib/tennpipes-init/tennpipes-tasks/mongomapper.rb +55 -0
  147. data/lib/tennpipes-init/tennpipes-tasks/sequel.rb +85 -0
  148. data/lib/tennpipes-init/tennpipes-tasks/sql-helpers.rb +72 -0
  149. data/test/fixtures/admin_template.rb +7 -0
  150. data/test/fixtures/example_template.rb +15 -0
  151. data/test/fixtures/git_template.rb +4 -0
  152. data/test/fixtures/plugin_template.rb +13 -0
  153. data/test/fixtures/rake_template.rb +9 -0
  154. data/test/helper.rb +103 -0
  155. data/test/test_app_generator.rb +142 -0
  156. data/test/test_cli.rb +27 -0
  157. data/test/test_component_generator.rb +98 -0
  158. data/test/test_controller_generator.rb +272 -0
  159. data/test/test_generator.rb +13 -0
  160. data/test/test_helper_generator.rb +133 -0
  161. data/test/test_mailer_generator.rb +69 -0
  162. data/test/test_migration_generator.rb +222 -0
  163. data/test/test_model_generator.rb +553 -0
  164. data/test/test_plugin_generator.rb +152 -0
  165. data/test/test_project_generator.rb +757 -0
  166. data/test/test_task_generator.rb +53 -0
  167. metadata +285 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7ceae2eea5dffe4f6251675777b082af7ff26fd
4
+ data.tar.gz: 30e12698ffc27d64b3e719a0444be4c4e47597aa
5
+ SHA512:
6
+ metadata.gz: 39f426e683fb4166564fb2297ddbf4a1a93d0fdd4917f1a53a10686fc3c1c89cfd22779aa5561c2a21a4935566761a0be4dc564b1e030f373db0bd091e1f47b5
7
+ data.tar.gz: 2b208aec0720a1ee5d24df9591261882cec35ddd8ae77f5cddc49f37a3ea3aff59e3bedf8227be1f5519307265605cb393d373f0c7ff5122d994436b56aaf281
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Tennpipes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,163 @@
1
+ = Agnostic Application Generators (tennpipes-init)
2
+
3
+ === Overview
4
+
5
+ Tennpipes comes preloaded with flexible code generators powered in part by the excellent Thor gem
6
+ (incidentally also used in the Rails 3 generators). These generators are intended to allow for easy code generation
7
+ both in creating new applications and building on existing ones. The generators have been built to be as library agnostic
8
+ as possible, supporting a myriad of test frameworks, js libraries, mocking libraries, etc.
9
+
10
+ See the guide for {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators] for a
11
+ more in-depth look at the system.
12
+
13
+ === Project Generator
14
+
15
+ Tennpipes provides generator support for quickly creating new Tennpipes applications. This provides many benefits
16
+ such as constructing the recommended Tennpipes application structure, auto-generating a Gemfile listing
17
+ all starting dependencies and guidelines provided within the generated files to help orient a new user
18
+ to using Tennpipes.
19
+
20
+ One important feature of the generators is that they were built from the ground up to support a wide variety
21
+ of tools, libraries and gems for use within your tennpipes application.
22
+
23
+ The simplest possible command to generate a base application would be:
24
+
25
+ $ tennpipes-init project demo_project
26
+
27
+ This would construct a Tennpipes application DemoApp (which extends from Tennpipes::Application)
28
+ inside the folder 'demo_project' at our current path. Inside the application there would be configuration and
29
+ setup performed for the default components.
30
+
31
+ You can define specific components to be used:
32
+
33
+ $ tennpipes-init project demo_project -t rspec -r haml -m rr -s jquery -d datamapper
34
+
35
+ You can also instruct the generator to skip a certain component to avoid using one at all (or to use your own):
36
+
37
+ $ tennpipes-init project demo_project --test none --renderer none
38
+
39
+ The available components and their default options are listed below:
40
+
41
+ test:: none (default), bacon, shoulda, cucumber, riot, rspec, minitest, steak
42
+ renderer:: slim (default), erb, erubis, liquid, haml
43
+ stylesheet:: none (default), less, compass, sass, scss
44
+ mock:: none (default), mocha, rr
45
+ script:: none (default), jquery, prototype, mootools, rightjs, extcore, dojo
46
+ orm:: none (default), datamapper, mongomapper, mongoid, activerecord, minirecord, sequel, couchrest, ohm, mongomatic, ripple, dynamoid
47
+
48
+ In addition, you can generate projects based on existing templates:
49
+
50
+ $ tennpipes-init project demo_project --template sampleblog
51
+
52
+ To learn more about the project generator, check out the guide to
53
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
54
+
55
+ === Plugin System
56
+
57
+ Tennpipes provides support for plugins to be executed within your application. For example:
58
+
59
+ $ tennpipes-init plugin hoptoad
60
+
61
+ would install the hoptoad middleware into your application automatically.
62
+
63
+ To learn more about the plugin system, check out the guide to
64
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
65
+
66
+ === Sub App Generator
67
+
68
+ Unlike other ruby frameworks Tennpipes is principally designed for mounting multiple apps at the same time.
69
+
70
+ First you need to create a project
71
+
72
+ $ tennpipes-init project demo_project
73
+ $ cd demo_project
74
+
75
+ Now you are in demo_project and you can create your apps:
76
+
77
+ $ tennpipes-init app one
78
+ $ tennpipes-init app two
79
+
80
+ By default these apps are mounted under:
81
+
82
+ * /one
83
+ * /two
84
+
85
+ but you can edit config/apps.rb and change it.
86
+
87
+ To learn more about the subapp generator, check out the guide to
88
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
89
+
90
+ === Model Generator
91
+
92
+ Tennpipes provides generator support for quickly creating new models within your Tennpipes application. Note that
93
+ the models (and migrations) generated are specifically tailored towards the ORM component and testing framework
94
+ chosen during application generation.
95
+
96
+ Very important to note that model generators are intended primarily to work within applications
97
+ created through the Tennpipes application generator and that follow Tennpipes conventions. Using model generators
98
+ within an existing application not generated by Tennpipes will likely not work as expected.
99
+
100
+ Using the model generator is as simple as:
101
+
102
+ $ tennpipes-init model User
103
+
104
+ You can also specify desired fields to be contained within your User model:
105
+
106
+ $ tennpipes-init model User name:string age:integer email:string
107
+
108
+ To learn more about the model generator, check out the guide to
109
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
110
+
111
+ === Migration Generator
112
+
113
+ Tennpipes provides generator for quickly generating new migrations to change or manipulate the database schema.
114
+ These migrations generated will be tailored towards the ORM chosen when generating the application.
115
+
116
+ Very important to note that migration generators are intended primarily to work within applications
117
+ created through the Tennpipes application generator and that follow Tennpipes conventions. Using migration generators
118
+ within an existing application not generated by Tennpipes will likely not work as expected.
119
+
120
+ Using the migration generator is as simple as:
121
+
122
+ $ tennpipes-init migration AddFieldsToUsers
123
+ $ tennpipes-init migration RemoveFieldsFromUsers
124
+
125
+ To learn more about the migration generator, check out the guide to
126
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
127
+
128
+ === Controller Generator
129
+
130
+ Tennpipes provides generator support for quickly creating new controllers within your Tennpipes application. Note that
131
+ the controller tests are generated specifically tailored towards the testing framework chosen
132
+ during application generation.
133
+
134
+ Very important to note that controller generators are intended primarily to work within applications
135
+ created through the Tennpipes application generator and that follow Tennpipes conventions.
136
+
137
+ Using the controller generator is as simple as:
138
+
139
+ $ tennpipes-init controller Admin
140
+
141
+ You can also specify desired actions to be added to your controller:
142
+
143
+ $ tennpipes-init controller Admin get:index get:new post:create
144
+
145
+ To learn more about the controller generator, check out the guide to
146
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
147
+
148
+ === Mailer Generator
149
+
150
+ Tennpipes provides generator support for quickly creating new mailers within your Tennpipes application.
151
+ Very important to note that mailer generators are intended primarily to work within applications
152
+ created through the Tennpipes application generator and that follow Tennpipes conventions.
153
+
154
+ Using the mailer generator is as simple as:
155
+
156
+ $ tennpipes-init mailer UserNotifier
157
+
158
+ To learn more about the mailer generator, check out the guide to
159
+ {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
160
+
161
+ == Copyright
162
+
163
+ Copyright (c) 2011-2013 Tennpipes. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems' unless defined?(Gem) # Useful only on --dev mode
3
+ require 'bundler/setup' if %w(Gemfile .components).all? { |f| File.exist?(f) }
4
+
5
+ tennpipes_gen_path = File.expand_path('../../lib', __FILE__)
6
+ $:.unshift(tennpipes_gen_path) if File.directory?(tennpipes_gen_path) && !$:.include?(tennpipes_gen_path)
7
+
8
+ # We try to load the vendored tennpipes-base if exist (useful also for --dev mode)
9
+ tennpipes_core_path = File.expand_path('../../../tennpipes-base/lib', __FILE__)
10
+ $:.unshift(tennpipes_core_path) if File.directory?(tennpipes_core_path) && !$:.include?(tennpipes_core_path)
11
+
12
+ require 'tennpipes-init'
13
+ require 'tennpipes-init/generators/cli'
14
+
15
+ # We need our config boot because we need to load registered generators so:
16
+ Tennpipes::Generators::Cli.start(ARGV)
@@ -0,0 +1,73 @@
1
+ require 'tennpipes-base/tasks'
2
+ require 'tennpipes-init/command'
3
+ require 'active_support/ordered_hash'
4
+
5
+ module Tennpipes
6
+ ##
7
+ # This module it's used for register generators.
8
+ #
9
+ # Can be useful for 3rd party generators:
10
+ #
11
+ # # custom_generator.rb
12
+ # class CustomGenerator < Thor::Group
13
+ # Tennpipes::Generators.add_generator(:custom_generator, self)
14
+ # end
15
+ #
16
+ # Now for handle generators in tennpipes you need to add it to into +load_paths+.
17
+ #
18
+ # Tennpipes::Generators.load_paths << "custom_generator.rb"
19
+ #
20
+ module Generators
21
+ # Defines the absolute path to the tennpipes source folder.
22
+ DEV_PATH = File.expand_path("../../", File.dirname(__FILE__))
23
+
24
+ class << self
25
+ ##
26
+ # Store our generators paths.
27
+ #
28
+ def load_paths
29
+ @_files ||= []
30
+ end
31
+
32
+ ##
33
+ # Return an ordered list of task with their class.
34
+ #
35
+ def mappings
36
+ @_mappings ||= ActiveSupport::OrderedHash.new
37
+ end
38
+
39
+ ##
40
+ # Global add a new generator class to +tennpipes-init+.
41
+ #
42
+ # @param [Symbol] name
43
+ # Key name for generator mapping.
44
+ # @param [Class] klass
45
+ # Class of generator.
46
+ #
47
+ # @return [Hash] generator mappings
48
+ #
49
+ # @example
50
+ # Tennpipes::Generators.add_generator(:controller, Controller)
51
+ #
52
+ def add_generator(name, klass)
53
+ mappings[name] = klass
54
+ end
55
+
56
+ ##
57
+ # Load Global Actions and Component Actions then all files in +load_path+.
58
+ #
59
+ def load_components!
60
+ require 'tennpipes-init/generators/actions'
61
+ require 'tennpipes-init/generators/components/actions'
62
+ require 'tennpipes-init/generators/runner'
63
+ load_paths.flatten.each { |file| require file }
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Add our generators to Tennpipes::Generators.
70
+ Tennpipes::Generators.load_paths << Dir[File.dirname(__FILE__) + '/tennpipes-init/generators/{project,app,mailer,controller,helper,model,migration,plugin,component,task}.rb']
71
+
72
+ # Add our tasks to tennpipes-base.
73
+ Tennpipes::Tasks.files << Dir[File.dirname(__FILE__) + "/tennpipes-init/tennpipes-tasks/**/*.rb"]
@@ -0,0 +1,18 @@
1
+ require 'tennpipes-base/command'
2
+
3
+ module Tennpipes
4
+ ##
5
+ # This method return the correct location of tennpipes-init bin or
6
+ # exec it using Kernel#system with the given args.
7
+ #
8
+ # @param [Array<String>] args.
9
+ # Splat of arguments to pass to tennpipes-init.
10
+ #
11
+ # @example
12
+ # Tennpipes.bin_gen(:app, name.to_s, "-r=#{destination_root}")
13
+ #
14
+ def self.bin_gen(*args)
15
+ @_tennpipes_gen_bin ||= [Tennpipes.ruby_command, File.expand_path("../../../bin/tennpipes-init", __FILE__)]
16
+ system args.unshift(@_tennpipes_gen_bin).join(" ")
17
+ end
18
+ end
@@ -0,0 +1,630 @@
1
+ require 'pathname'
2
+
3
+ module Tennpipes
4
+ module Generators
5
+ # Raised when an application does not have a resolved root path.
6
+ class AppRootNotFound < RuntimeError; end
7
+ ##
8
+ # Default helper name for use in tiny app skeleton generator.
9
+ #
10
+ DEFAULT_HELPER_NAME = "Helper".freeze
11
+ ##
12
+ # Common actions needed to support project and component generation.
13
+ #
14
+ module Actions
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+ ##
19
+ # Avoids editing destination file if it does not exist.
20
+ #
21
+ def inject_into_file(destination, *args, &block)
22
+ destination_path = Pathname.new(destination).absolute? ? destination : destination_root(destination)
23
+ return unless File.exist?(destination_path)
24
+ super
25
+ end
26
+
27
+ ##
28
+ # Performs the necessary generator for a given component choice.
29
+ #
30
+ # @param [Symbol] component
31
+ # The type of component module.
32
+ # @param [String] choice
33
+ # The name of the component module choice.
34
+ #
35
+ # @example
36
+ # execute_component_setup(:mock, 'rr')
37
+ #
38
+ def execute_component_setup(component, choice)
39
+ return true && say_status(:skipping, "#{component} component...") if choice.to_s == 'none'
40
+ say_status(:applying, "#{choice} (#{component})...")
41
+ apply_component_for(choice, component)
42
+ send("setup_#{component}") if respond_to?("setup_#{component}")
43
+ end
44
+
45
+ ##
46
+ # Returns the related module for a given component and option.
47
+ #
48
+ # @param [String] choice
49
+ # The name of the component module.
50
+ # @param [Symbol] component
51
+ # The type of the component module.
52
+ #
53
+ # @example
54
+ # apply_component_for('rr', :mock)
55
+ #
56
+ def apply_component_for(choice, component)
57
+ # I need to override Thor#apply because for unknow reason :verbose => false break tasks.
58
+ path = File.expand_path(File.dirname(__FILE__) + "/components/#{component.to_s.pluralize}/#{choice}.rb")
59
+ say_status :apply, "#{component.to_s.pluralize}/#{choice}"
60
+ shell.padding += 1
61
+ instance_eval(File.read(path))
62
+ shell.padding -= 1
63
+ end
64
+
65
+ ##
66
+ # Includes the component module for the given component and choice.
67
+ # It determines the choice using .components file.
68
+ #
69
+ # @param [Symbol] component
70
+ # The type of component module.
71
+ # @param [String] choice
72
+ # The name of the component module.
73
+ #
74
+ # @example
75
+ # include_component_module_for(:mock)
76
+ # include_component_module_for(:mock, 'rr')
77
+ #
78
+ def include_component_module_for(component, choice=nil)
79
+ choice = fetch_component_choice(component) unless choice
80
+ return false if choice.to_s == 'none'
81
+ apply_component_for(choice, component)
82
+ end
83
+
84
+ ##
85
+ # Returns the component choice stored within the .component file of an application.
86
+ #
87
+ # @param [Symbol] component
88
+ # The type of component module.
89
+ #
90
+ # @return [String] Name of the component module.
91
+ #
92
+ # @example
93
+ # fetch_component_choice(:mock)
94
+ #
95
+ def fetch_component_choice(component)
96
+ retrieve_component_config(destination_root('.components'))[component]
97
+ end
98
+
99
+ ##
100
+ # Set the component choice in the .component file of the application.
101
+ #
102
+ # @param [Symbol] key
103
+ # The type of component module.
104
+ # @param [Symbol] value
105
+ # The name of the component module.
106
+ #
107
+ # @return [Symbol] The name of the component module.
108
+ #
109
+ # @example
110
+ # store_component_choice(:renderer, :haml)
111
+ #
112
+ def store_component_choice(key, value)
113
+ path = destination_root('.components')
114
+ config = retrieve_component_config(path)
115
+ config[key] = value
116
+ create_file(path, :force => true) { config.to_yaml }
117
+ value
118
+ end
119
+
120
+ ##
121
+ # Loads the component config back into a hash.
122
+ #
123
+ # @param [String] target
124
+ # Path to component config file.
125
+ #
126
+ # @return [Hash] Loaded YAML file.
127
+ #
128
+ # @example
129
+ # retrieve_component_config(...)
130
+ # # => { :mock => 'rr', :test => 'riot', ... }
131
+ #
132
+ def retrieve_component_config(target)
133
+ YAML.load_file(target)
134
+ end
135
+
136
+ ##
137
+ # Prompts the user if necessary until a valid choice is returned for the component.
138
+ #
139
+ # @param [Symbol] component
140
+ # The type of component module.
141
+ #
142
+ # @return [String] Name of component if valid, otherwise ask for valid choice.
143
+ #
144
+ # @example
145
+ # resolve_valid_choice(:mock)
146
+ #
147
+ def resolve_valid_choice(component)
148
+ available_string = self.class.available_choices_for(component).join(", ")
149
+ choice = options[component]
150
+ until valid_choice?(component, choice)
151
+ say("Option for --#{component} '#{choice}' is not available.", :red)
152
+ choice = ask("Please enter a valid option for #{component} (#{available_string}):")
153
+ end
154
+ choice
155
+ end
156
+
157
+ ##
158
+ # Returns true if the option passed is a valid choice for component.
159
+ #
160
+ # @param [Symbol] component
161
+ # The type of component module.
162
+ # @param [String] choice
163
+ # The name of the component module.
164
+ #
165
+ # @return [Boolean] Boolean of whether the choice is valid.
166
+ #
167
+ # @example
168
+ # valid_choice?(:mock, 'rr')
169
+ #
170
+ def valid_choice?(component, choice)
171
+ choice.present? && self.class.available_choices_for(component).include?(choice.to_sym)
172
+ end
173
+
174
+ ##
175
+ # Creates a component_config file at the destination containing all component options.
176
+ # Content is a YAMLized version of a hash containing component name mapping to chosen value.
177
+ #
178
+ # @param [String] destination
179
+ # The file path to store the component config.
180
+ #
181
+ # @example
182
+ # store_component_config('/foo/bar')
183
+ #
184
+ def store_component_config(destination)
185
+ components = @_components || options
186
+ create_file(destination) do
187
+ self.class.component_types.inject({}) { |result, comp|
188
+ result[comp] = components[comp].to_s; result
189
+ }.to_yaml
190
+ end
191
+ end
192
+
193
+ ##
194
+ # Returns the root for this Thor class (also aliased as destination root).
195
+ #
196
+ # @param [Array<String>] paths
197
+ # The relative path from destination root.
198
+ #
199
+ # @return [String] The full path
200
+ #
201
+ # @example
202
+ # destination_root('config/boot.rb')
203
+ #
204
+ def destination_root(*paths)
205
+ File.expand_path(File.join(@destination_stack.last, paths))
206
+ end
207
+
208
+ ##
209
+ # Returns true if inside a Tennpipes application.
210
+ #
211
+ def in_app_root?
212
+ File.exist?(destination_root('config/boot.rb'))
213
+ end
214
+
215
+ ##
216
+ # Returns true if constant name already exists.
217
+ #
218
+ def already_exists?(name, project_name = nil)
219
+ project_name = project_name ? (Object.const_get(project_name) rescue nil) : nil
220
+ Object.const_defined?(name) || (project_name && project_name.const_defined?(name))
221
+ end
222
+
223
+ ##
224
+ # Returns the field with an unacceptable name(for symbol) else returns nil.
225
+ #
226
+ # @param [Array<String>] fields
227
+ # Field names for generators.
228
+ #
229
+ # @return [Array<String>] array of invalid fields
230
+ #
231
+ # @example
232
+ # invalid_fields ['foo:bar', 'hello:world']
233
+ #
234
+ def invalid_fields(fields)
235
+ results = fields.select { |field| field.split(":").first =~ /\W/ }
236
+ results.empty? ? nil : results
237
+ end
238
+
239
+ ##
240
+ # Apply default field types.
241
+ #
242
+ # @param [Array<String>] fields
243
+ # Field names for generators.
244
+ #
245
+ # @return [Array<String>] fields with default types
246
+ #
247
+ def apply_default_fields(fields)
248
+ fields.map! { |field| field =~ /:/ ? field : "#{field}:string" }
249
+ end
250
+
251
+ # Returns the namespace for the project.
252
+ #
253
+ # @param [String] app
254
+ # folder name of application.
255
+ #
256
+ # @return [String] namespace for application.
257
+ #
258
+ # @example
259
+ # fetch_project_name
260
+ #
261
+ def fetch_project_name(app='app')
262
+ app_path = destination_root(app, 'app.rb')
263
+ @project_name = fetch_component_choice(:namespace) if @project_name.empty?
264
+ @project_name ||= begin
265
+ say "Autodetecting project namespace using folder name.", :red
266
+ say ""
267
+ detected_namespace = File.basename(destination_root('.')).gsub(/\W/, '_').camelize
268
+ say(<<-WARNING, :red)
269
+ From v0.11.0 on, applications should have a `namespace` setting
270
+ in their .components file. Please include a line like the following
271
+ in your .components file:
272
+ WARNING
273
+ say "\t:namespace: #{detected_namespace}", :yellow
274
+ say ""
275
+
276
+ detected_namespace
277
+ end
278
+ end
279
+
280
+ ##
281
+ # Returns the app_name for the application at root.
282
+ #
283
+ # @param [String] app
284
+ # folder name of application.
285
+ #
286
+ # @return [String] class name for application.
287
+ #
288
+ # @example
289
+ # fetch_app_name('subapp')
290
+ #
291
+ def fetch_app_name(app='app')
292
+ app_path = destination_root(app, 'app.rb')
293
+ @app_name ||= File.read(app_path).scan(/class\s(.*?)\s</).flatten[0]
294
+ end
295
+
296
+ ##
297
+ # Adds all the specified gems into the Gemfile for bundler.
298
+ #
299
+ # @param [Array<String>] gem_names
300
+ # Splat of gems to require in Gemfile.
301
+ # @param [Hash] options
302
+ # The options to pass to gem in Gemfile.
303
+ #
304
+ # @example
305
+ # require_dependencies('active_record')
306
+ # require_dependencies('mocha', 'bacon', :group => 'test')
307
+ # require_dependencies('json', :version => ">=1.2.3")
308
+ #
309
+ def require_dependencies(*gem_names)
310
+ options = gem_names.extract_options!
311
+ gem_names.reverse_each { |lib| insert_into_gemfile(lib, options) }
312
+ end
313
+
314
+ ##
315
+ # Inserts a required gem into the Gemfile to add the bundler dependency.
316
+ #
317
+ # @param [String] name
318
+ # Name of gem to insert into Gemfile.
319
+ # @param [Hash] options
320
+ # Options to generate into Gemfile for gem.
321
+ #
322
+ # @example
323
+ # insert_into_gemfile(name)
324
+ # insert_into_gemfile(name, :group => 'test', :require => 'foo')
325
+ # insert_into_gemfile(name, :group => 'test', :version => ">1.2.3")
326
+ #
327
+ def insert_into_gemfile(name, options={})
328
+ after_pattern = options[:group] ? "#{options[:group].to_s.capitalize} requirements\n" : "Component requirements\n"
329
+ version = options.delete(:version)
330
+ gem_options = options.map { |k, v| k.to_s == 'require' && [true,false].include?(v) ? ":#{k} => #{v}" : ":#{k} => '#{v}'" }.join(", ")
331
+ write_option = gem_options.present? ? ", #{gem_options}" : ''
332
+ write_version = version.present? ? ", '#{version}'" : ''
333
+ include_text = "gem '#{name}'" << write_version << write_option << "\n"
334
+ inject_into_file('Gemfile', include_text, :after => after_pattern)
335
+ end
336
+
337
+ ##
338
+ # Inserts an hook before or after load in our boot.rb.
339
+ #
340
+ # @param [String] include_text
341
+ # Text to include into hooks in boot.rb.
342
+ # @param [Symbol] where
343
+ # method hook to call from Tennpipes, i.e :after_load, :before_load.
344
+ #
345
+ # @example
346
+ # insert_hook("DataMapper.finalize", :after_load)
347
+ #
348
+ def insert_hook(include_text, where)
349
+ inject_into_file('config/boot.rb', " #{include_text}\n", :after => "Tennpipes.#{where} do\n")
350
+ end
351
+
352
+ ##
353
+ # Inserts a middleware inside app.rb.
354
+ #
355
+ # @param [String] include_text
356
+ # Text to include into hooks in boot.rb.
357
+ #
358
+ # @example
359
+ # insert_middleware(ActiveRecord::ConnectionAdapters::ConnectionManagement)
360
+ #
361
+ def insert_middleware(include_text, app=nil)
362
+ name = app || (options[:name].present? ? @app_name.downcase : 'app')
363
+ inject_into_file("#{name}/app.rb", " use #{include_text}\n", :after => "Tennpipes::Application\n")
364
+ end
365
+
366
+ ##
367
+ # Registers and creates initializer.
368
+ #
369
+ # @param [Symbol] name
370
+ # Name of the initializer.
371
+ # @param [String] data
372
+ # Text to generate into the initializer file.
373
+ #
374
+ # @example
375
+ # initializer(:test, "some stuff here")
376
+ # #=> generates 'lib/test_init.rb'
377
+ #
378
+ def initializer(name, data=nil)
379
+ @_init_name, @_init_data = name, data
380
+ register = data.present? ? " register #{name.to_s.underscore.camelize}Initializer\n" : " register #{name}\n"
381
+ inject_into_file destination_root("/app/app.rb"), register, :after => "Tennpipes::Application\n"
382
+ template "templates/initializer.rb.tt", destination_root("/lib/#{name}_initializer.rb") if data.present?
383
+ end
384
+
385
+ ##
386
+ # Creates and inserts middleware.
387
+ # @param [Symbol, String] name
388
+ # Name of the middleware.
389
+ # @param [String] source
390
+ # Text to generate into the middleware file.
391
+ #
392
+ # @example
393
+ # middleware(:hello, "class Hello\nend")
394
+ # #=> generates 'lib/hello_middleware.rb'
395
+ #
396
+ def middleware(name, source)
397
+ create_file destination_root("lib/#{name}_middleware.rb"), source
398
+ insert_middleware name.to_s.underscore.camelize
399
+ end
400
+
401
+ ##
402
+ # Insert the regired gem and add in boot.rb custom contribs.
403
+ #
404
+ # @param [String] contrib
405
+ # name of library from tennpipes-contrib
406
+ #
407
+ # @example
408
+ # require_contrib('auto_locale')
409
+ #
410
+ def require_contrib(contrib)
411
+ insert_into_gemfile 'tennpipes-contrib'
412
+ contrib = "require '" + File.join("tennpipes-contrib", contrib) + "'\n"
413
+ inject_into_file destination_root("/config/boot.rb"), contrib, :before => "\nTennpipes.load!"
414
+ end
415
+
416
+ ##
417
+ # Return true if our project has test component.
418
+ #
419
+ def test?
420
+ fetch_component_choice(:test).to_s != 'none'
421
+ end
422
+
423
+ ##
424
+ # Return true if we have a tiny skeleton.
425
+ #
426
+ def tiny?
427
+ File.exist?(destination_root('app/controllers.rb'))
428
+ end
429
+
430
+ ##
431
+ # Run the bundler.
432
+ #
433
+ def run_bundler
434
+ say 'Bundling application dependencies using bundler...', :yellow
435
+ in_root { run 'bundle install' }
436
+ end
437
+
438
+ ##
439
+ # Ask something to the user and receives a response.
440
+ #
441
+ # @param [String] statement
442
+ # String of statement to display for input.
443
+ # @param [String] default
444
+ # Default value for input.
445
+ # @param [String] color
446
+ # Name of color to display input.
447
+ #auto_locale
448
+ # @return [String] Input value
449
+ #
450
+ # @example
451
+ # ask("What is your name?")
452
+ # ask("Path for ruby", "/usr/local/bin/ruby") => "Path for ruby (leave blank for /usr/local/bin/ruby):"
453
+ #
454
+ def ask(statement, default=nil, color=nil)
455
+ default_text = default ? " (leave blank for #{default}):" : nil
456
+ say("#{statement}#{default_text} ", color)
457
+ result = $stdin.gets.strip
458
+ result.blank? ? default : result
459
+ end
460
+
461
+ ##
462
+ # Raise SystemExit if the app does not exist.
463
+ #
464
+ # @param [String] app
465
+ # Directory name of application.
466
+ #
467
+ # @example
468
+ # check_app_existence 'app'
469
+ #
470
+ def check_app_existence(app)
471
+ unless File.exist?(destination_root(app))
472
+ say
473
+ say "================================================================="
474
+ say "Unable to locate '#{app.underscore.camelize}' application "
475
+ say "================================================================="
476
+ say
477
+ raise SystemExit
478
+ end
479
+ end
480
+
481
+ ##
482
+ # Generates standard and tiny applications within a project.
483
+ #
484
+ # @param [String] app
485
+ # Name of application.
486
+ # @param [Boolean] tiny
487
+ # Boolean to generate a tiny structure.
488
+ #
489
+ # @example
490
+ # app_skeleton 'some_app'
491
+ # app_skeleton 'sub_app', true
492
+ #
493
+ def app_skeleton(app, tiny=false)
494
+ directory('app/', destination_root(app))
495
+ if tiny
496
+ template 'templates/controller.rb.tt', destination_root(app, 'controllers.rb')
497
+ @helper_name = DEFAULT_HELPER_NAME
498
+ template 'templates/helper.rb.tt', destination_root(app, 'helpers.rb')
499
+ @short_name = 'notifier'
500
+ template 'templates/mailer.rb.tt', destination_root(app, 'mailers.rb')
501
+ else
502
+ empty_directory destination_root(app, 'controllers')
503
+ empty_directory destination_root(app, 'helpers')
504
+ empty_directory destination_root(app, 'views')
505
+ empty_directory destination_root(app, 'views', 'layouts')
506
+ end
507
+ end
508
+
509
+ ##
510
+ # Ensure that project name is valid, else raise an NameError.
511
+ #
512
+ # @param [String] name
513
+ # Name of project.
514
+ #
515
+ # @return [Exception] Exception with error message if not valid.
516
+ #
517
+ # @example
518
+ # valid_constant '1235Stuff'
519
+ # valid_constant '#Abc'
520
+ #
521
+ def valid_constant?(name)
522
+ if name =~ /^\d/
523
+ raise ::NameError, "Project name #{name} cannot start with numbers"
524
+ elsif name =~ /^\W/
525
+ raise ::NameError, "Project name #{name} cannot start with non-word character"
526
+ end
527
+ end
528
+
529
+ ##
530
+ # Recognizes the path of application.
531
+ #
532
+ def recognize_path
533
+ options[:app] == '.' ? '/..' : '/../..'
534
+ end
535
+
536
+ ##
537
+ # Creates an empty directory with .keep file
538
+ #
539
+ def empty_directory_with_keep_file(destination, config = {})
540
+ empty_directory(destination, config)
541
+ keep_file(destination)
542
+ end
543
+
544
+ ##
545
+ # Creates an empty .keep file
546
+ #
547
+ def keep_file(destination)
548
+ create_file("#{destination}/.keep")
549
+ end
550
+
551
+ # Class methods for Thor generators to support the generators and component choices.
552
+ module ClassMethods
553
+ ##
554
+ # Defines a class option to allow a component to be chosen and add to component type list.
555
+ # Also builds the available_choices hash of which component choices are supported.
556
+ #
557
+ # @param [Symbol] name
558
+ # Name of component.
559
+ # @param [String] caption
560
+ # Description of the component.
561
+ # @param [Hash] options
562
+ # Additional parameters for component choice.
563
+ #
564
+ # @example
565
+ # component_option :test, "Testing framework", :aliases => '-t', :choices => [:bacon, :shoulda]
566
+ #
567
+ def component_option(name, caption, options = {})
568
+ (@component_types ||= []) << name # TODO use ordered hash and combine with choices below
569
+ (@available_choices ||= Hash.new)[name] = options[:choices]
570
+ description = "The #{caption} component (#{options[:choices].join(', ')}, none)"
571
+ class_option name, :default => options[:default] || options[:choices].first, :aliases => options[:aliases], :desc => description
572
+ end
573
+
574
+ ##
575
+ # Definitions for the available customizable components.
576
+ #
577
+ def defines_component_options(options = {})
578
+ [
579
+ [ :orm, 'database engine', { :aliases => '-d', :default => :none }],
580
+ [ :test, 'testing framework', { :aliases => '-t', :default => :none }],
581
+ [ :mock, 'mocking library', { :aliases => '-m', :default => :none }],
582
+ [ :script, 'javascript library', { :aliases => '-s', :default => :none }],
583
+ [ :renderer, 'template engine', { :aliases => '-e', :default => :none }],
584
+ [ :stylesheet, 'stylesheet engine', { :aliases => '-c', :default => :none }]
585
+ ].each do |name, caption, opts|
586
+ opts[:default] = '' if options[:default] == false
587
+ component_option name, caption, opts.merge(:choices => Dir["#{File.dirname(__FILE__)}/components/#{name.to_s.pluralize}/*.rb"].map{|lib| File.basename(lib, '.rb').to_sym})
588
+ end
589
+ end
590
+
591
+ ##
592
+ # Tell Tennpipes that for this Thor::Group it is a necessary task to run.
593
+ #
594
+ def require_arguments!
595
+ @require_arguments = true
596
+ end
597
+
598
+ ##
599
+ # Return true if we need an arguments for our Thor::Group.
600
+ #
601
+ def require_arguments?
602
+ @require_arguments
603
+ end
604
+
605
+ ##
606
+ # Returns the compiled list of component types which can be specified.
607
+ #
608
+ def component_types
609
+ @component_types
610
+ end
611
+
612
+ ##
613
+ # Returns the list of available choices for the given component (including none).
614
+ #
615
+ # @param [Symbol] component
616
+ # The type of the component module.
617
+ #
618
+ # @return [Array<Symbol>] Array of component choices.
619
+ #
620
+ # @example
621
+ # available_choices_for :test
622
+ # => [:shoulda, :bacon, :riot, :minitest]
623
+ #
624
+ def available_choices_for(component)
625
+ @available_choices[component] + [:none]
626
+ end
627
+ end
628
+ end
629
+ end
630
+ end