atli 0.1.9 → 0.1.10

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.
@@ -129,94 +129,21 @@ module ClassMethods
129
129
  end
130
130
 
131
131
 
132
- # Adds an argument to the class and creates an attr_accessor for it.
133
- #
134
- # Arguments are different from options in several aspects. The first one
135
- # is how they are parsed from the command line, arguments are retrieved
136
- # from position:
137
- #
138
- # thor command NAME
139
- #
140
- # Instead of:
141
- #
142
- # thor command --name=NAME
143
- #
144
- # Besides, arguments are used inside your code as an accessor
145
- # (self.argument), while options are all kept in a hash (self.options).
146
- #
147
- # Finally, arguments cannot have type :default or :boolean but can be
148
- # optional (supplying :optional => :true or :required => false), although
149
- # you cannot have a required argument after a non-required argument. If
150
- # you try it, an error is raised.
151
- #
152
- # ==== Parameters
153
- # name<Symbol>:: The name of the argument.
154
- # options<Hash>:: Described below.
155
- #
156
- # ==== Options
157
- # :desc - Description for the argument.
158
- # :required - If the argument is required or not.
159
- # :optional - If the argument is optional or not.
160
- # :type - The type of the argument, can be :string, :hash, :array,
161
- # :numeric.
162
- # :default - Default value for this argument. It cannot be required and
163
- # have default values.
164
- # :banner - String to show on usage notes.
165
- #
166
- # ==== Errors
167
- # ArgumentError:: Raised if you supply a required argument after a non
168
- # required one.
169
- #
170
- def argument(name, options = {})
171
- is_thor_reserved_word?(name, :argument)
172
- no_commands { attr_accessor name }
173
-
174
- required = if options.key?(:optional)
175
- !options[:optional]
176
- elsif options.key?(:required)
177
- options[:required]
178
- else
179
- options[:default].nil?
180
- end
181
-
182
- remove_argument name
183
-
184
- if required
185
- arguments.each do |argument|
186
- next if argument.required?
187
- raise ArgumentError,
188
- "You cannot have #{name.to_s.inspect} as required argument " \
189
- "after the non-required argument #{argument.human_name.inspect}."
190
- end
191
- end
192
-
193
- options[:required] = required
194
-
195
- arguments << Thor::Argument.new(name, options)
196
- end
197
-
198
-
199
- # Returns this class arguments, looking up in the ancestors chain.
200
- #
201
- # ==== Returns
202
- # Array[Thor::Argument]
203
- #
204
- def arguments
205
- @arguments ||= from_superclass(:arguments, [])
206
- end
207
-
208
-
209
132
  # Adds a bunch of options to the set of class options.
210
133
  #
211
134
  # class_options :foo => false, :bar => :required, :baz => :string
212
135
  #
213
136
  # If you prefer more detailed declaration, check class_option.
214
137
  #
215
- # ==== Parameters
216
- # Hash[Symbol => Object]
138
+ # @param [Hash<(String | Symbol), Object>] options
139
+ # New option definitions to add via {#build_options}.
140
+ #
141
+ # @return [HashWithIndifferentAccess<String, Thor::Option>]
142
+ # Hash of option names to the option instances.
217
143
  #
218
- def class_options(options = nil)
219
- @class_options ||= from_superclass(:class_options, {})
144
+ def class_options options = nil
145
+ @class_options ||= \
146
+ from_superclass( :class_options, HashWithIndifferentAccess.new )
220
147
  build_options(options, @class_options) if options
221
148
  @class_options
222
149
  end
@@ -248,27 +175,6 @@ module ClassMethods
248
175
  end
249
176
 
250
177
 
251
- # Removes a previous defined argument. If :undefine is given, undefine
252
- # accessors as well.
253
- #
254
- # ==== Parameters
255
- # names<Array>:: Arguments to be removed
256
- #
257
- # ==== Examples
258
- #
259
- # remove_argument :foo
260
- # remove_argument :foo, :bar, :baz, :undefine => true
261
- #
262
- def remove_argument(*names)
263
- options = names.last.is_a?(Hash) ? names.pop : {}
264
-
265
- names.each do |name|
266
- arguments.delete_if { |a| a.name == name.to_s }
267
- undef_method name, "#{name}=" if options[:undefine]
268
- end
269
- end
270
-
271
-
272
178
  # Removes a previous defined class option.
273
179
  #
274
180
  # ==== Parameters
@@ -304,25 +210,24 @@ module ClassMethods
304
210
 
305
211
  # Returns the commands for this Thor class.
306
212
  #
307
- # ==== Returns
308
- # OrderedHash:: An ordered hash with commands names as keys and
309
- # Thor::Command objects as values.
213
+ # @return [HashWithIndifferentAccess<String, Thor::Command>]
214
+ # An hash with commands names as keys and Thor::Command objects as values.
310
215
  #
311
216
  def commands
312
- @commands ||= Thor::CoreExt::OrderedHash.new
217
+ @commands ||= HashWithIndifferentAccess.new
313
218
  end
314
219
  alias_method :tasks, :commands
315
220
 
316
221
 
317
222
  # Returns the commands for this Thor class and all subclasses.
318
223
  #
319
- # ==== Returns
320
- # OrderedHash:: An ordered hash with commands names as keys and
321
- # Thor::Command objects as values.
224
+ # @return [HashWithIndifferentAccess<String, Thor::Command>]
225
+ # An hash with commands names as keys and {Thor::Command}
226
+ # objects as values.
322
227
  #
323
228
  def all_commands
324
229
  @all_commands ||= from_superclass( :all_commands,
325
- Thor::CoreExt::OrderedHash.new )
230
+ HashWithIndifferentAccess.new )
326
231
  @all_commands.merge!(commands)
327
232
  end
328
233
  alias_method :all_tasks, :all_commands
@@ -451,13 +356,12 @@ module ClassMethods
451
356
  # For details on why this is here see
452
357
  # {file:doc/files/notes/too-broken-to-fail.md Too Broken to Fail}.
453
358
  #
454
- def exec!(given_args = ARGV, config = {})
359
+ def exec! given_args = ARGV, config = {}
455
360
  execution = Thor::Execution.new thor_class: self,
456
361
  given_args: given_args,
457
362
  thor_config: config
458
-
459
363
  execution.exec!
460
- end # #start
364
+ end # #exec!
461
365
 
462
366
 
463
367
  # Allows to use private methods from parent in child classes as commands.
@@ -485,7 +389,7 @@ module ClassMethods
485
389
  "#{namespace.inspect} namespace."
486
390
  end
487
391
  raise Thor::UndefinedCommandError,
488
- "Could not find command #{command.inspect}."
392
+ "Could not find command #{command.inspect}, commands: #{ all_commands.keys }"
489
393
  end
490
394
  alias_method :handle_no_task_error, :handle_no_command_error
491
395
 
@@ -599,11 +503,12 @@ module ClassMethods
599
503
  # name<Symbol>:: The name of the argument.
600
504
  # options<Hash>:: Described in both class_option and method_option.
601
505
  # scope<Hash>:: Options hash that is being built up
602
- def build_option(name, options, scope) #:nodoc:
603
- scope[name] = Thor::Option.new(
506
+ def build_option(name, options, scope)
507
+ option = Thor::Option.new(
604
508
  name,
605
509
  options.merge(:check_default_type => check_default_type?)
606
510
  )
511
+ scope[option.name] = option
607
512
  end
608
513
 
609
514
 
@@ -612,11 +517,17 @@ module ClassMethods
612
517
  #
613
518
  # build_options :foo => true, :bar => :required, :baz => :string
614
519
  #
615
- # ==== Parameters
616
- # Hash[Symbol => Object]
617
- def build_options(options, scope) #:nodoc:
520
+ # @param [Hash<(String | Symbol), Object>] options
521
+ #
522
+ # @param [HashWithIndifferentAccess<String, Thor::Option>] scope
523
+ #
524
+ # @return [nil]
525
+ # New {Thor::Option} are added to `scope`.
526
+ #
527
+ def build_options options, scope
618
528
  options.each do |key, value|
619
- scope[key] = Thor::Option.parse(key, value)
529
+ option = Thor::Option.parse key, value
530
+ scope[option.name] = option
620
531
  end
621
532
  end
622
533
 
@@ -0,0 +1,123 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ require 'active_support/concern'
11
+
12
+
13
+ # Refinements
14
+ # =======================================================================
15
+
16
+ require 'nrser/refinements/types'
17
+ using NRSER::Types
18
+
19
+ # Namespace
20
+ # =======================================================================
21
+
22
+ class Thor
23
+ module Base
24
+
25
+ # Definitions
26
+ # =======================================================================
27
+
28
+ # Share stuff... define {Thor::Argument}, {Thor::Option} and whatever else
29
+ # you like once then apply those definitions to many commands.
30
+ #
31
+ module SharedConcern
32
+
33
+ extend ActiveSupport::Concern
34
+
35
+ class_methods do
36
+ # ==========================================================================
37
+
38
+ def shared_defs
39
+ @shared_defs ||= []
40
+ end
41
+
42
+
43
+ # def normalize_kind input
44
+ # {
45
+ # 'arg' => 'argument',
46
+
47
+ # }
48
+ # end
49
+
50
+
51
+ def def_shared kind, name:, groups: nil, **options
52
+ shared_defs << {
53
+ name: name.to_s,
54
+ kind: kind,
55
+ groups: Set[*groups],
56
+ options: options,
57
+ }
58
+ end
59
+
60
+
61
+ def include_shared *names, kinds: nil, groups: nil, **overrides
62
+ find_shared( *names, kinds: kinds, groups: groups ).
63
+ each do |name:, kind:, groups:, options:|
64
+ send kind, name, **options.merge( overrides )
65
+ end
66
+ end
67
+
68
+
69
+ # Find shared options given names and groups.
70
+ #
71
+ # @param [*<Symbol>] names
72
+ # Individual shared option names to include.
73
+ #
74
+ # @param [nil | Symbol | Enumerable<Symbol>] groups:
75
+ # Single or list of shared option groups to include.
76
+ #
77
+ # @return [Hash<Symbol, Thor::SharedOption>]
78
+ # Hash mapping option names (as {Symbol}) to instances.
79
+ #
80
+ def find_shared *names, kinds: nil, groups: nil
81
+ groups_set = Set[*groups]
82
+ kinds_set = Set[*kinds]
83
+ names.map! &:to_s
84
+
85
+ results = []
86
+
87
+ shared_defs.each do |name:, kind:, groups:, options:|
88
+ match = {}
89
+
90
+ if names.include? name
91
+ match[:name] = true
92
+ end
93
+
94
+ match_groups = groups & groups_set
95
+
96
+ unless match_groups.empty?
97
+ match[:groups] = match_groups
98
+ end
99
+
100
+ if kinds_set.include? kind
101
+ match[:kind] = true
102
+ end
103
+
104
+ unless match.empty?
105
+ results << {
106
+ name: name,
107
+ kind: kind,
108
+ groups: groups,
109
+ options: options,
110
+ }
111
+ end
112
+ end
113
+ end # #find_shared
114
+
115
+ end # class_methods ********************************************************
116
+
117
+ end # module SharedConcern
118
+
119
+ # /Namespace
120
+ # =======================================================================
121
+
122
+ end # module Base
123
+ end # class Thor
@@ -0,0 +1,235 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+
5
+ # Requirements
6
+ # =======================================================================
7
+
8
+ # Deps
9
+ # -----------------------------------------------------------------------
10
+
11
+ require 'active_support/concern'
12
+
13
+
14
+ # Refinements
15
+ # =======================================================================
16
+
17
+ require 'nrser/refinements/types'
18
+ using NRSER::Types
19
+
20
+ # Namespace
21
+ # =======================================================================
22
+
23
+ class Thor
24
+ module Base
25
+
26
+
27
+ # Definitions
28
+ # =======================================================================
29
+
30
+ # Support for sharing {Thor::Option} declarations among many
31
+ # {Thor::Command} (methods). All class methods.
32
+ #
33
+ module SharedOptionsConcern
34
+
35
+ # Mixins
36
+ # ========================================================================
37
+
38
+ # Get concerned
39
+ extend ActiveSupport::Concern
40
+
41
+
42
+ class_methods do
43
+ # ==========================================================================
44
+
45
+ # Declare a shared method option with an optional groups that can then
46
+ # be added by name or group to commands.
47
+ #
48
+ # The shared options can then be added to methods individually by name and
49
+ # collectively as groups with {Thor.include_method_options}.
50
+ #
51
+ # @example
52
+ # class MyCLI < Thor
53
+ #
54
+ # # Declare a shared option:
55
+ # shared_option :force,
56
+ # groups: :write,
57
+ # desc: "Force the operation",
58
+ # type: :boolean
59
+ #
60
+ # # ...
61
+ #
62
+ # desc "write [OPTIONS] path",
63
+ # "Write to a path"
64
+ #
65
+ # # Add the shared options to the method:
66
+ # include_options groups: :write
67
+ #
68
+ # def write path
69
+ #
70
+ # # Get a slice of `#options` with any of the `:write` group options
71
+ # # that were provided and use it in a method call:
72
+ # MyModule.write path, **option_kwds( groups: :write )
73
+ #
74
+ # end
75
+ # end
76
+ #
77
+ # @param [Symbol] name
78
+ # The name of the option.
79
+ #
80
+ # @param [**<Symbol, V>] options
81
+ # Keyword args used to initialize the {Thor::SharedOption}.
82
+ #
83
+ # All +**options+ are optional.
84
+ #
85
+ # @option options [Symbol | Array<Symbol>] :groups
86
+ # One or more _shared_ _option_ _group_ that the new option will belong
87
+ # to.
88
+ #
89
+ # Examples:
90
+ # groups: :read
91
+ # groups: [:read, :write]
92
+ #
93
+ # *NOTE* The keyword is +groups+ with an +s+! {Thor::Option} already has
94
+ # a +group+ string attribute that, as far as I can tell, is only
95
+ #
96
+ # @option options [String] :desc
97
+ # Description for the option for help and feedback.
98
+ #
99
+ # @option options [Boolean] :required
100
+ # If the option is required or not.
101
+ #
102
+ # @option options [Object] :default
103
+ # Default value for this argument.
104
+ #
105
+ # It cannot be +required+ and have default values.
106
+ #
107
+ # @option options [String | Array<String>] :aliases
108
+ # Aliases for this option.
109
+ #
110
+ # Examples:
111
+ # aliases: '-s'
112
+ # aliases: '--other-name'
113
+ # aliases: ['-s', '--other-name']
114
+ #
115
+ # @option options [:string | :hash | :array | :numeric | :boolean] :type
116
+ # Type of acceptable values, see
117
+ # {types for method options}[https://github.com/erikhuda/thor/wiki/Method-Options#types-for-method_options]
118
+ # in the Thor wiki.
119
+ #
120
+ # @option options [String] :banner
121
+ # String to show on usage notes.
122
+ #
123
+ # @option options [Boolean] :hide
124
+ # If you want to hide this option from the help.
125
+ #
126
+ # @return (see .build_shared_option)
127
+ #
128
+ def shared_method_option name, **options
129
+ # Don't think the `:for` option makes sense... that would just be a
130
+ # regular method option, right? I guess `:for` could be an array and
131
+ # apply the option to each command, but it seems like that would just
132
+ # be better as an extension to the {.method_option} behavior.
133
+ #
134
+ # So, we raise if we see it
135
+ if options.key? :for
136
+ raise ArgumentError,
137
+ ".shared_method_option does not accept the `:for` option"
138
+ end
139
+
140
+ build_shared_option(name, options)
141
+ end # #shared_method_option
142
+
143
+ alias_method :shared_option, :shared_method_option
144
+
145
+
146
+ # @return [Hash<Symbol, Thor::SharedOption]
147
+ # Get all shared options
148
+ #
149
+ def shared_method_options(options = nil)
150
+ @shared_method_options ||= begin
151
+ # Reach up the inheritance chain, if there's anyone there
152
+ if superclass.respond_to? __method__
153
+ superclass.send( __method__ ).dup
154
+ else
155
+ # Or just default to empty
156
+ {}
157
+ end
158
+ end
159
+
160
+ if options
161
+ # We don't support this (yet at least)
162
+ raise NotImplementedError,
163
+ "Bulk set not supported, use .shared_method_option"
164
+ # build_shared_options(options, @shared_method_options)
165
+ end
166
+ @shared_method_options
167
+ end
168
+
169
+ alias_method :shared_options, :shared_method_options
170
+
171
+
172
+ # Find shared options given names and groups.
173
+ #
174
+ # @param [*<Symbol>] names
175
+ # Individual shared option names to include.
176
+ #
177
+ # @param [nil | Symbol | Enumerable<Symbol>] groups:
178
+ # Single or list of shared option groups to include.
179
+ #
180
+ # @return [Hash<Symbol, Thor::SharedOption>]
181
+ # Hash mapping option names (as {Symbol}) to instances.
182
+ #
183
+ def find_shared_method_options *names, groups: nil
184
+ groups_set = Set[*groups]
185
+
186
+ shared_method_options.each_with_object( {} ) do |(name, option), results|
187
+ match = {}
188
+
189
+ if names.include? name
190
+ match[:name] = true
191
+ end
192
+
193
+ match_groups = option.groups & groups_set
194
+
195
+ unless match_groups.empty?
196
+ match[:groups] = match_groups
197
+ end
198
+
199
+ unless match.empty?
200
+ results[name] = {
201
+ option: option,
202
+ match: match,
203
+ }
204
+ end
205
+ end
206
+ end # #find_shared_method_options
207
+
208
+ alias_method :find_shared_options, :find_shared_method_options
209
+
210
+
211
+ # Add the {Thor::SharedOption} instances with +names+ and in +groups+ to
212
+ # the next defined command method.
213
+ #
214
+ # @param (see .find_shared_method_options)
215
+ # @return (see .find_shared_method_options)
216
+ #
217
+ def include_method_options *names, groups: nil
218
+ find_shared_method_options( *names, groups: groups ).
219
+ each do |name, result|
220
+ method_options[name] = Thor::IncludedOption.new **result
221
+ end
222
+ end
223
+
224
+ alias_method :include_options, :include_method_options
225
+
226
+ end # class_methods ********************************************************
227
+
228
+ end # module SharedOptionsConcern
229
+
230
+
231
+ # /Namespace
232
+ # =======================================================================
233
+
234
+ end # module Base
235
+ end # class Thor