Class: Thor::Group

Inherits:
Object show all
Includes:
Base
Defined in:
lib/vendor/thor/lib/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.



177
178
179
180
181
182
# File 'lib/vendor/thor/lib/thor/group.rb', line 177

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 descrition 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/vendor/thor/lib/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.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/vendor/thor/lib/thor/group.rb', line 188

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)


222
223
224
# File 'lib/vendor/thor/lib/thor/group.rb', line 222

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.



45
46
47
48
49
50
51
# File 'lib/vendor/thor/lib/thor/group.rb', line 45

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.



61
62
63
# File 'lib/vendor/thor/lib/thor/group.rb', line 61

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

.invocationsObject

Stores invocations for this class merging with superclass values.



55
56
57
# File 'lib/vendor/thor/lib/thor/group.rb', line 55

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.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/vendor/thor/lib/thor/group.rb', line 72

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.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/vendor/thor/lib/thor/group.rb', line 126

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.



215
216
217
218
219
220
# File 'lib/vendor/thor/lib/thor/group.rb', line 215

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


165
166
167
168
169
170
171
172
# File 'lib/vendor/thor/lib/thor/group.rb', line 165

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

.start(original_args = ARGV, config = {}) ⇒ Object

Start works differently in Thor::Group, it simply invokes all tasks inside the class.



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/vendor/thor/lib/thor/group.rb', line 28

def start(original_args=ARGV, config={})
  super do |given_args|
    if Thor::HELP_MAPPINGS.include?(given_args.first)
      help(config[:shell])
      return
    end

    args, opts = Thor::Options.split(given_args)
    new(args, opts, config).invoke
  end
end