tennpipes-init 3.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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