Class: Thor::Group

Inherits:
Object show all
Includes:
Base
Defined in:
lib/bundler/vendor/thor/group.rb

Overview

Thor has a special class called Thor::Group. The main difference to Thor class is that it invokes all tasks at once. It also include some methods that allows invocations to be done at the class method, which are not available to Thor tasks.

Instance Attribute Summary

Attributes included from Base

#options

Class Method Summary collapse

Methods included from Base

included, #initialize, register_klass_file, shell, shell=, subclass_files, subclasses

Class Method Details

.class_options_help(shell, groups = {}) ⇒ Object

Overwrite class options help to allow invoked generators options to be shown recursively when invoking a generator.



162
163
164
165
166
167
# File 'lib/bundler/vendor/thor/group.rb', line 162

def class_options_help(shell, groups={}) #:nodoc:
  get_options_from_invocations(groups, class_options) do |klass|
    klass.send(:get_options_from_invocations, groups, class_options)
  end
  super(shell, groups)
end

.desc(description = nil) ⇒ Object

The description for this Thor::Group. If none is provided, but a source root exists, tries to find the USAGE one folder above it, otherwise searches in the superclass.

Parameters

description<String>

The description for this Thor::Group.



16
17
18
19
20
21
22
23
# File 'lib/bundler/vendor/thor/group.rb', line 16

def desc(description=nil)
  case description
    when nil
      @desc ||= from_superclass(:desc, nil)
    else
      @desc = description
  end
end

.get_options_from_invocations(group_options, base_options) ⇒ Object

Get invocations array and merge options from invocations. Those options are added to group_options hash. Options that already exists in base_options are not added twice.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/bundler/vendor/thor/group.rb', line 173

def get_options_from_invocations(group_options, base_options) #:nodoc:
  invocations.each do |name, from_option|
    value = if from_option
      option = class_options[name]
      option.type == :boolean ? name : option.default
    else
      name
    end
    next unless value

    klass, task = prepare_for_invocation(name, value)
    next unless klass && klass.respond_to?(:class_options)

    value = value.to_s
    human_name = value.respond_to?(:classify) ? value.classify : value

    group_options[human_name] ||= []
    group_options[human_name] += klass.class_options.values.select do |option|
      base_options[option.name.to_sym].nil? && option.group.nil? &&
      !group_options.values.flatten.any? { |i| i.name == option.name }
    end

    yield klass if block_given?
  end
end

.handle_argument_error(task, error) ⇒ Object

:nodoc:

Raises:

  • (error)


207
208
209
# File 'lib/bundler/vendor/thor/group.rb', line 207

def handle_argument_error(task, error) #:nodoc:
  raise error, "#{task.name.inspect} was called incorrectly. Are you sure it has arity equals to 0?"
end

.help(shell) ⇒ Object

Prints help information.

Options

short

When true, shows only usage.



30
31
32
33
34
35
36
# File 'lib/bundler/vendor/thor/group.rb', line 30

def help(shell)
  shell.say "Usage:"
  shell.say "  #{banner}\n"
  shell.say
  class_options_help(shell)
  shell.say self.desc if self.desc
end

.invocation_blocksObject

Stores invocation blocks used on invoke_from_option.



46
47
48
# File 'lib/bundler/vendor/thor/group.rb', line 46

def invocation_blocks #:nodoc:
  @invocation_blocks ||= from_superclass(:invocation_blocks, {})
end

.invocationsObject

Stores invocations for this class merging with superclass values.



40
41
42
# File 'lib/bundler/vendor/thor/group.rb', line 40

def invocations #:nodoc:
  @invocations ||= from_superclass(:invocations, {})
end

.invoke(*names, &block) ⇒ Object

Invoke the given namespace or class given. It adds an instance method that will invoke the klass and task. You can give a block to configure how it will be invoked.

The namespace/class given will have its options showed on the help usage. Check invoke_from_option for more information.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/bundler/vendor/thor/group.rb', line 57

def invoke(*names, &block)
  options = names.last.is_a?(Hash) ? names.pop : {}
  verbose = options.fetch(:verbose, true)

  names.each do |name|
    invocations[name] = false
    invocation_blocks[name] = block if block_given?

    class_eval <<-METHOD, __FILE__, __LINE__
      def _invoke_#{name.to_s.gsub(/\W/, '_')}
        klass, task = self.class.prepare_for_invocation(nil, #{name.inspect})

        if klass
          say_status :invoke, #{name.inspect}, #{verbose.inspect}
          block = self.class.invocation_blocks[#{name.inspect}]
          _invoke_for_class_method klass, task, &block
        else
          say_status :error, %(#{name.inspect} [not found]), :red
        end
      end
    METHOD
  end
end

.invoke_from_option(*names, &block) ⇒ Object

Invoke a thor class based on the value supplied by the user to the given option named “name”. A class option must be created before this method is invoked for each name given.

Examples

class GemGenerator < Thor::Group
  class_option :test_framework, :type => :string
  invoke_from_option :test_framework
end

Boolean options

In some cases, you want to invoke a thor class if some option is true or false. This is automatically handled by invoke_from_option. Then the option name is used to invoke the generator.

Preparing for invocation

In some cases you want to customize how a specified hook is going to be invoked. You can do that by overwriting the class method prepare_for_invocation. The class method must necessarily return a klass and an optional task.

Custom invocations

You can also supply a block to customize how the option is giong to be invoked. The block receives two parameters, an instance of the current class and the klass to be invoked.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/bundler/vendor/thor/group.rb', line 111

def invoke_from_option(*names, &block)
  options = names.last.is_a?(Hash) ? names.pop : {}
  verbose = options.fetch(:verbose, :white)

  names.each do |name|
    unless class_options.key?(name)
      raise ArgumentError, "You have to define the option #{name.inspect} " <<
                           "before setting invoke_from_option."
    end

    invocations[name] = true
    invocation_blocks[name] = block if block_given?

    class_eval <<-METHOD, __FILE__, __LINE__
      def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
        return unless options[#{name.inspect}]

        value = options[#{name.inspect}]
        value = #{name.inspect} if TrueClass === value
        klass, task = self.class.prepare_for_invocation(#{name.inspect}, value)

        if klass
          say_status :invoke, value, #{verbose.inspect}
          block = self.class.invocation_blocks[#{name.inspect}]
          _invoke_for_class_method klass, task, &block
        else
          say_status :error, %(\#{value} [not found]), :red
        end
      end
    METHOD
  end
end

.printable_tasksObject

Returns tasks ready to be printed.



200
201
202
203
204
205
# File 'lib/bundler/vendor/thor/group.rb', line 200

def printable_tasks(*)
  item = []
  item << banner
  item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "")
  [item]
end

.remove_invocation(*names) ⇒ Object

Remove a previously added invocation.

Examples

remove_invocation :test_framework


150
151
152
153
154
155
156
157
# File 'lib/bundler/vendor/thor/group.rb', line 150

def remove_invocation(*names)
  names.each do |name|
    remove_task(name)
    remove_class_option(name)
    invocations.delete(name)
    invocation_blocks.delete(name)
  end
end