thor-exclude_pattern 0.18.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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CHANGELOG.md +130 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +34 -0
  6. data/Thorfile +30 -0
  7. data/bin/rake2thor +86 -0
  8. data/bin/thor +6 -0
  9. data/lib/thor.rb +458 -0
  10. data/lib/thor/actions.rb +318 -0
  11. data/lib/thor/actions/create_file.rb +105 -0
  12. data/lib/thor/actions/create_link.rb +60 -0
  13. data/lib/thor/actions/directory.rb +119 -0
  14. data/lib/thor/actions/empty_directory.rb +153 -0
  15. data/lib/thor/actions/file_manipulation.rb +314 -0
  16. data/lib/thor/actions/inject_into_file.rb +109 -0
  17. data/lib/thor/base.rb +649 -0
  18. data/lib/thor/command.rb +136 -0
  19. data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  20. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  21. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  22. data/lib/thor/error.rb +32 -0
  23. data/lib/thor/exclude_pattern/version.rb +5 -0
  24. data/lib/thor/group.rb +287 -0
  25. data/lib/thor/invocation.rb +172 -0
  26. data/lib/thor/parser.rb +4 -0
  27. data/lib/thor/parser/argument.rb +74 -0
  28. data/lib/thor/parser/arguments.rb +171 -0
  29. data/lib/thor/parser/option.rb +121 -0
  30. data/lib/thor/parser/options.rb +218 -0
  31. data/lib/thor/rake_compat.rb +72 -0
  32. data/lib/thor/runner.rb +322 -0
  33. data/lib/thor/shell.rb +88 -0
  34. data/lib/thor/shell/basic.rb +393 -0
  35. data/lib/thor/shell/color.rb +148 -0
  36. data/lib/thor/shell/html.rb +127 -0
  37. data/lib/thor/util.rb +270 -0
  38. data/lib/thor/version.rb +3 -0
  39. data/spec/actions/create_file_spec.rb +170 -0
  40. data/spec/actions/create_link_spec.rb +95 -0
  41. data/spec/actions/directory_spec.rb +169 -0
  42. data/spec/actions/empty_directory_spec.rb +130 -0
  43. data/spec/actions/file_manipulation_spec.rb +382 -0
  44. data/spec/actions/inject_into_file_spec.rb +135 -0
  45. data/spec/actions_spec.rb +331 -0
  46. data/spec/base_spec.rb +294 -0
  47. data/spec/command_spec.rb +80 -0
  48. data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
  49. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  50. data/spec/exit_condition_spec.rb +19 -0
  51. data/spec/fixtures/application.rb +2 -0
  52. data/spec/fixtures/app{1}/README +3 -0
  53. data/spec/fixtures/bundle/execute.rb +6 -0
  54. data/spec/fixtures/bundle/main.thor +1 -0
  55. data/spec/fixtures/command.thor +10 -0
  56. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  57. data/spec/fixtures/doc/COMMENTER +11 -0
  58. data/spec/fixtures/doc/README +3 -0
  59. data/spec/fixtures/doc/block_helper.rb +3 -0
  60. data/spec/fixtures/doc/config.rb +1 -0
  61. data/spec/fixtures/doc/config.yaml.tt +1 -0
  62. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
  63. data/spec/fixtures/enum.thor +10 -0
  64. data/spec/fixtures/group.thor +128 -0
  65. data/spec/fixtures/invoke.thor +112 -0
  66. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  67. data/spec/fixtures/preserve/script.sh +3 -0
  68. data/spec/fixtures/script.thor +199 -0
  69. data/spec/fixtures/subcommand.thor +17 -0
  70. data/spec/group_spec.rb +216 -0
  71. data/spec/helper.rb +67 -0
  72. data/spec/invocation_spec.rb +100 -0
  73. data/spec/parser/argument_spec.rb +53 -0
  74. data/spec/parser/arguments_spec.rb +66 -0
  75. data/spec/parser/option_spec.rb +202 -0
  76. data/spec/parser/options_spec.rb +400 -0
  77. data/spec/rake_compat_spec.rb +72 -0
  78. data/spec/register_spec.rb +197 -0
  79. data/spec/runner_spec.rb +241 -0
  80. data/spec/sandbox/application.rb +2 -0
  81. data/spec/sandbox/app{1}/README +3 -0
  82. data/spec/sandbox/bundle/execute.rb +6 -0
  83. data/spec/sandbox/bundle/main.thor +1 -0
  84. data/spec/sandbox/command.thor +10 -0
  85. data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
  86. data/spec/sandbox/doc/COMMENTER +11 -0
  87. data/spec/sandbox/doc/README +4 -0
  88. data/spec/sandbox/doc/block_helper.rb +3 -0
  89. data/spec/sandbox/doc/config.rb +1 -0
  90. data/spec/sandbox/doc/config.yaml.tt +1 -0
  91. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
  92. data/spec/sandbox/enum.thor +10 -0
  93. data/spec/sandbox/group.thor +128 -0
  94. data/spec/sandbox/invoke.thor +112 -0
  95. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  96. data/spec/sandbox/preserve/script.sh +3 -0
  97. data/spec/sandbox/script.thor +199 -0
  98. data/spec/sandbox/subcommand.thor +17 -0
  99. data/spec/shell/basic_spec.rb +311 -0
  100. data/spec/shell/color_spec.rb +95 -0
  101. data/spec/shell/html_spec.rb +32 -0
  102. data/spec/shell_spec.rb +47 -0
  103. data/spec/subcommand_spec.rb +30 -0
  104. data/spec/thor_spec.rb +469 -0
  105. data/spec/util_spec.rb +196 -0
  106. data/thor.gemspec +24 -0
  107. metadata +232 -0
@@ -0,0 +1,136 @@
1
+ class Thor
2
+ class Command < Struct.new(:name, :description, :long_description, :usage, :options)
3
+ FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
4
+
5
+ def initialize(name, description, long_description, usage, options=nil)
6
+ super(name.to_s, description, long_description, usage, options || {})
7
+ end
8
+
9
+ def initialize_copy(other) #:nodoc:
10
+ super(other)
11
+ self.options = other.options.dup if other.options
12
+ end
13
+
14
+ def hidden?
15
+ false
16
+ end
17
+
18
+ # By default, a command invokes a method in the thor class. You can change this
19
+ # implementation to create custom commands.
20
+ def run(instance, args=[])
21
+ arity = nil
22
+
23
+ if private_method?(instance)
24
+ instance.class.handle_no_command_error(name)
25
+ elsif public_method?(instance)
26
+ arity = instance.method(name).arity
27
+ instance.__send__(name, *args)
28
+ elsif local_method?(instance, :method_missing)
29
+ instance.__send__(:method_missing, name.to_sym, *args)
30
+ else
31
+ instance.class.handle_no_command_error(name)
32
+ end
33
+ rescue ArgumentError => e
34
+ handle_argument_error?(instance, e, caller) ?
35
+ instance.class.handle_argument_error(self, e, arity) : (raise e)
36
+ rescue NoMethodError => e
37
+ handle_no_method_error?(instance, e, caller) ?
38
+ instance.class.handle_no_command_error(name) : (raise e)
39
+ end
40
+
41
+ # Returns the formatted usage by injecting given required arguments
42
+ # and required options into the given usage.
43
+ def formatted_usage(klass, namespace = true, subcommand = false)
44
+ if namespace
45
+ namespace = klass.namespace
46
+ formatted = "#{namespace.gsub(/^(default)/,'')}:"
47
+ end
48
+ formatted = "#{klass.namespace.split(':').last} " if subcommand
49
+
50
+ formatted ||= ""
51
+
52
+ # Add usage with required arguments
53
+ formatted << if klass && !klass.arguments.empty?
54
+ usage.to_s.gsub(/^#{name}/) do |match|
55
+ match << " " << klass.arguments.map{ |a| a.usage }.compact.join(' ')
56
+ end
57
+ else
58
+ usage.to_s
59
+ end
60
+
61
+ # Add required options
62
+ formatted << " #{required_options}"
63
+
64
+ # Strip and go!
65
+ formatted.strip
66
+ end
67
+
68
+ protected
69
+
70
+ def not_debugging?(instance)
71
+ !(instance.class.respond_to?(:debugging) && instance.class.debugging)
72
+ end
73
+
74
+ def required_options
75
+ @required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
76
+ end
77
+
78
+ # Given a target, checks if this class name is a public method.
79
+ def public_method?(instance) #:nodoc:
80
+ !(instance.public_methods & [name.to_s, name.to_sym]).empty?
81
+ end
82
+
83
+ def private_method?(instance)
84
+ !(instance.private_methods & [name.to_s, name.to_sym]).empty?
85
+ end
86
+
87
+ def local_method?(instance, name)
88
+ methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false)
89
+ !(methods & [name.to_s, name.to_sym]).empty?
90
+ end
91
+
92
+ def sans_backtrace(backtrace, caller) #:nodoc:
93
+ saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) }
94
+ saned -= caller
95
+ end
96
+
97
+ def handle_argument_error?(instance, error, caller)
98
+ not_debugging?(instance) && error.message =~ /wrong number of arguments/ && begin
99
+ saned = sans_backtrace(error.backtrace, caller)
100
+ # Ruby 1.9 always include the called method in the backtrace
101
+ saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
102
+ end
103
+ end
104
+
105
+ def handle_no_method_error?(instance, error, caller)
106
+ not_debugging?(instance) &&
107
+ error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
108
+ end
109
+ end
110
+ Task = Command
111
+
112
+ # A command that is hidden in help messages but still invocable.
113
+ class HiddenCommand < Command
114
+ def hidden?
115
+ true
116
+ end
117
+ end
118
+ HiddenTask = HiddenCommand
119
+
120
+ # A dynamic command that handles method missing scenarios.
121
+ class DynamicCommand < Command
122
+ def initialize(name, options=nil)
123
+ super(name.to_s, "A dynamically-generated command", name.to_s, name.to_s, options)
124
+ end
125
+
126
+ def run(instance, args=[])
127
+ if (instance.methods & [name.to_s, name.to_sym]).empty?
128
+ super
129
+ else
130
+ instance.class.handle_no_command_error(name)
131
+ end
132
+ end
133
+ end
134
+ DynamicTask = DynamicCommand
135
+
136
+ end
@@ -0,0 +1,80 @@
1
+ class Thor
2
+ module CoreExt #:nodoc:
3
+
4
+ # A hash with indifferent access and magic predicates.
5
+ #
6
+ # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true
7
+ #
8
+ # hash[:foo] #=> 'bar'
9
+ # hash['foo'] #=> 'bar'
10
+ # hash.foo? #=> true
11
+ #
12
+ class HashWithIndifferentAccess < ::Hash #:nodoc:
13
+
14
+ def initialize(hash={})
15
+ super()
16
+ hash.each do |key, value|
17
+ self[convert_key(key)] = value
18
+ end
19
+ end
20
+
21
+ def [](key)
22
+ super(convert_key(key))
23
+ end
24
+
25
+ def []=(key, value)
26
+ super(convert_key(key), value)
27
+ end
28
+
29
+ def delete(key)
30
+ super(convert_key(key))
31
+ end
32
+
33
+ def values_at(*indices)
34
+ indices.collect { |key| self[convert_key(key)] }
35
+ end
36
+
37
+ def merge(other)
38
+ dup.merge!(other)
39
+ end
40
+
41
+ def merge!(other)
42
+ other.each do |key, value|
43
+ self[convert_key(key)] = value
44
+ end
45
+ self
46
+ end
47
+
48
+ # Convert to a Hash with String keys.
49
+ def to_hash
50
+ Hash.new(default).merge!(self)
51
+ end
52
+
53
+ protected
54
+
55
+ def convert_key(key)
56
+ key.is_a?(Symbol) ? key.to_s : key
57
+ end
58
+
59
+ # Magic predicates. For instance:
60
+ #
61
+ # options.force? # => !!options['force']
62
+ # options.shebang # => "/usr/lib/local/ruby"
63
+ # options.test_framework?(:rspec) # => options[:test_framework] == :rspec
64
+ #
65
+ def method_missing(method, *args, &block)
66
+ method = method.to_s
67
+ if method =~ /^(\w+)\?$/
68
+ if args.empty?
69
+ !!self[$1]
70
+ else
71
+ self[$1] == args.first
72
+ end
73
+ else
74
+ self[method]
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,12 @@
1
+ class IO #:nodoc:
2
+ class << self
3
+
4
+ def binread(file, *args)
5
+ raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
6
+ File.open(file, 'rb') do |f|
7
+ f.read(*args)
8
+ end
9
+ end unless method_defined? :binread
10
+
11
+ end
12
+ end
@@ -0,0 +1,100 @@
1
+ class Thor
2
+ module CoreExt #:nodoc:
3
+
4
+ if RUBY_VERSION >= '1.9'
5
+ class OrderedHash < ::Hash
6
+ end
7
+ else
8
+ # This class is based on the Ruby 1.9 ordered hashes.
9
+ #
10
+ # It keeps the semantics and most of the efficiency of normal hashes
11
+ # while also keeping track of the order in which elements were set.
12
+ #
13
+ class OrderedHash #:nodoc:
14
+ include Enumerable
15
+
16
+ Node = Struct.new(:key, :value, :next, :prev)
17
+
18
+ def initialize
19
+ @hash = {}
20
+ end
21
+
22
+ def [](key)
23
+ @hash[key] && @hash[key].value
24
+ end
25
+
26
+ def []=(key, value)
27
+ if node = @hash[key]
28
+ node.value = value
29
+ else
30
+ node = Node.new(key, value)
31
+
32
+ if @first.nil?
33
+ @first = @last = node
34
+ else
35
+ node.prev = @last
36
+ @last.next = node
37
+ @last = node
38
+ end
39
+ end
40
+
41
+ @hash[key] = node
42
+ value
43
+ end
44
+
45
+ def delete(key)
46
+ if node = @hash[key]
47
+ prev_node = node.prev
48
+ next_node = node.next
49
+
50
+ next_node.prev = prev_node if next_node
51
+ prev_node.next = next_node if prev_node
52
+
53
+ @first = next_node if @first == node
54
+ @last = prev_node if @last == node
55
+
56
+ value = node.value
57
+ end
58
+
59
+ @hash.delete(key)
60
+ value
61
+ end
62
+
63
+ def keys
64
+ self.map { |k, v| k }
65
+ end
66
+
67
+ def values
68
+ self.map { |k, v| v }
69
+ end
70
+
71
+ def each
72
+ return unless @first
73
+ yield [@first.key, @first.value]
74
+ node = @first
75
+ yield [node.key, node.value] while node = node.next
76
+ self
77
+ end
78
+
79
+ def merge(other)
80
+ hash = self.class.new
81
+
82
+ self.each do |key, value|
83
+ hash[key] = value
84
+ end
85
+
86
+ other.each do |key, value|
87
+ hash[key] = value
88
+ end
89
+
90
+ hash
91
+ end
92
+
93
+ def empty?
94
+ @hash.empty?
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
data/lib/thor/error.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Thor
2
+ # Thor::Error is raised when it's caused by wrong usage of thor classes. Those
3
+ # errors have their backtrace suppressed and are nicely shown to the user.
4
+ #
5
+ # Errors that are caused by the developer, like declaring a method which
6
+ # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we
7
+ # ensure that developer errors are shown with full backtrace.
8
+ class Error < StandardError
9
+ end
10
+
11
+ # Raised when a command was not found.
12
+ class UndefinedCommandError < Error
13
+ end
14
+ UndefinedTaskError = UndefinedCommandError
15
+
16
+ # Raised when a command was found, but not invoked properly.
17
+ class InvocationError < Error
18
+ end
19
+
20
+ class UnknownArgumentError < Error
21
+ end
22
+
23
+ class RequiredArgumentMissingError < InvocationError
24
+ end
25
+
26
+ class MalformattedArgumentError < InvocationError
27
+ end
28
+
29
+ # Raised when a user tries to call a private method encoded in templated filename.
30
+ class PrivateMethodEncodedError < Error
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ class Thor
2
+ class ExcludePattern
3
+ VERSION = "0.18.0"
4
+ end
5
+ end
data/lib/thor/group.rb ADDED
@@ -0,0 +1,287 @@
1
+ require 'thor/base'
2
+
3
+ # Thor has a special class called Thor::Group. The main difference to Thor class
4
+ # is that it invokes all commands at once. It also include some methods that allows
5
+ # invocations to be done at the class method, which are not available to Thor
6
+ # commands.
7
+ class Thor::Group
8
+ class << self
9
+ # The description for this Thor::Group. If none is provided, but a source root
10
+ # exists, tries to find the USAGE one folder above it, otherwise searches
11
+ # in the superclass.
12
+ #
13
+ # ==== Parameters
14
+ # description<String>:: The description for this Thor::Group.
15
+ #
16
+ def desc(description=nil)
17
+ @desc = case description
18
+ when nil
19
+ @desc || from_superclass(:desc, nil)
20
+ else
21
+ description
22
+ end
23
+ end
24
+
25
+ # Prints help information.
26
+ #
27
+ # ==== Options
28
+ # short:: When true, shows only usage.
29
+ #
30
+ def help(shell)
31
+ shell.say "Usage:"
32
+ shell.say " #{banner}\n"
33
+ shell.say
34
+ class_options_help(shell)
35
+ shell.say self.desc if self.desc
36
+ end
37
+
38
+ # Stores invocations for this class merging with superclass values.
39
+ #
40
+ def invocations #:nodoc:
41
+ @invocations ||= from_superclass(:invocations, {})
42
+ end
43
+
44
+ # Stores invocation blocks used on invoke_from_option.
45
+ #
46
+ def invocation_blocks #:nodoc:
47
+ @invocation_blocks ||= from_superclass(:invocation_blocks, {})
48
+ end
49
+
50
+ # Invoke the given namespace or class given. It adds an instance
51
+ # method that will invoke the klass and command. You can give a block to
52
+ # configure how it will be invoked.
53
+ #
54
+ # The namespace/class given will have its options showed on the help
55
+ # usage. Check invoke_from_option for more information.
56
+ #
57
+ def invoke(*names, &block)
58
+ options = names.last.is_a?(Hash) ? names.pop : {}
59
+ verbose = options.fetch(:verbose, true)
60
+
61
+ names.each do |name|
62
+ invocations[name] = false
63
+ invocation_blocks[name] = block if block_given?
64
+
65
+ class_eval <<-METHOD, __FILE__, __LINE__
66
+ def _invoke_#{name.to_s.gsub(/\W/, '_')}
67
+ klass, command = self.class.prepare_for_invocation(nil, #{name.inspect})
68
+
69
+ if klass
70
+ say_status :invoke, #{name.inspect}, #{verbose.inspect}
71
+ block = self.class.invocation_blocks[#{name.inspect}]
72
+ _invoke_for_class_method klass, command, &block
73
+ else
74
+ say_status :error, %(#{name.inspect} [not found]), :red
75
+ end
76
+ end
77
+ METHOD
78
+ end
79
+ end
80
+
81
+ # Invoke a thor class based on the value supplied by the user to the
82
+ # given option named "name". A class option must be created before this
83
+ # method is invoked for each name given.
84
+ #
85
+ # ==== Examples
86
+ #
87
+ # class GemGenerator < Thor::Group
88
+ # class_option :test_framework, :type => :string
89
+ # invoke_from_option :test_framework
90
+ # end
91
+ #
92
+ # ==== Boolean options
93
+ #
94
+ # In some cases, you want to invoke a thor class if some option is true or
95
+ # false. This is automatically handled by invoke_from_option. Then the
96
+ # option name is used to invoke the generator.
97
+ #
98
+ # ==== Preparing for invocation
99
+ #
100
+ # In some cases you want to customize how a specified hook is going to be
101
+ # invoked. You can do that by overwriting the class method
102
+ # prepare_for_invocation. The class method must necessarily return a klass
103
+ # and an optional command.
104
+ #
105
+ # ==== Custom invocations
106
+ #
107
+ # You can also supply a block to customize how the option is going to be
108
+ # invoked. The block receives two parameters, an instance of the current
109
+ # class and the klass to be invoked.
110
+ #
111
+ def invoke_from_option(*names, &block)
112
+ options = names.last.is_a?(Hash) ? names.pop : {}
113
+ verbose = options.fetch(:verbose, :white)
114
+
115
+ names.each do |name|
116
+ unless class_options.key?(name)
117
+ raise ArgumentError, "You have to define the option #{name.inspect} " <<
118
+ "before setting invoke_from_option."
119
+ end
120
+
121
+ invocations[name] = true
122
+ invocation_blocks[name] = block if block_given?
123
+
124
+ class_eval <<-METHOD, __FILE__, __LINE__
125
+ def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
126
+ return unless options[#{name.inspect}]
127
+
128
+ value = options[#{name.inspect}]
129
+ value = #{name.inspect} if TrueClass === value
130
+ klass, command = self.class.prepare_for_invocation(#{name.inspect}, value)
131
+
132
+ if klass
133
+ say_status :invoke, value, #{verbose.inspect}
134
+ block = self.class.invocation_blocks[#{name.inspect}]
135
+ _invoke_for_class_method klass, command, &block
136
+ else
137
+ say_status :error, %(\#{value} [not found]), :red
138
+ end
139
+ end
140
+ METHOD
141
+ end
142
+ end
143
+
144
+ # Remove a previously added invocation.
145
+ #
146
+ # ==== Examples
147
+ #
148
+ # remove_invocation :test_framework
149
+ #
150
+ def remove_invocation(*names)
151
+ names.each do |name|
152
+ remove_command(name)
153
+ remove_class_option(name)
154
+ invocations.delete(name)
155
+ invocation_blocks.delete(name)
156
+ end
157
+ end
158
+
159
+ # Overwrite class options help to allow invoked generators options to be
160
+ # shown recursively when invoking a generator.
161
+ #
162
+ def class_options_help(shell, groups={}) #:nodoc:
163
+ get_options_from_invocations(groups, class_options) do |klass|
164
+ klass.send(:get_options_from_invocations, groups, class_options)
165
+ end
166
+ super(shell, groups)
167
+ end
168
+
169
+ # Get invocations array and merge options from invocations. Those
170
+ # options are added to group_options hash. Options that already exists
171
+ # in base_options are not added twice.
172
+ #
173
+ def get_options_from_invocations(group_options, base_options) #:nodoc:
174
+ invocations.each do |name, from_option|
175
+ value = if from_option
176
+ option = class_options[name]
177
+ option.type == :boolean ? name : option.default
178
+ else
179
+ name
180
+ end
181
+ next unless value
182
+
183
+ klass, _ = prepare_for_invocation(name, value)
184
+ next unless klass && klass.respond_to?(:class_options)
185
+
186
+ value = value.to_s
187
+ human_name = value.respond_to?(:classify) ? value.classify : value
188
+
189
+ group_options[human_name] ||= []
190
+ group_options[human_name] += klass.class_options.values.select do |class_option|
191
+ base_options[class_option.name.to_sym].nil? && class_option.group.nil? &&
192
+ !group_options.values.flatten.any? { |i| i.name == class_option.name }
193
+ end
194
+
195
+ yield klass if block_given?
196
+ end
197
+ end
198
+
199
+ # Returns commands ready to be printed.
200
+ def printable_commands(*)
201
+ item = []
202
+ item << banner
203
+ item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "")
204
+ [item]
205
+ end
206
+ alias printable_tasks printable_commands
207
+
208
+ def handle_argument_error(command, error, arity=nil) #:nodoc:
209
+ if arity > 0
210
+ msg = "#{basename} #{command.name} takes #{arity} argument"
211
+ msg << "s" if arity > 1
212
+ msg << ", but it should not."
213
+ else
214
+ msg = "You should not pass arguments to #{basename} #{command.name}."
215
+ end
216
+
217
+ raise error, msg
218
+ end
219
+
220
+ protected
221
+
222
+ # The method responsible for dispatching given the args.
223
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
224
+ if Thor::HELP_MAPPINGS.include?(given_args.first)
225
+ help(config[:shell])
226
+ return
227
+ end
228
+
229
+ args, opts = Thor::Options.split(given_args)
230
+ opts = given_opts || opts
231
+
232
+ instance = new(args, opts, config)
233
+ yield instance if block_given?
234
+
235
+ if command
236
+ instance.invoke_command(all_commands[command])
237
+ else
238
+ instance.invoke_all
239
+ end
240
+ end
241
+
242
+ # The banner for this class. You can customize it if you are invoking the
243
+ # thor class by another ways which is not the Thor::Runner.
244
+ def banner
245
+ "#{basename} #{self_command.formatted_usage(self, false)}"
246
+ end
247
+
248
+ # Represents the whole class as a command.
249
+ def self_command #:nodoc:
250
+ Thor::DynamicCommand.new(self.namespace, class_options)
251
+ end
252
+ alias self_task self_command
253
+
254
+ def baseclass #:nodoc:
255
+ Thor::Group
256
+ end
257
+
258
+ def create_command(meth) #:nodoc:
259
+ commands[meth.to_s] = Thor::Command.new(meth, nil, nil, nil, nil)
260
+ true
261
+ end
262
+ alias create_task create_command
263
+ end
264
+
265
+ include Thor::Base
266
+
267
+ protected
268
+
269
+ # Shortcut to invoke with padding and block handling. Use internally by
270
+ # invoke and invoke_from_option class methods.
271
+ def _invoke_for_class_method(klass, command=nil, *args, &block) #:nodoc:
272
+ with_padding do
273
+ if block
274
+ case block.arity
275
+ when 3
276
+ block.call(self, klass, command)
277
+ when 2
278
+ block.call(self, klass)
279
+ when 1
280
+ instance_exec(klass, &block)
281
+ end
282
+ else
283
+ invoke klass, command, *args
284
+ end
285
+ end
286
+ end
287
+ end