rabal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/COPYING +339 -0
  2. data/LICENSE +54 -0
  3. data/README +172 -0
  4. data/README.PLUGIN +276 -0
  5. data/bin/rabal +12 -0
  6. data/lib/rabal/action_tree.rb +42 -0
  7. data/lib/rabal/application.rb +209 -0
  8. data/lib/rabal/directory_tree.rb +59 -0
  9. data/lib/rabal/error.rb +7 -0
  10. data/lib/rabal/file_tree.rb +89 -0
  11. data/lib/rabal/logger.rb +18 -0
  12. data/lib/rabal/plugin/bin.rb +8 -0
  13. data/lib/rabal/plugin/core.rb +24 -0
  14. data/lib/rabal/plugin/foundation.rb +154 -0
  15. data/lib/rabal/plugin/license.rb +36 -0
  16. data/lib/rabal/plugin/spec.rb +8 -0
  17. data/lib/rabal/plugin/test.rb +8 -0
  18. data/lib/rabal/plugin.rb +5 -0
  19. data/lib/rabal/plugin_tree.rb +61 -0
  20. data/lib/rabal/project_tree.rb +17 -0
  21. data/lib/rabal/tree.rb +231 -0
  22. data/lib/rabal/usage.rb +100 -0
  23. data/lib/rabal/util.rb +62 -0
  24. data/lib/rabal/version.rb +18 -0
  25. data/lib/rabal.rb +49 -0
  26. data/resources/trees/bin/rabal.project +10 -0
  27. data/resources/trees/core/CHANGES +4 -0
  28. data/resources/trees/core/README +15 -0
  29. data/resources/trees/core/Rakefile +0 -0
  30. data/resources/trees/core/lib/rabal.project/version.rb.erb +17 -0
  31. data/resources/trees/core/lib/rabal.project.rb.erb +27 -0
  32. data/resources/trees/license/COPYING.gpl +339 -0
  33. data/resources/trees/license/COPYING.lgpl +504 -0
  34. data/resources/trees/license/COPYING.ruby +339 -0
  35. data/resources/trees/license/LICENSE.bsd +31 -0
  36. data/resources/trees/license/LICENSE.mit +19 -0
  37. data/resources/trees/license/LICENSE.ruby +54 -0
  38. data/resources/trees/spec/rabal.project_spec.rb.erb +16 -0
  39. data/resources/trees/spec/spec_helper.rb.erb +5 -0
  40. data/resources/trees/test/rabal.project_test.rb.erb +10 -0
  41. data/resources/trees/test/test_helper.rb.erb +3 -0
  42. data/spec/action_tree_spec.rb +28 -0
  43. data/spec/bin_plugin_spec.rb +23 -0
  44. data/spec/core_plugin_spec.rb +29 -0
  45. data/spec/directory_tree_spec.rb +28 -0
  46. data/spec/file_tree_spec.rb +48 -0
  47. data/spec/license_plugin_spec.rb +39 -0
  48. data/spec/plugin_tree_spec.rb +53 -0
  49. data/spec/project_tree_spec.rb +39 -0
  50. data/spec/spec_helper.rb +59 -0
  51. data/spec/spec_plugin_spec.rb +23 -0
  52. data/spec/test_plugin_spec.rb +23 -0
  53. data/spec/tree_spec.rb +80 -0
  54. data/spec/utils_spec.rb +45 -0
  55. data/spec/version_spec.rb +26 -0
  56. metadata +134 -0
@@ -0,0 +1,18 @@
1
+ require 'logger'
2
+ module Rabal
3
+ module Log
4
+ LOGGER = Logger.new(STDOUT)
5
+ LOGGER.datetime_format = "%Y-%m-%d %H:%M:%S"
6
+
7
+
8
+ class << self
9
+ %w(debug info warn error fatal).each do |m|
10
+ module_eval <<-code
11
+ def #{ m } *a, &b
12
+ LOGGER.#{ m } *a, &b
13
+ end
14
+ code
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ require 'rabal/plugin/foundation'
2
+ module Rabal
3
+ module Plugin
4
+ class Bin < Rabal::Plugin::Base "/rabal/bin"
5
+ description "Add a commandline application."
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ require 'rabal/plugin/foundation'
2
+ module Rabal
3
+ module Plugin
4
+ class Core < Rabal::Plugin::Base "/rabal/core"
5
+ parameter "author", "Author of the project"
6
+ parameter "email", "Email address of the author"
7
+ use_always
8
+ description <<-DESC
9
+ The core functionality and baseline information needed by every project.
10
+ DESC
11
+
12
+ # core is slightly different from the default and uses a
13
+ # ProjecTree instead of a PluginTree. It does attach a
14
+ # PluginTree below the project tree with the basic file
15
+ # structure
16
+ def initialize(options)
17
+ @parameters = OpenStruct.new(options)
18
+ validate_parameters
19
+ @tree = ProjectTree.new(options[:project] || options["project"],options)
20
+ @tree << PluginTree.new({},resource_by_name(my_main_tree_name))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,154 @@
1
+ require 'rabal'
2
+ require 'rubygems'
3
+ require 'main'
4
+
5
+ module Rabal
6
+ module Plugin
7
+ #
8
+ # Base plugin that all other plugins will inherit from, but not
9
+ # directly. New plugins are declared with:
10
+ #
11
+ # class NewPlugin < Rabal::Plugin::Base "/foo/bar"
12
+ # ...
13
+ # end
14
+ #
15
+ # This process uses GemPlugin under the covers, it has just been
16
+ # wrapped to provide a different +Base+ class for everything to
17
+ # inherit from.
18
+ #
19
+ class Foundation
20
+
21
+ # the PluginTree that the plugin creates.
22
+ attr_reader :tree
23
+
24
+ class << self
25
+
26
+ # Called when another class inherits from Foundation.
27
+ # when that happens that class is registered in the
28
+ # GemPlugin::Manager
29
+ def inherited(by_class)
30
+ register_key = "/" + by_class.to_s.downcase
31
+ by_class.register_path register_as
32
+ GemPlugin::Manager.instance.register(register_as,register_key,by_class)
33
+ register_as = nil
34
+ end
35
+
36
+ # allows Plugin::Base to store the registration
37
+ # information in the class variable.
38
+ attribute :register_as => nil
39
+
40
+ # part of the mini DSL for describing a Plugin
41
+ def parameter(pname,description)
42
+ @parameters ||= {}
43
+ @parameters[pname] = [pname, description]
44
+ end
45
+
46
+ # get the parameters bac
47
+ def parameters
48
+ @parameters ||= {}
49
+ end
50
+
51
+ def use_always?
52
+ @use_always
53
+ end
54
+
55
+ def use_always(d = true)
56
+ @use_always = d
57
+ end
58
+
59
+ attribute :description => "I Need a Description"
60
+ attribute :register_path
61
+
62
+ def use_name
63
+ name.split("::").last.dashify
64
+ end
65
+ end
66
+
67
+ # A Plugin is instantiated and the options passed to it are
68
+ # the results of the command line options for this plugin.
69
+ #
70
+ # The default action for any Plugin is to create a
71
+ # PluginTree from its options utilizing the +register_path+
72
+ # to determine a location within the gem's resources. The
73
+ # resources is used to instantiate a PluginTree and that is
74
+ # set to +tree+ and by default, this tree will be 'mounted'
75
+ # at the root of some other tree.
76
+ def initialize(options = {})
77
+ @parameters = OpenStruct.new(options)
78
+ validate_parameters
79
+ main_tree_name = my_main_tree_name
80
+ @tree = PluginTree.new(options,resource_by_name(main_tree_name),
81
+ File.basename(main_tree_name))
82
+ end
83
+
84
+ ############################################################
85
+ # regular instance methods, provide for convenience to the
86
+ # child plugins
87
+ ############################################################
88
+
89
+ #
90
+ # validate the parameters of the plugin in the simplest way
91
+ # possible. Make sure that each listend parameters is not
92
+ # null. This assumes that @parameters has a method for each
93
+ # parameter naem
94
+ #
95
+ def validate_parameters
96
+ self.class.parameters.each do |param,desc|
97
+ if not @parameters.respond_to?(param) or @parameters.send(param).nil? then
98
+ raise PluginParameterMissingError, "Missing parameter '#{param}' from #{self.class.use_name} plugin. See --use-#{self.class.use_name} --help"
99
+ end
100
+ end
101
+ end
102
+ # What gem a plugin belongs to. This is necessary to access
103
+ # the resources of the gem the plugin may use. Overload
104
+ # this in a child plugin to return what you want. By
105
+ # default it uses the first part of the path the gem is
106
+ # registered under.
107
+ #
108
+ # That is when the plugin is defined
109
+ #
110
+ # class MyPlugin < Rabal::Plugin::Base "/my-plugin/something"
111
+ # ...
112
+ # end
113
+ #
114
+ # 'my-plugin' is defined as being the default gem name.
115
+ def my_gem_name
116
+ self.class.register_path.split("/").find{|p| p.length > 0}
117
+ end
118
+
119
+ # The main resource for this Plugin. This is generally a
120
+ # file or a directory that the plugin will use as a template
121
+ # and create a PluginTree from.
122
+ def my_main_tree_name
123
+ tree_name = self.class.register_path.split("/").find_all {|p| p.length > 0}
124
+ tree_name.shift
125
+ tree_name.unshift "trees"
126
+ tree_name.join("/")
127
+ end
128
+
129
+ # Access a resource utilized by the gem. The name is the
130
+ # path to a file or directory under the 'resources'
131
+ # directory in the gem this plugin is a part of.
132
+ def resource_by_name(resource_name)
133
+ Rabal.application.plugin_resource(my_gem_name,resource_name)
134
+ end
135
+ end
136
+ end
137
+
138
+ #
139
+ # This is the happen'n way to do things. Camping does it,
140
+ # GemPlugin does it. Come on You can do it too.
141
+ #
142
+ # Put +register_path+ into the class variable @@path of
143
+ # Plugin::Foundation and then return the Plugin::Foundation class
144
+ # which will be used as the parent class for the new class.
145
+ #
146
+ # Upon declaration of the new class, Foundation.inherited will be
147
+ # invoked which will register the new class with GemPlugin::Manager
148
+ # an clear out @@path
149
+ #
150
+ def Plugin::Base(register_path)
151
+ Plugin::Foundation.register_as = register_path
152
+ Plugin::Foundation
153
+ end
154
+ end
@@ -0,0 +1,36 @@
1
+ require 'rabal/plugin/foundation'
2
+ module Rabal
3
+ module Plugin
4
+ #
5
+ # The license plugin helps the user pick a license for their
6
+ # project. The current available license to choose from are
7
+ # BSD, GPL, LGPG, MIT and Ruby
8
+ #
9
+ class License < Rabal::Plugin::Base "/rabal/license"
10
+ TYPES = %w[BSD GPL LGPL MIT Ruby]
11
+ parameter "flavor", "Flavor of License for your project: #{TYPES.join(', ')}"
12
+ description "Indicate under what license your project is released."
13
+ use_always
14
+
15
+ def initialize(options)
16
+ @parameters = OpenStruct.new(options)
17
+ if not @parameters.respond_to?(:flavor) then
18
+ raise PluginParameterMissingError, "Missing parameter 'flavor' from license plugin. See --use-license --help"
19
+ end
20
+ suffix = @parameters.flavor
21
+ # look at all files in our resource directory and any
22
+ # that have the same suffix as the 'flavor' load it into
23
+ # the tree.
24
+ if TYPES.include?(suffix) then
25
+ resource_dir = resource_by_name(my_main_tree_name)
26
+ @tree = DirectoryTree.new(".")
27
+ Dir.glob(File.join(resource_dir,"*.#{suffix.downcase}")).each do |file|
28
+ @tree << FileTree.from_file(file)
29
+ end
30
+ else
31
+ raise PluginParameterMissingError, "Invalid value '#{suffix}' for 'flavor' parameter from license plugin. Only #{TYPES.join(",")} are currently supported."
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ require 'rabal/plugin/foundation'
2
+ module Rabal
3
+ module Plugin
4
+ class Spec < Rabal::Plugin::Base "/rabal/spec"
5
+ description "Add an RSpec framework."
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'rabal/plugin/foundation'
2
+ module Rabal
3
+ module Plugin
4
+ class Test < Rabal::Plugin::Base "/rabal/test"
5
+ description "Add a Test::Unit framework."
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'gem_plugin'
3
+
4
+ # load up all the builtin plugins
5
+ Rabal.require_all_libs_relative_to(__FILE__)
@@ -0,0 +1,61 @@
1
+ require 'rabal'
2
+ require 'find'
3
+ require 'rabal/util'
4
+
5
+ module Rabal
6
+ #
7
+ # Represents the root of a plugin directory structure. This plugin
8
+ # could also only represent a single FileTree by having the
9
+ # 'directory' it represents being '.'
10
+ #
11
+ class PluginTree < DirectoryTree
12
+
13
+ include Util
14
+
15
+ # the source directory from which the project is generated
16
+ attr_accessor :src_directory
17
+
18
+ # create a new Plugin Tree based upon a source directory. This
19
+ # 'mounts' the src_directory into the dest_directory in the
20
+ # project. The dest_directory defaults to "." . The +options+
21
+ # are a hash that are propogated to the +parameters+ member
22
+ # variable.
23
+ def initialize(options,src_directory,dest_directory= ".")
24
+ super(dest_directory)
25
+ @src_directory = src_directory
26
+ @parameters = OpenStruct.new(options)
27
+ end
28
+
29
+ #
30
+ # populating the tree needs to take place after the PluginTree
31
+ # has been added to the Tree, but before the processing of the
32
+ # tree takes place
33
+ #
34
+ def post_add
35
+ populate_tree(src_directory)
36
+ end
37
+
38
+ private
39
+
40
+ #
41
+ # Given a source directory populate a PluginTree based upon the
42
+ # contents of the directory. All files will be mapped to
43
+ # FileTree and directories will be mapped to DirectoryTree.
44
+ #
45
+ def populate_tree(src_directory,tree=self)
46
+ Dir.chdir(src_directory) do |pwd|
47
+ Dir.entries(".").each do |entry|
48
+ next if entry[0] == ?.
49
+ next if pwd == entry
50
+
51
+ if File.file?(entry) then
52
+ tree << FileTree.from_file(entry,true,replace_known_words(entry))
53
+ elsif File.directory?(entry) then
54
+ tree << dir = DirectoryTree.new(replace_known_words(entry))
55
+ populate_tree(entry,dir)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ require 'rabal/directory_tree'
2
+ module Rabal
3
+ #
4
+ # The ProjectTree represents the master configuration/specification
5
+ # of a project.
6
+ #
7
+ class ProjectTree < DirectoryTree
8
+
9
+ # FIXME: this should derive a whole bunch of instance variables
10
+ # and delegate items to a Gem specification.
11
+ def initialize(project_name,options)
12
+ super(project_name)
13
+ @parameters = OpenStruct.new(options)
14
+ @parameters.project_name = project_name
15
+ end
16
+ end
17
+ end
data/lib/rabal/tree.rb ADDED
@@ -0,0 +1,231 @@
1
+ require 'rabal'
2
+
3
+ module Rabal
4
+ #
5
+ # A basic Tree structure
6
+ #
7
+ class Tree
8
+
9
+ include Enumerable
10
+
11
+ # The name of this Tree
12
+ attr_accessor :name
13
+
14
+ # The parent of this node. If this is nil then this Tree is a
15
+ # root.
16
+ attr_accessor :parent
17
+
18
+ # The children of this node. If this Array is empty, then this
19
+ # Tree is a leaf.
20
+ attr_accessor :children
21
+
22
+ # An abstract data point that can be utilized by child classes
23
+ # for whatever they like. If this is non-nil and responds to
24
+ # method calls it will be searched as part of the
25
+ # 'method_missing' protocol.
26
+ attr_accessor :parameters
27
+
28
+ #
29
+ # Create a new Tree with the given object.to_s as its +name+.
30
+ #
31
+ def initialize(name)
32
+ @name = name.to_s
33
+ @parent = nil
34
+ @children = {}
35
+ @parameters = nil
36
+ end
37
+
38
+ #
39
+ # Return true if this Tree has no children.
40
+ #
41
+ def is_leaf?
42
+ @children.empty?
43
+ end
44
+
45
+ #
46
+ # Return true if this Tree has no parent.
47
+ #
48
+ def is_root?
49
+ @parent.nil?
50
+ end
51
+
52
+ #
53
+ # Return the root node of the tree
54
+ #
55
+ def root
56
+ return self if is_root?
57
+ return @parent.root
58
+ end
59
+
60
+ #
61
+ # Return the distance from the root
62
+ #
63
+ def depth
64
+ return 0 if is_root?
65
+ return (1 + @parent.depth)
66
+ end
67
+
68
+ #
69
+ # Attach the given tree at the indicated path. The path given
70
+ # is always assumed to be from the root of the Tree being
71
+ # attached to.
72
+ #
73
+ # The path is given as a string separated by '/'. Each portion
74
+ # of the string is matched against the name of the particular
75
+ # tree.
76
+ #
77
+ # Given :
78
+ #
79
+ # a --- b --- c
80
+ # \
81
+ # d - e --- f
82
+ # \
83
+ # g - h
84
+ #
85
+ # * the path +a/b/c+ will match the path to Tree +c+
86
+ # * the path +d/e/g+ will _not_ match anything as the path must start at +a+ here
87
+ # * the path +a/d/e+ will _not_ match anytthin as +e+ is not a child of +d+
88
+ # * the path +a/d/e/g+ will match node +g+
89
+ #
90
+ # Leading and trailing '/' on the path are not necessary and removed.
91
+ #
92
+ def add_at_path(path,subtree)
93
+ parent_tree = tree_at_path(path)
94
+ parent_tree << subtree
95
+ return self
96
+ end
97
+
98
+
99
+ #
100
+ # Return the Tree that resides at the given path
101
+ #
102
+ def tree_at_path(path_str)
103
+ path_str = path_str.chomp("/").reverse.chomp("/").reverse
104
+ path = path_str.split("/")
105
+
106
+ # strip of the redundant first match if it is the same as
107
+ # the current node
108
+ find_subtree(path)
109
+ end
110
+
111
+ #
112
+ # Add the given object to the Tree as a child of this node. If
113
+ # the given object is not a Tree then wrap it with a Tree.
114
+ #
115
+ def <<(subtree)
116
+ # this should not generally be the case, but wrap things
117
+ # up to be nice.
118
+ if not subtree.kind_of?(Tree) then
119
+ subtree = Tree.new(subtree)
120
+ end
121
+
122
+ subtree.parent = self
123
+
124
+ # Don't overwrite any existing children with the same name,
125
+ # just put this one's children in that one, I think this
126
+ # works recursively now.
127
+ if children.has_key?(subtree.name) then
128
+ subtree.children.each do |n,tree|
129
+ children[n] = tree
130
+ end
131
+ else
132
+ children[subtree.name] = subtree
133
+ end
134
+
135
+ subtree.post_add
136
+
137
+ return self
138
+ end
139
+
140
+ alias :add :<<
141
+
142
+ #
143
+ # Allow for Enumerable to be included. This just wraps walk.
144
+ #
145
+ def each
146
+ self.walk(self,lambda { |tree| yield tree })
147
+ end
148
+
149
+ #
150
+ # Count how many items are in the tree
151
+ #
152
+ def size
153
+ inject(0) { |count,n| count + 1 }
154
+ end
155
+
156
+ #
157
+ # Walk the tree in a depth first manner, visiting the Tree
158
+ # first, then its children
159
+ #
160
+ def walk(tree,method)
161
+ method.call(tree)
162
+ tree.children.each_pair do |name,child|
163
+ walk(child,method)
164
+ end
165
+ end
166
+
167
+ #
168
+ # Allow for a method call to cascade up the tree looking for a
169
+ # Tree that responds to the call.
170
+ #
171
+ def method_missing(method_id,*params,&block)
172
+ if not parameters.nil? and parameters.respond_to?(method_id) then
173
+ return parameters.send(method_id, *params, &block)
174
+ elsif not is_root? then
175
+ @parent.send method_id, *params, &block
176
+ else
177
+ raise NoMethodError, "undefined method `#{method_id}' for #{name}:Tree"
178
+ end
179
+ end
180
+
181
+
182
+ #
183
+ # allow for a hook so newly added Tree objects may do custom
184
+ # processing after being added to the tree, but before the tree
185
+ # is walked or processed
186
+ #
187
+ def post_add
188
+ end
189
+ #
190
+ # find the current path of the tree from root to here, return it
191
+ # as a '/' separates string.
192
+ #
193
+ def current_path
194
+ return "*#{name}*" if is_root?
195
+ return ([name,parent.current_path]).flatten.reverse.join("/")
196
+ end
197
+
198
+ #
199
+ # Given the initial path to match as an Array find the Tree that
200
+ # matches that path.
201
+ #
202
+ def find_subtree(path)
203
+
204
+ if path.empty? then
205
+ return self
206
+ else
207
+ possible_child = path.shift
208
+ if children.has_key?(possible_child) then
209
+ children[possible_child].find_subtree(path)
210
+ else
211
+ raise PathNotFoundError, "`#{possible_child}' does not match anything at the current path in the Tree (#{current_path})"
212
+ end
213
+ end
214
+ end
215
+
216
+ private
217
+
218
+ #
219
+ # Log to the Rabal::Log padding the message with 2 spaces *
220
+ # depth.
221
+ #
222
+ %w(debug info warn error fatal).each do |m|
223
+ class_eval <<-code
224
+ def #{ m }(msg)
225
+ msg = (" " * depth) + msg
226
+ Rabal::Log.#{ m }(msg)
227
+ end
228
+ code
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,100 @@
1
+ require 'main'
2
+ module Rabal
3
+
4
+ # Rabal has unique Usage output requirements and as such the default
5
+ # usage provided by the Main gem although nice are not sufficient.
6
+ #
7
+ # Rabal requires the Usage to be generated after the parameters have
8
+ # been parsed as the parameters that are on the commandline
9
+ # determine how the help is printed.
10
+ class Usage
11
+
12
+ attr_reader :app
13
+ attr_reader :old_usage
14
+
15
+ def initialize(app)
16
+ @app = app
17
+ @old_usage = {}
18
+ app.main.usage.each_pair do |key,value|
19
+ @old_usage[key] = value
20
+ end
21
+ end
22
+
23
+ # some of the generated usage is quite useful, others we want
24
+ # to dump, or rename
25
+ def to_s
26
+ u = ::Main::Usage.new
27
+ # just transfer directly over these
28
+ %w[name synopsis description].each do |chunk|
29
+ u[chunk.dup] = old_usage[chunk].to_s
30
+ end
31
+
32
+ arguments = app.main.parameters.select{|p| p.type == :argument}
33
+ global_options = app.main.parameters.select{|p| p.type == :option and app.global_option_names.include?(p.name) }
34
+ load_options = app.main.parameters.select{|p| p.type == :option and app.plugin_load_option_names.include?(p.name) }
35
+ plugin_options = app.main.parameters.select{|p| p.type == :option and app.plugin_option_names.include?(p.name) }
36
+
37
+ # rework the formatting of the parameters limiting them to
38
+ # the globals, force
39
+ u['global options'] = section_options(" ",global_options)
40
+
41
+ # format the available modules
42
+ s = ""
43
+ s << ::Main::Util.columnize("Force any module to be used by giving the --use-[modulename] option. Modules with a '*' next to them are always used.",:indent => 0, :width => 72)
44
+ s << "\n\n"
45
+ s << ""
46
+ module_options = []
47
+ app.plugin_manager.plugins.sort_by{|c,p| c}.each do |cat,plugins|
48
+ plugins.each do |key,plugin|
49
+ pre = " " + (plugin.use_always? ? "*" : " ")
50
+ s << option_format(pre,"#{plugin.use_name} (#{plugin.register_path})",plugin.description,30,32,78)
51
+ s << "\n"
52
+
53
+ # create the module options for this one, if the
54
+ # plugin is use_always.
55
+ if app.main.parameters['use-all'].given? or plugin.use_always? or
56
+ app.main.parameters["use-#{plugin.use_name}"].given? then
57
+ plugin_options = app.main.parameters.select{|p| p.type == :option and p.name =~ %r{^#{plugin.use_name}}}
58
+ module_options << ["Module options - #{plugin.use_name.camelize}", section_options(" ",plugin_options)]
59
+ end
60
+ end
61
+ end
62
+
63
+
64
+ u['Available Modules'] = s
65
+
66
+ module_options.each { |k,v| u[k] = v }
67
+
68
+ u['author'] = old_usage['author']
69
+ u.to_s
70
+ end
71
+
72
+ # take in an option and a description and some formatting
73
+ # criteria and format a single option
74
+ def option_format(pre,option,description,col1,col2,width)
75
+ s = ""
76
+ s << "#{pre}#{option}".ljust(col1)
77
+ if description then
78
+ lines = ::Main::Util.columnize(description,:indent => col2, :width => width).split("\n")
79
+ inter_first = ' ' * (col2 - col1 - 2)
80
+ s << lines.shift.sub(/^\s*/,"#{inter_first}- ")
81
+ if lines.size > 0 then
82
+ s << "\n"
83
+ s << lines.join("\n")
84
+ end
85
+ end
86
+ s
87
+ end
88
+
89
+ def section_options(pre,list)
90
+ if list.size == 0 then
91
+ return "No options available\n"
92
+ end
93
+ list.sort_by{|p| p.name}.collect do |p|
94
+ ps = ""
95
+ ps << option_format(pre,p.short_synopsis,p.description,35,39,78)
96
+ ps
97
+ end.join("\n")
98
+ end
99
+ end
100
+ end