bundler 0.9.0.pre5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

@@ -1,101 +0,0 @@
1
- require 'thor/actions/empty_directory'
2
-
3
- class Thor
4
- module Actions
5
-
6
- # Injects the given content into a file. Different from gsub_file, this
7
- # method is reversible.
8
- #
9
- # ==== Parameters
10
- # destination<String>:: Relative path to the destination root
11
- # data<String>:: Data to add to the file. Can be given as a block.
12
- # config<Hash>:: give :verbose => false to not log the status and the flag
13
- # for injection (:after or :before).
14
- #
15
- # ==== Examples
16
- #
17
- # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n"
18
- #
19
- # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do
20
- # gems = ask "Which gems would you like to add?"
21
- # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
22
- # end
23
- #
24
- def inject_into_file(destination, *args, &block)
25
- if block_given?
26
- data, config = block, args.shift
27
- else
28
- data, config = args.shift, args.shift
29
- end
30
- action InjectIntoFile.new(self, destination, data, config)
31
- end
32
-
33
- class InjectIntoFile < EmptyDirectory #:nodoc:
34
- attr_reader :replacement, :flag, :behavior
35
-
36
- def initialize(base, destination, data, config)
37
- super(base, destination, { :verbose => true }.merge(config))
38
-
39
- @behavior, @flag = if @config.key?(:after)
40
- [:after, @config.delete(:after)]
41
- else
42
- [:before, @config.delete(:before)]
43
- end
44
-
45
- @replacement = data.is_a?(Proc) ? data.call : data
46
- @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
47
- end
48
-
49
- def invoke!
50
- say_status :invoke
51
-
52
- content = if @behavior == :after
53
- '\0' + replacement
54
- else
55
- replacement + '\0'
56
- end
57
-
58
- replace!(/#{flag}/, content)
59
- end
60
-
61
- def revoke!
62
- say_status :revoke
63
-
64
- regexp = if @behavior == :after
65
- content = '\1\2'
66
- /(#{flag})(.*)(#{Regexp.escape(replacement)})/m
67
- else
68
- content = '\2\3'
69
- /(#{Regexp.escape(replacement)})(.*)(#{flag})/m
70
- end
71
-
72
- replace!(regexp, content)
73
- end
74
-
75
- protected
76
-
77
- def say_status(behavior)
78
- status = if flag == /\A/
79
- behavior == :invoke ? :prepend : :unprepend
80
- elsif flag == /\z/
81
- behavior == :invoke ? :append : :unappend
82
- else
83
- behavior == :invoke ? :inject : :deinject
84
- end
85
-
86
- super(status, config[:verbose])
87
- end
88
-
89
- # Adds the content to the file.
90
- #
91
- def replace!(regexp, string)
92
- unless base.options[:pretend]
93
- content = File.binread(destination)
94
- content.gsub!(regexp, string)
95
- File.open(destination, 'wb') { |file| file.write(content) }
96
- end
97
- end
98
-
99
- end
100
- end
101
- end
@@ -1,267 +0,0 @@
1
- # Thor has a special class called Thor::Group. The main difference to Thor class
2
- # is that it invokes all tasks at once. It also include some methods that allows
3
- # invocations to be done at the class method, which are not available to Thor
4
- # tasks.
5
- #
6
- class Thor::Group
7
- class << self
8
- # The descrition for this Thor::Group. If none is provided, but a source root
9
- # exists, tries to find the USAGE one folder above it, otherwise searches
10
- # in the superclass.
11
- #
12
- # ==== Parameters
13
- # description<String>:: The description for this Thor::Group.
14
- #
15
- def desc(description=nil)
16
- case description
17
- when nil
18
- @desc ||= from_superclass(:desc, nil)
19
- else
20
- @desc = description
21
- end
22
- end
23
-
24
- # Start works differently in Thor::Group, it simply invokes all tasks
25
- # inside the class.
26
- #
27
- def start(given_args=ARGV, config={})
28
- super do
29
- if Thor::HELP_MAPPINGS.include?(given_args.first)
30
- help(config[:shell])
31
- return
32
- end
33
-
34
- args, opts = Thor::Options.split(given_args)
35
- new(args, opts, config).invoke
36
- end
37
- end
38
-
39
- # Prints help information.
40
- #
41
- # ==== Options
42
- # short:: When true, shows only usage.
43
- #
44
- def help(shell)
45
- shell.say "Usage:"
46
- shell.say " #{banner}\n"
47
- shell.say
48
- class_options_help(shell)
49
- shell.say self.desc if self.desc
50
- end
51
-
52
- # Stores invocations for this class merging with superclass values.
53
- #
54
- def invocations #:nodoc:
55
- @invocations ||= from_superclass(:invocations, {})
56
- end
57
-
58
- # Stores invocation blocks used on invoke_from_option.
59
- #
60
- def invocation_blocks #:nodoc:
61
- @invocation_blocks ||= from_superclass(:invocation_blocks, {})
62
- end
63
-
64
- # Invoke the given namespace or class given. It adds an instance
65
- # method that will invoke the klass and task. You can give a block to
66
- # configure how it will be invoked.
67
- #
68
- # The namespace/class given will have its options showed on the help
69
- # usage. Check invoke_from_option for more information.
70
- #
71
- def invoke(*names, &block)
72
- options = names.last.is_a?(Hash) ? names.pop : {}
73
- verbose = options.fetch(:verbose, true)
74
-
75
- names.each do |name|
76
- invocations[name] = false
77
- invocation_blocks[name] = block if block_given?
78
-
79
- class_eval <<-METHOD, __FILE__, __LINE__
80
- def _invoke_#{name.to_s.gsub(/\W/, '_')}
81
- klass, task = self.class.prepare_for_invocation(nil, #{name.inspect})
82
-
83
- if klass
84
- say_status :invoke, #{name.inspect}, #{verbose.inspect}
85
- block = self.class.invocation_blocks[#{name.inspect}]
86
- _invoke_for_class_method klass, task, &block
87
- else
88
- say_status :error, %(#{name.inspect} [not found]), :red
89
- end
90
- end
91
- METHOD
92
- end
93
- end
94
-
95
- # Invoke a thor class based on the value supplied by the user to the
96
- # given option named "name". A class option must be created before this
97
- # method is invoked for each name given.
98
- #
99
- # ==== Examples
100
- #
101
- # class GemGenerator < Thor::Group
102
- # class_option :test_framework, :type => :string
103
- # invoke_from_option :test_framework
104
- # end
105
- #
106
- # ==== Boolean options
107
- #
108
- # In some cases, you want to invoke a thor class if some option is true or
109
- # false. This is automatically handled by invoke_from_option. Then the
110
- # option name is used to invoke the generator.
111
- #
112
- # ==== Preparing for invocation
113
- #
114
- # In some cases you want to customize how a specified hook is going to be
115
- # invoked. You can do that by overwriting the class method
116
- # prepare_for_invocation. The class method must necessarily return a klass
117
- # and an optional task.
118
- #
119
- # ==== Custom invocations
120
- #
121
- # You can also supply a block to customize how the option is giong to be
122
- # invoked. The block receives two parameters, an instance of the current
123
- # class and the klass to be invoked.
124
- #
125
- def invoke_from_option(*names, &block)
126
- options = names.last.is_a?(Hash) ? names.pop : {}
127
- verbose = options.fetch(:verbose, :white)
128
-
129
- names.each do |name|
130
- unless class_options.key?(name)
131
- raise ArgumentError, "You have to define the option #{name.inspect} " <<
132
- "before setting invoke_from_option."
133
- end
134
-
135
- invocations[name] = true
136
- invocation_blocks[name] = block if block_given?
137
-
138
- class_eval <<-METHOD, __FILE__, __LINE__
139
- def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
140
- return unless options[#{name.inspect}]
141
-
142
- value = options[#{name.inspect}]
143
- value = #{name.inspect} if TrueClass === value
144
- klass, task = self.class.prepare_for_invocation(#{name.inspect}, value)
145
-
146
- if klass
147
- say_status :invoke, value, #{verbose.inspect}
148
- block = self.class.invocation_blocks[#{name.inspect}]
149
- _invoke_for_class_method klass, task, &block
150
- else
151
- say_status :error, %(\#{value} [not found]), :red
152
- end
153
- end
154
- METHOD
155
- end
156
- end
157
-
158
- # Remove a previously added invocation.
159
- #
160
- # ==== Examples
161
- #
162
- # remove_invocation :test_framework
163
- #
164
- def remove_invocation(*names)
165
- names.each do |name|
166
- remove_task(name)
167
- remove_class_option(name)
168
- invocations.delete(name)
169
- invocation_blocks.delete(name)
170
- end
171
- end
172
-
173
- # Overwrite class options help to allow invoked generators options to be
174
- # shown recursively when invoking a generator.
175
- #
176
- def class_options_help(shell, groups={}) #:nodoc:
177
- get_options_from_invocations(groups, class_options) do |klass|
178
- klass.send(:get_options_from_invocations, groups, class_options)
179
- end
180
- super(shell, groups)
181
- end
182
-
183
- # Get invocations array and merge options from invocations. Those
184
- # options are added to group_options hash. Options that already exists
185
- # in base_options are not added twice.
186
- #
187
- def get_options_from_invocations(group_options, base_options) #:nodoc:
188
- invocations.each do |name, from_option|
189
- value = if from_option
190
- option = class_options[name]
191
- option.type == :boolean ? name : option.default
192
- else
193
- name
194
- end
195
- next unless value
196
-
197
- klass, task = prepare_for_invocation(name, value)
198
- next unless klass && klass.respond_to?(:class_options)
199
-
200
- value = value.to_s
201
- human_name = value.respond_to?(:classify) ? value.classify : value
202
-
203
- group_options[human_name] ||= []
204
- group_options[human_name] += klass.class_options.values.select do |option|
205
- base_options[option.name.to_sym].nil? && option.group.nil? &&
206
- !group_options.values.flatten.any? { |i| i.name == option.name }
207
- end
208
-
209
- yield klass if block_given?
210
- end
211
- end
212
-
213
- # Returns tasks ready to be printed.
214
- def printable_tasks(*)
215
- item = []
216
- item << banner
217
- item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "")
218
- [item]
219
- end
220
-
221
- protected
222
-
223
- # The banner for this class. You can customize it if you are invoking the
224
- # thor class by another ways which is not the Thor::Runner.
225
- #
226
- def banner
227
- "thor #{self_task.formatted_usage(self, false)}"
228
- end
229
-
230
- # Represents the whole class as a task.
231
- def self_task #:nodoc:
232
- Thor::Task::Dynamic.new(self.namespace, class_options)
233
- end
234
-
235
- def baseclass #:nodoc:
236
- Thor::Group
237
- end
238
-
239
- def create_task(meth) #:nodoc:
240
- tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil)
241
- true
242
- end
243
- end
244
-
245
- include Thor::Base
246
-
247
- protected
248
-
249
- # Shortcut to invoke with padding and block handling. Use internally by
250
- # invoke and invoke_from_option class methods.
251
- def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc:
252
- shell.padding += 1
253
-
254
- result = if block_given?
255
- if block.arity == 2
256
- block.call(self, klass)
257
- else
258
- block.call(self, klass, task)
259
- end
260
- else
261
- invoke klass, task, *args
262
- end
263
-
264
- shell.padding -= 1
265
- result
266
- end
267
- end
@@ -1,66 +0,0 @@
1
- require 'rake'
2
-
3
- class Thor
4
- # Adds a compatibility layer to your Thor classes which allows you to use
5
- # rake package tasks. For example, to use rspec rake tasks, one can do:
6
- #
7
- # require 'thor/rake_compat'
8
- #
9
- # class Default < Thor
10
- # include Thor::RakeCompat
11
- #
12
- # Spec::Rake::SpecTask.new(:spec) do |t|
13
- # t.spec_opts = ['--options', "spec/spec.opts"]
14
- # t.spec_files = FileList['spec/**/*_spec.rb']
15
- # end
16
- # end
17
- #
18
- module RakeCompat
19
- def self.rake_classes
20
- @rake_classes ||= []
21
- end
22
-
23
- def self.included(base)
24
- # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
25
- rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
26
- Rake.application.instance_variable_set(:@rakefile, rakefile)
27
- self.rake_classes << base
28
- end
29
- end
30
- end
31
-
32
- class Object #:nodoc:
33
- alias :rake_task :task
34
- alias :rake_namespace :namespace
35
-
36
- def task(*args, &block)
37
- task = rake_task(*args, &block)
38
-
39
- if klass = Thor::RakeCompat.rake_classes.last
40
- non_namespaced_name = task.name.split(':').last
41
-
42
- description = non_namespaced_name
43
- description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ')
44
- description.strip!
45
-
46
- klass.desc description, task.comment || non_namespaced_name
47
- klass.send :define_method, non_namespaced_name do |*args|
48
- Rake::Task[task.name.to_sym].invoke(*args)
49
- end
50
- end
51
-
52
- task
53
- end
54
-
55
- def namespace(name, &block)
56
- if klass = Thor::RakeCompat.rake_classes.last
57
- const_name = Thor::Util.camel_case(name.to_s).to_sym
58
- klass.const_set(const_name, Class.new(Thor))
59
- new_klass = klass.const_get(const_name)
60
- Thor::RakeCompat.rake_classes << new_klass
61
- end
62
-
63
- rake_namespace(name, &block)
64
- Thor::RakeCompat.rake_classes.pop
65
- end
66
- end
@@ -1,303 +0,0 @@
1
- require 'fileutils'
2
- require 'open-uri'
3
- require 'yaml'
4
- require 'digest/md5'
5
- require 'pathname'
6
-
7
- class Thor::Runner < Thor #:nodoc:
8
- map "-T" => :list, "-i" => :install, "-u" => :update
9
-
10
- # Override Thor#help so it can give information about any class and any method.
11
- #
12
- def help(meth=nil)
13
- if meth && !self.respond_to?(meth)
14
- initialize_thorfiles(meth)
15
- klass, task = Thor::Util.namespace_to_thor_class_and_task(meth)
16
- # Send mapping -h because it works with Thor::Group too
17
- klass.start(["-h", task].compact, :shell => self.shell)
18
- else
19
- super
20
- end
21
- end
22
-
23
- # If a task is not found on Thor::Runner, method missing is invoked and
24
- # Thor::Runner is then responsable for finding the task in all classes.
25
- #
26
- def method_missing(meth, *args)
27
- meth = meth.to_s
28
- initialize_thorfiles(meth)
29
- klass, task = Thor::Util.namespace_to_thor_class_and_task(meth)
30
- args.unshift(task) if task
31
- klass.start(args, :shell => shell)
32
- end
33
-
34
- desc "install NAME", "Install an optionally named Thor file into your system tasks"
35
- method_options :as => :string, :relative => :boolean
36
- def install(name)
37
- initialize_thorfiles
38
-
39
- # If a directory name is provided as the argument, look for a 'main.thor'
40
- # task in said directory.
41
- begin
42
- if File.directory?(File.expand_path(name))
43
- base, package = File.join(name, "main.thor"), :directory
44
- contents = open(base).read
45
- else
46
- base, package = name, :file
47
- contents = open(name).read
48
- end
49
- rescue OpenURI::HTTPError
50
- raise Error, "Error opening URI '#{name}'"
51
- rescue Errno::ENOENT
52
- raise Error, "Error opening file '#{name}'"
53
- end
54
-
55
- say "Your Thorfile contains:"
56
- say contents
57
-
58
- return false if no?("Do you wish to continue [y/N]?")
59
-
60
- as = options["as"] || begin
61
- first_line = contents.split("\n")[0]
62
- (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
63
- end
64
-
65
- unless as
66
- basename = File.basename(name)
67
- as = ask("Please specify a name for #{name} in the system repository [#{basename}]:")
68
- as = basename if as.empty?
69
- end
70
-
71
- location = if options[:relative] || name =~ /^http:\/\//
72
- name
73
- else
74
- File.expand_path(name)
75
- end
76
-
77
- thor_yaml[as] = {
78
- :filename => Digest::MD5.hexdigest(name + as),
79
- :location => location,
80
- :namespaces => Thor::Util.namespaces_in_content(contents, base)
81
- }
82
-
83
- save_yaml(thor_yaml)
84
- say "Storing thor file in your system repository"
85
- destination = File.join(thor_root, thor_yaml[as][:filename])
86
-
87
- if package == :file
88
- File.open(destination, "w") { |f| f.puts contents }
89
- else
90
- FileUtils.cp_r(name, destination)
91
- end
92
-
93
- thor_yaml[as][:filename] # Indicate success
94
- end
95
-
96
- desc "uninstall NAME", "Uninstall a named Thor module"
97
- def uninstall(name)
98
- raise Error, "Can't find module '#{name}'" unless thor_yaml[name]
99
- say "Uninstalling #{name}."
100
- FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}"))
101
-
102
- thor_yaml.delete(name)
103
- save_yaml(thor_yaml)
104
-
105
- puts "Done."
106
- end
107
-
108
- desc "update NAME", "Update a Thor file from its original location"
109
- def update(name)
110
- raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
111
-
112
- say "Updating '#{name}' from #{thor_yaml[name][:location]}"
113
-
114
- old_filename = thor_yaml[name][:filename]
115
- self.options = self.options.merge("as" => name)
116
- filename = install(thor_yaml[name][:location])
117
-
118
- unless filename == old_filename
119
- File.delete(File.join(thor_root, old_filename))
120
- end
121
- end
122
-
123
- desc "installed", "List the installed Thor modules and tasks"
124
- method_options :internal => :boolean
125
- def installed
126
- initialize_thorfiles(nil, true)
127
- display_klasses(true, options["internal"])
128
- end
129
-
130
- desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)"
131
- method_options :substring => :boolean, :group => :string, :all => :boolean
132
- def list(search="")
133
- initialize_thorfiles
134
-
135
- search = ".*#{search}" if options["substring"]
136
- search = /^#{search}.*/i
137
- group = options[:group] || "standard"
138
-
139
- klasses = Thor::Base.subclasses.select do |k|
140
- (options[:all] || k.group == group) && k.namespace =~ search
141
- end
142
-
143
- display_klasses(false, false, klasses)
144
- end
145
-
146
- private
147
-
148
- def self.banner(task)
149
- "thor " + task.formatted_usage(self, false)
150
- end
151
-
152
- def thor_root
153
- Thor::Util.thor_root
154
- end
155
-
156
- def thor_yaml
157
- @thor_yaml ||= begin
158
- yaml_file = File.join(thor_root, "thor.yml")
159
- yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file)
160
- yaml || {}
161
- end
162
- end
163
-
164
- # Save the yaml file. If none exists in thor root, creates one.
165
- #
166
- def save_yaml(yaml)
167
- yaml_file = File.join(thor_root, "thor.yml")
168
-
169
- unless File.exists?(yaml_file)
170
- FileUtils.mkdir_p(thor_root)
171
- yaml_file = File.join(thor_root, "thor.yml")
172
- FileUtils.touch(yaml_file)
173
- end
174
-
175
- File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
176
- end
177
-
178
- def self.exit_on_failure?
179
- true
180
- end
181
-
182
- # Load the thorfiles. If relevant_to is supplied, looks for specific files
183
- # in the thor_root instead of loading them all.
184
- #
185
- # By default, it also traverses the current path until find Thor files, as
186
- # described in thorfiles. This look up can be skipped by suppliying
187
- # skip_lookup true.
188
- #
189
- def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
190
- thorfiles(relevant_to, skip_lookup).each do |f|
191
- Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
192
- end
193
- end
194
-
195
- # Finds Thorfiles by traversing from your current directory down to the root
196
- # directory of your system. If at any time we find a Thor file, we stop.
197
- #
198
- # We also ensure that system-wide Thorfiles are loaded first, so local
199
- # Thorfiles can override them.
200
- #
201
- # ==== Example
202
- #
203
- # If we start at /Users/wycats/dev/thor ...
204
- #
205
- # 1. /Users/wycats/dev/thor
206
- # 2. /Users/wycats/dev
207
- # 3. /Users/wycats <-- we find a Thorfile here, so we stop
208
- #
209
- # Suppose we start at c:\Documents and Settings\james\dev\thor ...
210
- #
211
- # 1. c:\Documents and Settings\james\dev\thor
212
- # 2. c:\Documents and Settings\james\dev
213
- # 3. c:\Documents and Settings\james
214
- # 4. c:\Documents and Settings
215
- # 5. c:\ <-- no Thorfiles found!
216
- #
217
- def thorfiles(relevant_to=nil, skip_lookup=false)
218
- thorfiles = []
219
-
220
- unless skip_lookup
221
- Pathname.pwd.ascend do |path|
222
- thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
223
- break unless thorfiles.empty?
224
- end
225
- end
226
-
227
- files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob)
228
- files += thorfiles
229
- files -= ["#{thor_root}/thor.yml"]
230
-
231
- files.map! do |file|
232
- File.directory?(file) ? File.join(file, "main.thor") : file
233
- end
234
- end
235
-
236
- # Load thorfiles relevant to the given method. If you provide "foo:bar" it
237
- # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
238
- # namespaces registered.
239
- #
240
- def thorfiles_relevant_to(meth)
241
- lookup = [ meth, meth.split(":")[0...-1].join(":") ]
242
-
243
- files = thor_yaml.select do |k, v|
244
- v[:namespaces] && !(v[:namespaces] & lookup).empty?
245
- end
246
-
247
- files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
248
- end
249
-
250
- # Display information about the given klasses. If with_module is given,
251
- # it shows a table with information extracted from the yaml file.
252
- #
253
- def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses)
254
- klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal
255
-
256
- raise Error, "No Thor tasks available" if klasses.empty?
257
- show_modules if with_modules && !thor_yaml.empty?
258
-
259
- # Remove subclasses
260
- klasses.dup.each do |klass|
261
- klasses -= Thor::Util.thor_classes_in(klass)
262
- end
263
-
264
- list = Hash.new { |h,k| h[k] = [] }
265
- groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
266
-
267
- # Get classes which inherit from Thor
268
- (klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) }
269
-
270
- # Get classes which inherit from Thor::Base
271
- groups.map! { |k| k.printable_tasks(false).first }
272
- list["root"] = groups
273
-
274
- # Order namespaces with default coming first
275
- list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') }
276
- list.each { |n, tasks| display_tasks(n, tasks) unless tasks.empty? }
277
- end
278
-
279
- def display_tasks(namespace, list) #:nodoc:
280
- list.sort!{ |a,b| a[0] <=> b[0] }
281
-
282
- say shell.set_color(namespace, :blue, true)
283
- say "-" * namespace.size
284
-
285
- print_table(list, :truncate => true)
286
- say
287
- end
288
-
289
- def show_modules #:nodoc:
290
- info = []
291
- labels = ["Modules", "Namespaces"]
292
-
293
- info << labels
294
- info << [ "-" * labels[0].size, "-" * labels[1].size ]
295
-
296
- thor_yaml.each do |name, hash|
297
- info << [ name, hash[:namespaces].join(", ") ]
298
- end
299
-
300
- print_table info
301
- say ""
302
- end
303
- end