nucleon 0.1.19 → 0.2.0

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 (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