toys-core 0.14.7 → 0.15.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.
data/lib/toys/dsl/flag.rb CHANGED
@@ -120,7 +120,14 @@ module Toys
120
120
  # should be set. You may pass the handler as a Proc (or an object
121
121
  # responding to the `call` method) or you may pass a block.
122
122
  #
123
- # @param handler [Proc]
123
+ # You can also pass one of the special values `:set` or `:push` as the
124
+ # handler. The `:set` handler replaces the previous value (equivalent to
125
+ # `-> (val, _prev) { val }`.) The `:push` handler expects the previous
126
+ # value to be an array and pushes the given value onto it; it should be
127
+ # combined with setting the default value to `[]` and is intended for
128
+ # "multi-valued" flags.
129
+ #
130
+ # @param handler [Proc,:set,:push]
124
131
  # @param block [Proc]
125
132
  # @return [self]
126
133
  #
@@ -268,13 +275,36 @@ module Toys
268
275
  self
269
276
  end
270
277
 
278
+ ##
279
+ # Specify whether to add a method for this flag.
280
+ #
281
+ # Recognized values are true to force creation of a method, false to
282
+ # disable method creation, and nil for the default behavior. The default
283
+ # checks the name and adds a method if the name is a symbol representing
284
+ # a legal method name that starts with a letter and does not override any
285
+ # public method in the Ruby Object class or collide with any method
286
+ # directly defined in the tool class.
287
+ #
288
+ # @param value [true,false,nil]
289
+ #
290
+ def add_method(value)
291
+ @add_method =
292
+ if value.nil?
293
+ nil
294
+ elsif value
295
+ true
296
+ else
297
+ false
298
+ end
299
+ end
300
+
271
301
  ##
272
302
  # Called only from DSL::Tool
273
303
  #
274
304
  # @private
275
305
  #
276
306
  def initialize(flags, acceptor, default, handler, flag_completion, value_completion,
277
- report_collisions, group, desc, long_desc, display_name)
307
+ report_collisions, group, desc, long_desc, display_name, method_flag)
278
308
  @flags = flags
279
309
  @default = default
280
310
  @handler = handler
@@ -286,6 +316,7 @@ module Toys
286
316
  accept(acceptor)
287
317
  complete_flags(flag_completion, **{})
288
318
  complete_values(value_completion, **{})
319
+ add_method(method_flag)
289
320
  end
290
321
 
291
322
  ##
@@ -298,6 +329,13 @@ module Toys
298
329
  report_collisions: @report_collisions, group: @group,
299
330
  desc: @desc, long_desc: @long_desc, display_name: @display_name)
300
331
  end
332
+
333
+ ##
334
+ # @private
335
+ #
336
+ def _get_add_method
337
+ @add_method
338
+ end
301
339
  end
302
340
  end
303
341
  end
@@ -181,19 +181,29 @@ module Toys
181
181
  # arguments.) Defaults to the empty array.
182
182
  # @param display_name [String] A display name for this flag, used in help
183
183
  # text and error messages.
184
+ # @param add_method [true,false,nil] Whether to add a method for this
185
+ # flag. If omitted or set to nil, uses the default behavior, which
186
+ # adds the method if the key is a symbol representing a legal method
187
+ # name that starts with a letter and does not override any public
188
+ # method in the Ruby Object class or collide with any method directly
189
+ # defined in the tool class.
184
190
  # @param block [Proc] Configures the flag. See {Toys::DSL::Flag} for the
185
191
  # directives that can be called in this block.
186
192
  # @return [self]
187
193
  #
188
194
  def flag(key, *flags,
189
- accept: nil, default: nil, handler: nil, complete_flags: nil, complete_values: nil,
190
- report_collisions: true, desc: nil, long_desc: nil, display_name: nil,
195
+ accept: nil, default: nil, handler: nil,
196
+ complete_flags: nil, complete_values: nil,
197
+ report_collisions: true, desc: nil, long_desc: nil,
198
+ display_name: nil, add_method: nil,
191
199
  &block)
192
- flag_dsl = DSL::Flag.new(flags, accept, default, handler, complete_flags, complete_values,
193
- report_collisions, @flag_group, desc, long_desc, display_name)
200
+ flag_dsl = DSL::Flag.new(flags, accept, default, handler,
201
+ complete_flags, complete_values,
202
+ report_collisions, @flag_group, desc, long_desc,
203
+ display_name, add_method)
194
204
  flag_dsl.instance_exec(flag_dsl, &block) if block
195
205
  flag_dsl._add_to(@tool, key)
196
- DSL::Internal.maybe_add_getter(@tool_dsl, key)
206
+ DSL::Internal.maybe_add_getter(@tool_dsl, key, flag_dsl._get_add_method)
197
207
  self
198
208
  end
199
209
 
@@ -8,6 +8,14 @@ module Toys
8
8
  # @private
9
9
  #
10
10
  module Internal
11
+ ##
12
+ # @private A list of method names to avoid using as getters
13
+ #
14
+ AVOID_GETTERS = (::Object.instance_methods + [:run, :initialize])
15
+ .find_all { |name| /^[a-z]\w*$/.match?(name) }
16
+ .map { |name| [name, true] }.to_h
17
+ .freeze
18
+
11
19
  class << self
12
20
  ##
13
21
  # Called by the Loader and InputFile to prepare a tool class for running
@@ -91,14 +99,21 @@ module Toys
91
99
  #
92
100
  # @private
93
101
  #
94
- def maybe_add_getter(tool_class, key)
95
- if key.is_a?(::Symbol) && key.to_s =~ /^[_a-zA-Z]\w*[!?]?$/ && key != :run
96
- unless tool_class.public_method_defined?(key)
97
- tool_class.class_eval do
98
- define_method(key) do
99
- self[key]
100
- end
101
- end
102
+ def maybe_add_getter(tool_class, key, force)
103
+ return unless key.is_a?(::Symbol)
104
+ case force
105
+ when false
106
+ return
107
+ when true
108
+ return unless /^[_a-zA-Z]\w*[!?]?$/.match(key.to_s)
109
+ when nil
110
+ return if !/^[a-zA-Z]\w*[!?]?$/.match?(key.to_s) ||
111
+ AVOID_GETTERS.key?(key) ||
112
+ Compat.method_defined_without_ancestors?(tool_class, key)
113
+ end
114
+ tool_class.class_eval do
115
+ define_method(key) do
116
+ self[key]
102
117
  end
103
118
  end
104
119
  end
@@ -141,18 +141,42 @@ module Toys
141
141
  self
142
142
  end
143
143
 
144
+ ##
145
+ # Specify whether to add a method for this argument.
146
+ #
147
+ # Recognized values are true to force creation of a method, false to
148
+ # disable method creation, and nil for the default behavior. The default
149
+ # checks the name and adds a method if the name is a symbol representing
150
+ # a legal method name that starts with a letter and does not override any
151
+ # public method in the Ruby Object class or collide with any method
152
+ # directly defined in the tool class.
153
+ #
154
+ # @param value [true,false,nil]
155
+ #
156
+ def add_method(value)
157
+ @add_method =
158
+ if value.nil?
159
+ nil
160
+ elsif value
161
+ true
162
+ else
163
+ false
164
+ end
165
+ end
166
+
144
167
  ##
145
168
  # Called only from DSL::Tool
146
169
  #
147
170
  # @private
148
171
  #
149
- def initialize(acceptor, default, completion, display_name, desc, long_desc)
172
+ def initialize(acceptor, default, completion, display_name, desc, long_desc, method_flag)
150
173
  @default = default
151
174
  @display_name = display_name
152
175
  @desc = desc
153
176
  @long_desc = long_desc || []
154
177
  accept(acceptor, **{})
155
178
  complete(completion, **{})
179
+ add_method(method_flag)
156
180
  end
157
181
 
158
182
  ##
@@ -181,6 +205,13 @@ module Toys
181
205
  accept: @acceptor, default: @default, complete: @completion,
182
206
  display_name: @display_name, desc: @desc, long_desc: @long_desc)
183
207
  end
208
+
209
+ ##
210
+ # @private
211
+ #
212
+ def _get_add_method
213
+ @add_method
214
+ end
184
215
  end
185
216
  end
186
217
  end