nucleon 0.1.19 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +1 -0
  4. data/TODO.rdoc +0 -3
  5. data/VERSION +1 -1
  6. data/bin/nucleon +19 -0
  7. data/lib/core/config.rb +11 -7
  8. data/lib/core/environment.rb +338 -0
  9. data/lib/core/facade.rb +150 -98
  10. data/lib/core/manager.rb +160 -249
  11. data/lib/core/mixin/action/project.rb +2 -2
  12. data/lib/core/mixin/macro/plugin_interface.rb +11 -11
  13. data/lib/core/plugin/action.rb +277 -24
  14. data/lib/core/plugin/base.rb +22 -14
  15. data/lib/core/plugin/command.rb +1 -1
  16. data/lib/core/plugin/event.rb +3 -3
  17. data/lib/core/plugin/extension.rb +1 -1
  18. data/lib/core/plugin/project.rb +15 -15
  19. data/lib/core/plugin/template.rb +1 -1
  20. data/lib/core/plugin/translator.rb +1 -1
  21. data/lib/core/util/cache.rb +1 -1
  22. data/lib/core/util/cli.rb +32 -3
  23. data/lib/core/util/console.rb +30 -10
  24. data/lib/core/util/data.rb +11 -3
  25. data/lib/core/util/logger.rb +1 -1
  26. data/lib/core/util/shell.rb +6 -3
  27. data/lib/core/util/ssh.rb +148 -24
  28. data/lib/nucleon/action/extract.rb +11 -4
  29. data/lib/nucleon/action/{add.rb → project/add.rb} +13 -4
  30. data/lib/nucleon/action/{create.rb → project/create.rb} +12 -3
  31. data/lib/nucleon/action/{remove.rb → project/remove.rb} +11 -2
  32. data/lib/nucleon/action/{save.rb → project/save.rb} +11 -2
  33. data/lib/nucleon/action/{update.rb → project/update.rb} +11 -2
  34. data/lib/nucleon/command/bash.rb +1 -1
  35. data/lib/nucleon/event/regex.rb +1 -1
  36. data/lib/nucleon/project/git.rb +3 -3
  37. data/lib/nucleon/template/{json.rb → JSON.rb} +1 -1
  38. data/lib/nucleon/template/{yaml.rb → YAML.rb} +1 -1
  39. data/lib/nucleon/template/wrapper.rb +1 -1
  40. data/lib/nucleon/translator/{json.rb → JSON.rb} +1 -1
  41. data/lib/nucleon/translator/{yaml.rb → YAML.rb} +1 -1
  42. data/lib/nucleon_base.rb +26 -15
  43. data/locales/en.yml +69 -44
  44. data/nucleon.gemspec +129 -11
  45. data/rdoc/site/0.1.19/ARCHITECTURE_rdoc.html +634 -0
  46. data/rdoc/site/0.1.19/Hash.html +347 -0
  47. data/rdoc/site/0.1.19/Kernel.html +413 -0
  48. data/rdoc/site/0.1.19/Nucleon.html +570 -0
  49. data/rdoc/site/0.1.19/Nucleon/Action.html +280 -0
  50. data/rdoc/site/0.1.19/Nucleon/Action/Add.html +458 -0
  51. data/rdoc/site/0.1.19/Nucleon/Action/Create.html +415 -0
  52. data/rdoc/site/0.1.19/Nucleon/Action/Extract.html +413 -0
  53. data/rdoc/site/0.1.19/Nucleon/Action/Remove.html +461 -0
  54. data/rdoc/site/0.1.19/Nucleon/Action/Save.html +434 -0
  55. data/rdoc/site/0.1.19/Nucleon/Action/Update.html +381 -0
  56. data/rdoc/site/0.1.19/Nucleon/Codes.html +563 -0
  57. data/rdoc/site/0.1.19/Nucleon/Command.html +275 -0
  58. data/rdoc/site/0.1.19/Nucleon/Command/Bash.html +544 -0
  59. data/rdoc/site/0.1.19/Nucleon/Config.html +1623 -0
  60. data/rdoc/site/0.1.19/Nucleon/Config/Collection.html +509 -0
  61. data/rdoc/site/0.1.19/Nucleon/Config/Options.html +489 -0
  62. data/rdoc/site/0.1.19/Nucleon/Core.html +635 -0
  63. data/rdoc/site/0.1.19/Nucleon/Errors.html +275 -0
  64. data/rdoc/site/0.1.19/Nucleon/Errors/BatchError.html +281 -0
  65. data/rdoc/site/0.1.19/Nucleon/Errors/NucleonError.html +657 -0
  66. data/rdoc/site/0.1.19/Nucleon/Errors/SSHUnavailable.html +281 -0
  67. data/rdoc/site/0.1.19/Nucleon/Event.html +275 -0
  68. data/rdoc/site/0.1.19/Nucleon/Event/Regex.html +467 -0
  69. data/rdoc/site/0.1.19/Nucleon/Facade.html +2336 -0
  70. data/rdoc/site/0.1.19/Nucleon/Gems.html +635 -0
  71. data/rdoc/site/0.1.19/Nucleon/Manager.html +1828 -0
  72. data/rdoc/site/0.1.19/Nucleon/Mixin.html +284 -0
  73. data/rdoc/site/0.1.19/Nucleon/Mixin/Action.html +277 -0
  74. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Commit.html +381 -0
  75. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Project.html +395 -0
  76. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Push.html +371 -0
  77. data/rdoc/site/0.1.19/Nucleon/Mixin/Colors.html +545 -0
  78. data/rdoc/site/0.1.19/Nucleon/Mixin/ConfigCollection.html +481 -0
  79. data/rdoc/site/0.1.19/Nucleon/Mixin/ConfigOptions.html +449 -0
  80. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro.html +276 -0
  81. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro/ObjectInterface.html +695 -0
  82. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro/PluginInterface.html +682 -0
  83. data/rdoc/site/0.1.19/Nucleon/Mixin/Settings.html +481 -0
  84. data/rdoc/site/0.1.19/Nucleon/Mixin/SubConfig.html +887 -0
  85. data/rdoc/site/0.1.19/Nucleon/Parallel.html +325 -0
  86. data/rdoc/site/0.1.19/Nucleon/Parallel/ClassMethods.html +325 -0
  87. data/rdoc/site/0.1.19/Nucleon/Parallel/InstanceMethods.html +334 -0
  88. data/rdoc/site/0.1.19/Nucleon/Plugin.html +282 -0
  89. data/rdoc/site/0.1.19/Nucleon/Plugin/Action.html +1368 -0
  90. data/rdoc/site/0.1.19/Nucleon/Plugin/Action/Option.html +459 -0
  91. data/rdoc/site/0.1.19/Nucleon/Plugin/Base.html +1737 -0
  92. data/rdoc/site/0.1.19/Nucleon/Plugin/Command.html +721 -0
  93. data/rdoc/site/0.1.19/Nucleon/Plugin/Event.html +442 -0
  94. data/rdoc/site/0.1.19/Nucleon/Plugin/Extension.html +281 -0
  95. data/rdoc/site/0.1.19/Nucleon/Plugin/Project.html +2864 -0
  96. data/rdoc/site/0.1.19/Nucleon/Plugin/Template.html +476 -0
  97. data/rdoc/site/0.1.19/Nucleon/Plugin/Translator.html +371 -0
  98. data/rdoc/site/0.1.19/Nucleon/Project.html +276 -0
  99. data/rdoc/site/0.1.19/Nucleon/Project/Git.html +1801 -0
  100. data/rdoc/site/0.1.19/Nucleon/Project/Github.html +549 -0
  101. data/rdoc/site/0.1.19/Nucleon/Template.html +277 -0
  102. data/rdoc/site/0.1.19/Nucleon/Template/Json.html +329 -0
  103. data/rdoc/site/0.1.19/Nucleon/Template/Wrapper.html +329 -0
  104. data/rdoc/site/0.1.19/Nucleon/Template/Yaml.html +329 -0
  105. data/rdoc/site/0.1.19/Nucleon/Translator.html +276 -0
  106. data/rdoc/site/0.1.19/Nucleon/Translator/Json.html +366 -0
  107. data/rdoc/site/0.1.19/Nucleon/Translator/Yaml.html +366 -0
  108. data/rdoc/site/0.1.19/Nucleon/Util.html +285 -0
  109. data/rdoc/site/0.1.19/Nucleon/Util/CLI.html +388 -0
  110. data/rdoc/site/0.1.19/Nucleon/Util/CLI/Parser.html +1183 -0
  111. data/rdoc/site/0.1.19/Nucleon/Util/Cache.html +780 -0
  112. data/rdoc/site/0.1.19/Nucleon/Util/Console.html +1294 -0
  113. data/rdoc/site/0.1.19/Nucleon/Util/Data.html +1399 -0
  114. data/rdoc/site/0.1.19/Nucleon/Util/Disk.html +522 -0
  115. data/rdoc/site/0.1.19/Nucleon/Util/Git.html +361 -0
  116. data/rdoc/site/0.1.19/Nucleon/Util/Liquid.html +365 -0
  117. data/rdoc/site/0.1.19/Nucleon/Util/Logger.html +806 -0
  118. data/rdoc/site/0.1.19/Nucleon/Util/Package.html +558 -0
  119. data/rdoc/site/0.1.19/Nucleon/Util/SSH.html +910 -0
  120. data/rdoc/site/0.1.19/Nucleon/Util/SSH/Keypair.html +453 -0
  121. data/rdoc/site/0.1.19/Nucleon/Util/Shell.html +686 -0
  122. data/rdoc/site/0.1.19/Nucleon/Util/Shell/Result.html +497 -0
  123. data/rdoc/site/0.1.19/README_rdoc.html +312 -0
  124. data/rdoc/site/0.1.19/TODO_rdoc.html +267 -0
  125. data/rdoc/site/0.1.19/created.rid +60 -0
  126. data/rdoc/site/0.1.19/images/add.png +0 -0
  127. data/rdoc/site/0.1.19/images/brick.png +0 -0
  128. data/rdoc/site/0.1.19/images/brick_link.png +0 -0
  129. data/rdoc/site/0.1.19/images/bug.png +0 -0
  130. data/rdoc/site/0.1.19/images/bullet_black.png +0 -0
  131. data/rdoc/site/0.1.19/images/bullet_toggle_minus.png +0 -0
  132. data/rdoc/site/0.1.19/images/bullet_toggle_plus.png +0 -0
  133. data/rdoc/site/0.1.19/images/date.png +0 -0
  134. data/rdoc/site/0.1.19/images/delete.png +0 -0
  135. data/rdoc/site/0.1.19/images/find.png +0 -0
  136. data/rdoc/site/0.1.19/images/loadingAnimation.gif +0 -0
  137. data/rdoc/site/0.1.19/images/macFFBgHack.png +0 -0
  138. data/rdoc/site/0.1.19/images/package.png +0 -0
  139. data/rdoc/site/0.1.19/images/page_green.png +0 -0
  140. data/rdoc/site/0.1.19/images/page_white_text.png +0 -0
  141. data/rdoc/site/0.1.19/images/page_white_width.png +0 -0
  142. data/rdoc/site/0.1.19/images/plugin.png +0 -0
  143. data/rdoc/site/0.1.19/images/ruby.png +0 -0
  144. data/rdoc/site/0.1.19/images/tag_blue.png +0 -0
  145. data/rdoc/site/0.1.19/images/tag_green.png +0 -0
  146. data/rdoc/site/0.1.19/images/transparent.png +0 -0
  147. data/rdoc/site/0.1.19/images/wrench.png +0 -0
  148. data/rdoc/site/0.1.19/images/wrench_orange.png +0 -0
  149. data/rdoc/site/0.1.19/images/zoom.png +0 -0
  150. data/rdoc/site/0.1.19/index.html +311 -0
  151. data/rdoc/site/0.1.19/js/darkfish.js +155 -0
  152. data/rdoc/site/0.1.19/js/jquery.js +18 -0
  153. data/rdoc/site/0.1.19/js/navigation.js +142 -0
  154. data/rdoc/site/0.1.19/js/search.js +94 -0
  155. data/rdoc/site/0.1.19/js/search_index.js +1 -0
  156. data/rdoc/site/0.1.19/js/searcher.js +228 -0
  157. data/rdoc/site/0.1.19/rdoc.css +543 -0
  158. data/rdoc/site/0.1.19/table_of_contents.html +1541 -0
  159. metadata +140 -11
@@ -8,7 +8,7 @@ module Project
8
8
  # Settings
9
9
 
10
10
  def project_config
11
- project_plugins = Nucleon.loaded_plugins(:project)
11
+ project_plugins = Nucleon.loaded_plugins(:nucleon, :project)
12
12
 
13
13
  register :project_provider, :str, :git, 'nucleon.core.mixin.action.project.options.project_provider' do |value|
14
14
  value = value.to_sym
@@ -21,7 +21,7 @@ module Project
21
21
  end
22
22
  register :project_reference, :str, nil, 'nucleon.core.mixin.action.project.options.project_reference' do |value|
23
23
  success = true
24
- if info = Nucleon.plugin_class(:project).translate_reference(value)
24
+ if info = Nucleon.plugin_class(:nucleon, :project).translate_reference(value)
25
25
  if ! project_plugins.keys.include?(info[:provider].to_sym)
26
26
  warn('nucleon.core.mixin.action.project.errors.project_reference', {
27
27
  :value => value,
@@ -18,7 +18,7 @@ module PluginInterface
18
18
  #-----------------------------------------------------------------------------
19
19
  # Plugin collections
20
20
 
21
- def plugin_collection(_type, _method_options = {})
21
+ def plugin_collection(_namespace, _type, _method_options = {})
22
22
  _method_config = Config.ensure(_method_options)
23
23
  _method_config.set(:plugin, true)
24
24
 
@@ -29,7 +29,7 @@ module PluginInterface
29
29
 
30
30
  @@object_types[_type] = _method_config
31
31
 
32
- logger.debug("Creating new plugin collection #{_type} with: #{_method_config.inspect}")
32
+ logger.debug("Creating new plugin collection #{_namespace} #{_type}")
33
33
 
34
34
  #---------------------------------------------------------------------------
35
35
 
@@ -95,7 +95,7 @@ module PluginInterface
95
95
  data = get_hash(_plural) unless data
96
96
 
97
97
  providers = [ providers ] if providers && ! providers.is_a?(Array)
98
- providers.collect! { |elem| elem.to_sym }
98
+ providers.collect! { |elem| elem.to_sym } if providers
99
99
 
100
100
  logger.debug("Initializing #{_plugin_type} plugin data: #{data.inspect}")
101
101
  logger.debug("Providers: #{providers.inspect}")
@@ -105,7 +105,7 @@ module PluginInterface
105
105
  if _single_instance
106
106
  logger.debug("Initializing single instance plugin: #{instance_settings.inspect}")
107
107
 
108
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(instance_settings).import({ :meta => { :parent => myself }, :new => true }))
108
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(instance_settings).import({ :meta => { :parent => myself }, :new => true }))
109
109
 
110
110
  _set([ _plural, provider ], plugin)
111
111
  else
@@ -113,7 +113,7 @@ module PluginInterface
113
113
  if name != :settings
114
114
  logger.debug("Initializing plugin #{_plugin_type} #{name}: #{options.inspect}")
115
115
 
116
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
116
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
117
117
 
118
118
  _set([ _plural, provider, name ], plugin)
119
119
  end
@@ -139,14 +139,14 @@ module PluginInterface
139
139
  if _single_instance
140
140
  logger.debug("Setting single #{_plugin_type} #{provider}: #{instance_settings.inspect}")
141
141
 
142
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(instance_settings).import({ :meta => { :parent => myself }, :new => true }))
142
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(instance_settings).import({ :meta => { :parent => myself }, :new => true }))
143
143
 
144
144
  _set([ _plural, provider ], plugin)
145
145
  else
146
146
  instance_settings.each do |name, options|
147
147
  logger.debug("Setting #{_plugin_type} #{provider} #{name}: #{options.inspect}")
148
148
 
149
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
149
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
150
150
 
151
151
  _set([ _plural, provider, name ], plugin)
152
152
  end
@@ -200,7 +200,7 @@ module PluginInterface
200
200
  options = get([ _plural, provider ], nil)
201
201
 
202
202
  unless options.nil?
203
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :meta => { :parent => myself }, :new => true }))
203
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :meta => { :parent => myself }, :new => true }))
204
204
 
205
205
  logger.debug("Initializing plugin #{_plugin_type} #{provider}: #{options.inspect}")
206
206
 
@@ -219,7 +219,7 @@ module PluginInterface
219
219
 
220
220
  set([ _plural, provider ], options)
221
221
 
222
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :meta => { :parent => myself }, :new => true }))
222
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :meta => { :parent => myself }, :new => true }))
223
223
 
224
224
  logger.debug("Setting single #{_plugin_type} #{provider}: #{options.inspect}")
225
225
 
@@ -299,7 +299,7 @@ module PluginInterface
299
299
  options = get([ _plural, provider, name ], nil)
300
300
 
301
301
  unless options.nil?
302
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
302
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
303
303
 
304
304
  logger.debug("Initializing plugin #{_plugin_type} #{provider}: #{options.inspect}")
305
305
 
@@ -317,7 +317,7 @@ module PluginInterface
317
317
  options = Config.ensure(options).export
318
318
 
319
319
  set([ _plural, provider, name ], options)
320
- plugin = Nucleon.plugin(_plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
320
+ plugin = Nucleon.plugin(_namespace, _plugin_type, provider, Config.ensure(options).import({ :name => name, :meta => { :parent => myself }, :new => true }))
321
321
 
322
322
  logger.debug("Setting #{_plugin_type} #{provider} #{name}: #{options.inspect}")
323
323
 
@@ -1,7 +1,38 @@
1
1
 
2
2
  module Nucleon
3
3
  module Plugin
4
- class Action < Base
4
+ class Action < Nucleon.plugin_class(:nucleon, :base)
5
+
6
+ extend Mixin::Colors
7
+
8
+ #-----------------------------------------------------------------------------
9
+ # Info
10
+
11
+ def self.describe(group = nil, action = 'unknown', weight = -1000, description = nil, help = nil)
12
+ if group
13
+ group_name = Util::Data.array(group).join('.')
14
+ description_id = "#{namespace}.action.#{group_name}.#{action}.description"
15
+ help_id = "#{namespace}.action.#{group_name}.#{action}.help"
16
+ else
17
+ description_id = "#{namespace}.action.#{action}.description"
18
+ help_id = "#{namespace}.action.#{action}.help"
19
+ end
20
+
21
+ {
22
+ :namespace => namespace,
23
+ :weight => weight,
24
+ :group => group,
25
+ :action => action,
26
+ :description => description ? description : I18n.t(description_id),
27
+ :help => help ? help : I18n.t(help_id)
28
+ }
29
+ end
30
+
31
+ #---
32
+
33
+ def self.namespace
34
+ :nucleon
35
+ end
5
36
 
6
37
  #-----------------------------------------------------------------------------
7
38
  # Default option interface
@@ -46,7 +77,7 @@ class Action < Base
46
77
  exit_status = action.execute
47
78
  action_result = action.result
48
79
 
49
- rescue Exception => error
80
+ rescue => error
50
81
  logger.error("Nucleon action #{provider} experienced an error:")
51
82
  logger.error(error.inspect)
52
83
  logger.error(error.message)
@@ -57,8 +88,6 @@ class Action < Base
57
88
  exit_status = error.status_code if error.respond_to?(:status_code)
58
89
  end
59
90
 
60
- Nucleon.remove_plugin(action) if action
61
-
62
91
  exit_status = Nucleon.code.unknown_status unless exit_status.is_a?(Integer)
63
92
  { :status => exit_status, :result => action_result }
64
93
  end
@@ -114,8 +143,21 @@ class Action < Base
114
143
  #-----------------------------------------------------------------------------
115
144
  # Property accessor / modifiers
116
145
 
146
+ def index_config
147
+ action_info = nil
148
+ self.class.action_index(false).export.each do |action_id, info|
149
+ if info[:provider] == plugin_provider
150
+ action_info = info
151
+ break
152
+ end
153
+ end
154
+ Config.ensure(action_info)
155
+ end
156
+
157
+ #---
158
+
117
159
  def namespace
118
- :nucleon
160
+ self.class.namespace
119
161
  end
120
162
 
121
163
  #---
@@ -177,21 +219,33 @@ class Action < Base
177
219
  #---
178
220
 
179
221
  def configure
180
- register :color, :bool, true, 'nucleon.core.action.options.color'
222
+ action_info = index_config
181
223
 
182
- yield if block_given?
224
+ yield(action_info) if block_given?
225
+
226
+ group = array(action_info[:description][:group])
227
+ action = cyan(action_info[:description][:action])
228
+
229
+ if ! group.empty?
230
+ group = green(group.join(' ').strip)
231
+ usage = "#{group} #{action} "
232
+ else
233
+ usage = "#{action} "
234
+ end
183
235
 
184
- usage = "#{plugin_provider} "
185
236
  arguments.each do |arg|
186
237
  arg_config = config[arg.to_sym]
187
238
 
239
+ arg_prefix = arg_config.default ? '[' : ''
240
+ arg_suffix = arg_config.default ? ']' : ''
241
+
188
242
  if arg_config.type == :array
189
- usage << "<#{arg}> ..."
243
+ usage << "#{arg_prefix}<#{arg}> ...#{arg_suffix}"
190
244
  else
191
- usage << "<#{arg}> "
245
+ usage << "#{arg_prefix}<#{arg}>#{arg_suffix} "
192
246
  end
193
247
  end
194
- myself.usage = usage
248
+ myself.usage = yellow(usage)
195
249
  myself
196
250
  end
197
251
 
@@ -228,7 +282,14 @@ class Action < Base
228
282
  def parse_base(args)
229
283
  logger.info("Parsing action #{plugin_provider} with: #{args.inspect}")
230
284
 
231
- @parser = Util::CLI::Parser.new(args, usage) do |parser|
285
+ action_info = index_config
286
+
287
+ help_text = ''
288
+ action_info[:description][:help].split("\n").each do |line|
289
+ help_text << ' ' + line + "\n"
290
+ end
291
+
292
+ @parser = Util::CLI::Parser.new(args, usage, "\n#{help_text}\n") do |parser|
232
293
  parse(parser)
233
294
  extension(:parse, { :parser => parser, :config => config })
234
295
  end
@@ -237,11 +298,11 @@ class Action < Base
237
298
  if @parser.processed
238
299
  set(:processed, true)
239
300
  settings.import(Util::Data.merge([ @parser.options, @parser.arguments ], true))
240
- logger.debug("Parse successful: #{export.inspect}")
301
+ logger.debug("Parse successful")
241
302
 
242
303
  elsif @parser.options[:help] && ! quiet?
243
304
  executable = delete(:executable, '')
244
- puts I18n.t('nucleon.core.exec.help.usage') + ": #{executable} " + help + "\n"
305
+ puts I18n.t('nucleon.core.exec.help.usage') + ": " + executable.to_s + ' ' + help + "\n"
245
306
 
246
307
  else
247
308
  if @parser.options[:help]
@@ -256,7 +317,7 @@ class Action < Base
256
317
  #---
257
318
 
258
319
  def parse(parser)
259
-
320
+
260
321
  generate = lambda do |format, name|
261
322
  formats = [ :option, :arg ]
262
323
  types = [ :bool, :int, :float, :str, :array ]
@@ -329,17 +390,13 @@ class Action < Base
329
390
  myself.status = code.success
330
391
  myself.result = nil
331
392
 
332
- # TODO: Figure out how to deal with paralleization of actions with global ui settings
333
- use_colors = Util::Console.use_colors
334
- Util::Console.use_colors = @parser.options[:color]
335
-
336
393
  if processed?
337
394
  begin
338
395
  if skip_validate || validate
339
396
  yield if block_given? && ( skip_hooks || extension_check(:exec_init) )
340
397
  myself.status = extension_set(:exec_exit, myself.status) unless skip_hooks
341
398
  else
342
- puts "\n" + I18n.t('corl.core.exec.help.usage') + ': ' + help + "\n" unless quiet?
399
+ puts "\n" + I18n.t('nucleon.core.exec.help.usage') + ': ' + help + "\n" unless quiet?
343
400
  myself.status = code.validation_failed
344
401
  end
345
402
  ensure
@@ -356,14 +413,11 @@ class Action < Base
356
413
  myself.status = code.unknown_status unless status.is_a?(Integer)
357
414
 
358
415
  if processed? && status != code.success
359
- logger.warn("Execution failed for #{plugin_provider} with status #{status}: #{export.inspect}")
416
+ logger.warn("Execution failed for #{plugin_provider} with status #{status}")
360
417
  alert(Codes.render_index(status))
361
418
  end
362
419
 
363
420
  status
364
-
365
- ensure
366
- Util::Console.use_colors = use_colors
367
421
  end
368
422
 
369
423
  #---
@@ -389,6 +443,205 @@ class Action < Base
389
443
  def render_options
390
444
  settings
391
445
  end
446
+
447
+ #-----------------------------------------------------------------------------
448
+ # Utilities
449
+
450
+ def self.components(search)
451
+ components = []
452
+
453
+ array(search).each do |element|
454
+ break if element.match(/^\-+/)
455
+ components << element
456
+ end
457
+ components
458
+ end
459
+
460
+ #---
461
+
462
+ def self.action_index(tree = true)
463
+ action_config = Config.new
464
+ action_index = Config.new
465
+
466
+ generate_index = lambda do |info, parents = nil|
467
+ groups = info.keys - [ :_weight, :_weights ]
468
+ groups = groups.sort do |a, b|
469
+ info[b][:_weight] <=> info[a][:_weight]
470
+ end
471
+
472
+ groups.each do |group|
473
+ data = info[group]
474
+
475
+ if data.is_a?(Hash) && data.has_key?(:_weights)
476
+ sub_parents = parents.nil? ? [ group ] : [ parents, group ].flatten
477
+ generate_index.call(data, sub_parents)
478
+ else
479
+ keys = tree ? [ parents, group ] : [ parents, group ].flatten.join('::')
480
+ action_index.set(keys, data)
481
+ end
482
+ end
483
+ end
484
+
485
+ Nucleon.loaded_plugins(:nucleon, :action).each do |provider, data|
486
+ description = data[:class].describe
487
+ data[:description] = description
488
+ data[:_weight] = description[:weight]
489
+
490
+ keys = [ description[:namespace], description[:group], description[:action] ].flatten.compact
491
+ action_config.set(keys, data)
492
+
493
+ keys.pop
494
+
495
+ while ! keys.empty?
496
+ group_config = action_config.get(keys)
497
+
498
+ if group_config.has_key?(:_weights)
499
+ group_config[:_weights].push(description[:weight])
500
+ else
501
+ action_config.set([ keys, :_weights ], [ description[:weight] ])
502
+ end
503
+ action_config.set([ keys, :_weight ], group_config[:_weights].inject(0.0) { |sum, el| sum + el } / group_config[:_weights].size)
504
+ keys.pop
505
+ end
506
+ end
507
+
508
+ generate_index.call(action_config.export)
509
+ action_index
510
+ end
511
+
512
+ #---
513
+
514
+ def self.search_actions(search_components)
515
+ action_components = components(search_components)
516
+ action_index = action_index(false).export
517
+ actions_found = []
518
+ final_components = []
519
+
520
+ search_action = lambda do |components|
521
+ unless components.empty?
522
+ action_id = components.is_a?(Array) ? components.flatten.join('::') : components
523
+ action_id_pattern = action_id.gsub('::', ':.*:')
524
+
525
+ action_index.each do |loaded_action_id, loaded_action_info|
526
+ if loaded_action_id.match(/#{action_id_pattern}/)
527
+ loaded_action_info[:action_id] = loaded_action_id
528
+ actions_found << loaded_action_info
529
+ end
530
+ end
531
+ end
532
+ if components.is_a?(Array) && ! components.empty? && actions_found.empty?
533
+ components.pop
534
+ final_components = components
535
+ search_action.call(components)
536
+ else
537
+ final_components = components
538
+ end
539
+ end
540
+
541
+ search_action.call(action_components) unless action_components.empty?
542
+
543
+ { :actions => actions_found.size == 1 ? actions_found[0] : actions_found,
544
+ :components => final_components
545
+ }
546
+ end
547
+
548
+ #---
549
+
550
+ def self.action_help(action = nil, extended_help = false)
551
+ action_index = action_index(false).export
552
+ provider_index = {}
553
+ processed_actions = {}
554
+
555
+ last_namespace = nil
556
+ last_group = nil
557
+ multiple_found = false
558
+
559
+ command_width = 0
560
+ namespace_command_width = {}
561
+
562
+ output = ''
563
+
564
+ if action
565
+ if action.empty?
566
+ output << cyan(sprintf("\n%s\n", I18n.t('nucleon.core.exec.help.no_actions_found')))
567
+ else
568
+ multiple_found = true
569
+ output << cyan(sprintf("\n%s\n", I18n.t('nucleon.core.exec.help.multiple_actions_found')))
570
+
571
+ action.each do |info|
572
+ provider_index[info[:provider]] = true
573
+ end
574
+ end
575
+ end
576
+
577
+ action_index.each do |action_id, info|
578
+ if ! multiple_found || provider_index.has_key?(info[:provider])
579
+ action = Nucleon.action(info[:provider], { :settings => {}, :quiet => true })
580
+ command_text = action.help
581
+
582
+ command_size = command_text.gsub(/\e\[(\d+)m/, '').size
583
+ command_width = [ command_width, command_size + 2 ].max
584
+
585
+ namespace = info[:description][:namespace]
586
+
587
+ namespace_command_width[namespace] = 0 unless namespace_command_width.has_key?(namespace)
588
+ namespace_command_width[namespace] = [ namespace_command_width[namespace], command_size + 2 ].max
589
+
590
+ if extended_help
591
+ help_text = ''
592
+ info[:description][:help].split("\n").each do |line|
593
+ break if ! help_text.empty? && line.empty?
594
+ help_text << ' ' + line + "\n"
595
+ end
596
+ else
597
+ help_text = nil
598
+ end
599
+
600
+ processed_actions[action_id] = {
601
+ :info => info,
602
+ :command => command_text,
603
+ :help => help_text
604
+ }
605
+ end
606
+ end
607
+
608
+ processed_actions.each do |action_id, info|
609
+ command_text = info[:command]
610
+ help_text = info[:help]
611
+ info = info[:info]
612
+ namespace = info[:description][:namespace]
613
+ group = info[:description][:group]
614
+
615
+ group_id = group.is_a?(Array) ? group.flatten.join('::') : group
616
+ group_id = '' unless group_id
617
+
618
+ output << "\n" if group_id != last_group
619
+
620
+ if namespace != last_namespace
621
+ output << "\n----------------------------------------------------\n" if help_text
622
+ output << sprintf("\n %s:\n\n", I18n.t('nucleon.core.exec.help.action_group', { :namespace => purple(namespace) }))
623
+ end
624
+
625
+ if help_text
626
+ output << " " + render_colorized(command_text, namespace_command_width[namespace]) + " -- " + blue(info[:description][:description]) + "\n"
627
+ output << "\n#{help_text}\n"
628
+ else
629
+ output << " " + render_colorized(command_text, command_width) + " -- " + blue(info[:description][:description]) + "\n"
630
+ end
631
+
632
+ last_namespace = namespace
633
+ last_group = group_id
634
+ end
635
+ output
636
+ end
637
+
638
+ #---
639
+
640
+ def self.render_colorized(text, length = 0)
641
+ command_size = text.gsub(/\e\[(\d+)m/, '').size
642
+ remaining = [ length - command_size, 0 ].max
643
+ text + sprintf("%#{remaining}s", ' ')
644
+ end
392
645
  end
393
646
  end
394
647
  end