josevalim-thor 0.10.21 → 0.10.22

Sign up to get free protection for your applications and to get access to all the features.
data/lib/thor/actions.rb CHANGED
@@ -142,6 +142,7 @@ class Thor
142
142
  # chmod "script/*", 0755
143
143
  #
144
144
  def chmod(path, mode, log_status=true)
145
+ return unless behavior == :invoke
145
146
  path = File.expand_path(path, root)
146
147
  say_status :chmod, relative_to_absolute_root(path), log_status
147
148
  FileUtils.chmod_R(mode, path) unless options[:pretend]
@@ -161,6 +162,7 @@ class Thor
161
162
  # end
162
163
  #
163
164
  def run(command, log_status=true)
165
+ return unless behavior == :invoke
164
166
  say_status :run, "#{command} from #{relative_to_absolute_root(root, false)}", log_status
165
167
  `#{command}` unless options[:pretend]
166
168
  end
@@ -218,6 +220,7 @@ class Thor
218
220
  # remove_file 'app/controllers/application_controller.rb'
219
221
  #
220
222
  def remove_file(path, log_status=true)
223
+ return unless behavior == :invoke
221
224
  path = File.expand_path(path, root)
222
225
  say_status :remove, relative_to_absolute_root(path), log_status
223
226
 
@@ -242,6 +245,7 @@ class Thor
242
245
  # end
243
246
  #
244
247
  def gsub_file(path, flag, *args, &block)
248
+ return unless behavior == :invoke
245
249
  log_status = args.last.is_a?(Symbol) || [ true, false ].include?(args.last) ? args.pop : true
246
250
 
247
251
  path = File.expand_path(path, root)
@@ -267,9 +271,9 @@ class Thor
267
271
  # append_file 'config/environments/test.rb', 'config.gem "rspec"'
268
272
  #
269
273
  def append_file(path, data=nil, log_status=true, &block)
274
+ return unless behavior == :invoke
270
275
  path = File.expand_path(path, root)
271
276
  say_status :append, relative_to_absolute_root(path), log_status
272
-
273
277
  File.open(path, 'ab') { |file| file.write(data || block.call) } unless options[:pretend]
274
278
  end
275
279
 
@@ -286,6 +290,7 @@ class Thor
286
290
  # prepend_file 'config/environments/test.rb', 'config.gem "rspec"'
287
291
  #
288
292
  def prepend_file(path, data=nil, log_status=true, &block)
293
+ return unless behavior == :invoke
289
294
  path = File.expand_path(path, root)
290
295
  say_status :prepend, relative_to_absolute_root(path), log_status
291
296
 
data/lib/thor/base.rb CHANGED
@@ -35,36 +35,19 @@ class Thor
35
35
  send("#{key}=", value)
36
36
  end
37
37
 
38
- if options.is_a?(Array)
39
- task_options = config.delete(:task_options)
40
- parse_options = self.class.class_options
41
- parse_options = parse_options.merge(task_options) if task_options
38
+ parse_options = self.class.class_options
42
39
 
43
- options = Thor::Options.parse(parse_options, options)
44
- _set_default_options(options, task_options) if task_options
40
+ options = if options.is_a?(Array)
41
+ task_options = config.delete(:task_options) # hook for start
42
+ parse_options = parse_options.merge(task_options) if task_options
43
+ Thor::Options.parse(parse_options, options)
44
+ else
45
+ Thor::Options.parse(parse_options, []).merge(options)
45
46
  end
46
47
 
47
- _set_default_options(options, self.class.class_options)
48
48
  self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).freeze
49
49
  end
50
50
 
51
- protected
52
-
53
- # Receives a hash of options, stringify keys and merge with default
54
- # values from thor options.
55
- #
56
- def _set_default_options(options, default_options)
57
- options.each_key do |key|
58
- next unless key.is_a?(Symbol)
59
- options[key.to_s] = options.delete(key)
60
- end
61
-
62
- default_options.each do |key, option|
63
- next if option.default.nil? || options.key?(option.human_name.to_s)
64
- options[option.human_name.to_s] ||= option.default
65
- end
66
- end
67
-
68
51
  class << self
69
52
  def included(base) #:nodoc:
70
53
  base.send :extend, ClassMethods
@@ -178,7 +161,7 @@ class Thor
178
161
 
179
162
  # Adds a bunch of options to the set of class options.
180
163
  #
181
- # class_options :foo => :optional, :bar => :required, :baz => :string
164
+ # class_options :foo => false, :bar => :required, :baz => :string
182
165
  #
183
166
  # If you prefer more detailed declaration, check class_option.
184
167
  #
@@ -200,11 +183,10 @@ class Thor
200
183
  # ==== Options
201
184
  # :desc - Description for the argument.
202
185
  # :required - If the argument is required or not.
203
- # :default - Default value for this argument. It cannot be required and have default values.
186
+ # :default - Default value for this argument.
204
187
  # :group - The group for this options. Use by class options to output options in different levels.
205
188
  # :aliases - Aliases for this option.
206
- # :type - The type of the argument, can be :string, :hash, :array, :numeric, :boolean or :default.
207
- # Default accepts arguments as booleans (--switch) or as strings (--switch=VALUE).
189
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
208
190
  # :banner - String to show on usage notes.
209
191
  #
210
192
  def class_option(name, options)
@@ -433,7 +415,7 @@ class Thor
433
415
  # Receives a hash of options, parse them and add to the scope. This is a
434
416
  # fast way to set a bunch of options:
435
417
  #
436
- # build_options :foo => :optional, :bar => :required, :baz => :string
418
+ # build_options :foo => true, :bar => :required, :baz => :string
437
419
  #
438
420
  # ==== Parameters
439
421
  # Hash[Symbol => Object]
@@ -76,9 +76,10 @@ class Thor
76
76
  # invoke Rspec::RR, [], :style => :foo
77
77
  #
78
78
  def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil)
79
- task, args, opts, config = nil, task, args, opts if task.is_a?(Array)
80
- object, task = _setup_for_invoke(name, task)
79
+ task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array)
80
+ args, opts, config = nil, args, opts if args.is_a?(Hash)
81
81
 
82
+ object, task = _setup_for_invoke(name, task)
82
83
  if object.is_a?(Class)
83
84
  klass = object
84
85
 
@@ -9,15 +9,16 @@ class Thor
9
9
  class_name = self.class.name.split("::").last
10
10
 
11
11
  raise ArgumentError, "#{class_name} name can't be nil." if name.nil?
12
- raise ArgumentError, "#{class_name} cannot be required and have default value." if required && !default.nil?
13
12
  raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type)
14
13
 
15
14
  @name = name.to_s
16
15
  @description = description
17
16
  @required = required || false
18
- @type = (type || :default).to_sym
17
+ @type = (type || :string).to_sym
19
18
  @default = default
20
19
  @banner = banner || default_banner
20
+
21
+ validate! # Trigger specific validations
21
22
  end
22
23
 
23
24
  def usage
@@ -37,12 +38,12 @@ class Thor
37
38
  end
38
39
  end
39
40
 
40
- def input_required?
41
- [ :numeric, :hash, :array, :string ].include?(type)
42
- end
43
-
44
41
  protected
45
42
 
43
+ def validate!
44
+ raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil?
45
+ end
46
+
46
47
  def valid_type?(type)
47
48
  VALID_TYPES.include?(type.to_sym)
48
49
  end
@@ -23,24 +23,29 @@ class Thor
23
23
  # Takes an array of Thor::Argument objects.
24
24
  #
25
25
  def initialize(arguments=[])
26
- @arguments = arguments
27
- @non_assigned_required = @arguments.select { |a| a.required? }
26
+ @assigns, @non_assigned_required = {}, []
27
+ @switches = arguments
28
+
29
+ arguments.each do |argument|
30
+ if argument.default
31
+ @assigns[argument.human_name] = argument.default
32
+ elsif argument.required?
33
+ @non_assigned_required << argument
34
+ end
35
+ end
28
36
  end
29
37
 
30
38
  def parse(args)
31
- @pile, assigns = args.dup, {}
39
+ @pile = args.dup
32
40
 
33
- @arguments.each do |argument|
34
- assigns[argument.human_name] = if peek
35
- @non_assigned_required.delete(argument)
36
- send(:"parse_#{argument.type}", argument.human_name)
37
- else
38
- argument.default
39
- end
41
+ @switches.each do |argument|
42
+ break unless peek
43
+ @non_assigned_required.delete(argument)
44
+ @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name)
40
45
  end
41
46
 
42
47
  check_requirement!
43
- assigns
48
+ @assigns
44
49
  end
45
50
 
46
51
  private
@@ -2,10 +2,10 @@ class Thor
2
2
  class Option < Argument
3
3
  attr_reader :aliases, :group
4
4
 
5
- VALID_TYPES = [:boolean, :numeric, :hash, :array, :string, :default]
5
+ VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
6
6
 
7
7
  def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil)
8
- super(name, description, required, type || :default, default, banner)
8
+ super(name, description, required, type, default, banner)
9
9
  @aliases = [*aliases].compact
10
10
  @group = group.to_s.capitalize if group
11
11
  end
@@ -22,9 +22,6 @@ class Thor
22
22
  # parse :foo => :required
23
23
  # #=> Required option foo without default value
24
24
  #
25
- # parse :foo => :optional
26
- # #=> Optional foo without default value
27
- #
28
25
  # parse :foo => 2
29
26
  # #=> Option foo with default value 2 and type numeric
30
27
  #
@@ -58,6 +55,10 @@ class Thor
58
55
  value
59
56
  elsif required = (value == :required)
60
57
  :string
58
+ elsif value == :optional
59
+ # TODO Remove this warning in the future.
60
+ warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean."
61
+ :boolean
61
62
  end
62
63
  when TrueClass, FalseClass
63
64
  :boolean
@@ -94,8 +95,16 @@ class Thor
94
95
  end
95
96
  end
96
97
 
98
+ def input_required?
99
+ type != :boolean
100
+ end
101
+
97
102
  protected
98
103
 
104
+ def validate!
105
+ raise ArgumentError, "An option cannot be boolean and required." if type == :boolean && required?
106
+ end
107
+
99
108
  def valid_type?(type)
100
109
  VALID_TYPES.include?(type.to_sym)
101
110
  end
@@ -30,23 +30,22 @@ class Thor
30
30
 
31
31
  # Takes a hash of Thor::Option objects.
32
32
  #
33
- def initialize(switches={})
34
- @shorts, @non_assigned_required = {}, []
33
+ def initialize(options={})
34
+ options = options.values
35
+ super(options)
36
+ @shorts, @switches = {}, {}
35
37
 
36
- @switches = switches.values.inject({}) do |mem, option|
37
- @non_assigned_required << option if option.required?
38
+ options.each do |option|
39
+ @switches[option.switch_name] = option
38
40
 
39
41
  option.aliases.each do |short|
40
42
  @shorts[short.to_s] ||= option.switch_name
41
43
  end
42
-
43
- mem[option.switch_name] = option
44
- mem
45
44
  end
46
45
  end
47
46
 
48
47
  def parse(args)
49
- @pile, options = args.dup, {}
48
+ @pile = args.dup
50
49
 
51
50
  while peek
52
51
  if current_is_switch?
@@ -64,19 +63,14 @@ class Thor
64
63
  switch = normalize_switch(switch)
65
64
  next unless option = switch_option(switch)
66
65
 
67
- if option.input_required?
68
- raise RequiredArgumentMissingError, "no value provided for required option '#{switch}'" if peek.nil?
69
- raise MalformattedArgumentError, "cannot pass switch '#{peek}' as an argument" unless current_is_value?
70
- end
71
-
72
- options[option.human_name] = parse_peek(switch, option)
66
+ @assigns[option.human_name] = parse_peek(switch, option)
73
67
  else
74
68
  shift
75
69
  end
76
70
  end
77
71
 
78
72
  check_requirement!
79
- options
73
+ @assigns
80
74
  end
81
75
 
82
76
  protected
@@ -97,13 +91,18 @@ class Thor
97
91
  end
98
92
 
99
93
  def switch_option(arg)
100
- if arg =~ /^--(no|skip)-([-\w]+)$/
101
- @switches[arg] || @switches["--#{$2}"]
94
+ if match = no_or_skip?(arg)
95
+ @switches[arg] || @switches["--#{match}"]
102
96
  else
103
97
  @switches[arg]
104
98
  end
105
99
  end
106
100
 
101
+ def no_or_skip?(arg)
102
+ arg =~ /^--(no|skip)-([-\w]+)$/
103
+ $2
104
+ end
105
+
107
106
  # Check if the given argument is actually a shortcut.
108
107
  #
109
108
  def normalize_switch(arg)
@@ -116,24 +115,20 @@ class Thor
116
115
  if current_is_value?
117
116
  ["true", "TRUE", "t", "T", true].include?(shift)
118
117
  else
119
- @switches.key?(switch) || switch !~ /^--(no|skip)-([-\w]+)$/
118
+ @switches.key?(switch) || !no_or_skip?(switch)
120
119
  end
121
120
  end
122
121
 
123
- # Receives switch, option and the current values hash and assign the next
124
- # value to it. Also removes the option from the array where non assigned
125
- # required are kept.
122
+ # Parse the value at the peek analyzing if it requires an input or not.
126
123
  #
127
124
  def parse_peek(switch, option)
128
- @non_assigned_required.delete(option)
129
-
130
- type = if option.type == :default
131
- current_is_value? ? :string : :boolean
132
- else
133
- option.type
125
+ if option.input_required?
126
+ return nil if no_or_skip?(switch)
127
+ raise MalformattedArgumentError, "no value provided for option '#{switch}'" unless current_is_value?
134
128
  end
135
129
 
136
- send(:"parse_#{type}", switch)
130
+ @non_assigned_required.delete(option)
131
+ send(:"parse_#{option.type}", switch)
137
132
  end
138
133
 
139
134
  end
data/lib/thor/runner.rb CHANGED
@@ -31,7 +31,7 @@ class Thor::Runner < Thor
31
31
  end
32
32
 
33
33
  desc "install NAME", "Install a Thor file into your system tasks, optionally named for future updates"
34
- method_options :as => :optional, :relative => :boolean
34
+ method_options :as => :string, :relative => :boolean
35
35
  def install(name)
36
36
  initialize_thorfiles
37
37
 
@@ -132,7 +132,7 @@ class Thor::Runner < Thor
132
132
 
133
133
  desc "list [SEARCH]",
134
134
  "List the available thor tasks (--substring means SEARCH anywhere in the namespace)"
135
- method_options :substring => :boolean, :group => :optional, :all => :boolean
135
+ method_options :substring => :boolean, :group => :string, :all => :boolean
136
136
  def list(search="")
137
137
  initialize_thorfiles
138
138
 
data/lib/thor.rb CHANGED
@@ -72,7 +72,8 @@ class Thor
72
72
  #
73
73
  # ==== Parameters
74
74
  # Hash[Symbol => Object]:: The hash key is the name of the option and the value
75
- # is the type of the option. Can be :optional, :required, :boolean or :numeric.
75
+ # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric
76
+ # or :required (string). If you give a value, the type of the value is used.
76
77
  #
77
78
  def method_options(options=nil)
78
79
  @method_options ||= {}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: josevalim-thor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.21
4
+ version: 0.10.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yehuda Katz
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-30 00:00:00 -07:00
12
+ date: 2009-07-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15