shellopts 2.0.1 → 2.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f5448df8e0fdd882072ab927e185511b09ebd8b594a9556937fdfd20d41070d
4
- data.tar.gz: 2743f77e88de6ff10562a2f7d3980b1bfc730d0e024e60e6472da48342a2f153
3
+ metadata.gz: 0170d9ce5144afcf716b90a3904250c0afa5d769b7a64f39db0b8084e77b4fb7
4
+ data.tar.gz: 81495a3802c472c65812594d847c43b0f59849ea0ebe093c74c2fb7d3e822658
5
5
  SHA512:
6
- metadata.gz: 9e08795c96b4f745a00cb6c38e5ea63beef08ceb640a0427d4bc46ee705189cab188a227a9d1775177d6530596155744d6e8624fa378c87c47f94c36e1adf98b
7
- data.tar.gz: cb12f16c665fe6fc0e0751ad2328aa7d8e1e48baad9d9d27addb4d88f6a083d780c61ee0b8b57e8218ee829a6e107afa8c076067dfa5d24a973bf353489d7433
6
+ metadata.gz: 195801ea89b22920fca88216ed4bd7ac426b3370e482b61547dac085d1c7d9f1bd0a2d0edc7c3368bf126cd5f4da815dd882ee3149cd291549ff631d6302e93a
7
+ data.tar.gz: 6dcd50871438db9f5b0520e4f670f6df6ad04756685838d309874a9601770ee79a7370ebc11b0469d19a9f2be89868c7cfd12cfe028c0c01719b4d8d0593fc59
@@ -14,8 +14,8 @@ module ShellOpts
14
14
  # safe for concurrent processing
15
15
  attr_reader :message
16
16
 
17
- # Return true if .value is an "instance" of self (not used atm. See
18
- # Command#[] and Grammar::Option#value?)
17
+ # Return true if .value is an "instance" of self. Ie. an Integer object
18
+ # if type is an IntegerArgument
19
19
  def value?(value) true end
20
20
 
21
21
  # Convert value to Ruby type
@@ -131,7 +131,7 @@ module ShellOpts
131
131
  class EnumArgument < ArgumentType
132
132
  attr_reader :values
133
133
  def initialize(values) @values = values.dup end
134
- def match?(name, literal) literal?(literal) or set_message "Illegal value in #{name}: '#{literal}'" end
134
+ def match?(name, literal) value?(literal) or set_message "Illegal value in #{name}: '#{literal}'" end
135
135
  def value?(value) @values.include?(value) end
136
136
  end
137
137
  end
@@ -4,30 +4,33 @@
4
4
  module ShellOpts
5
5
  # Command represents a program or a subcommand. It is derived from
6
6
  # BasicObject to have only a minimum of inherited member methods.
7
- # Additional methods defined in Command use the '__<identifier>__' naming
8
- # convention that doesn't collide with option or subcommand names but
9
- # they're rarely used in application code
10
7
  #
11
8
  # The names of the inherited methods can't be used as options or
12
9
  # command namess. They are: instance_eval, instance_exec method_missing,
13
10
  # singleton_method_added, singleton_method_removed, and
14
- # singleton_method_undefined
11
+ # singleton_method_undefined.
12
+ #
13
+ # Additional methods defined in Command use the '__<identifier>__' naming
14
+ # convention that doesn't collide with option or subcommand names but
15
+ # they're rarely used in application code
15
16
  #
16
17
  # Command also defines #subcommand and #subcommand! but they can be
17
18
  # overshadowed by an option or command declaration. Their values can
18
19
  # still be accessed using the dashed name, though
19
20
  #
20
- # Options and subcommands can be accessed using #[]
21
+ # Option and Command objects can be accessed using #[]. #key? is also defined
21
22
  #
22
23
  # The following methods are created dynamically for each declared option
23
24
  # with an attribute name
24
25
  #
25
- # def <identifier>(default = nil) self["<identifier>"] || default end
26
- # def <identifier>=(value) self["<identifier>"] = value end
27
- # def <identifier>?() self.key?("<identifier>") end
26
+ # <identifier>(default = nil)
27
+ # <identifier>=(value)
28
+ # <identifier>?()
29
+ #
30
+ # The default value is used if the option or its value is missing
28
31
  #
29
32
  # Options without an an attribute can still be accessed using #[] or trough
30
- # #__options__ or #__options_list__):
33
+ # #__option_values__, #__option_hash, or #__options_list__
31
34
  #
32
35
  # Each subcommand has a single method:
33
36
  #
@@ -42,9 +45,9 @@ module ShellOpts
42
45
 
43
46
  # These names can't be used as option or command names
44
47
  RESERVED_OPTION_NAMES = %w(
45
- is_a
46
- instance_eval instance_exec method_missing singleton_method_added
47
- singleton_method_removed singleton_method_undefined)
48
+ is_a instance_eval instance_exec method_missing singleton_method_added
49
+ singleton_method_removed singleton_method_undefined
50
+ )
48
51
 
49
52
  # These methods can be overridden by an option (the value is not used -
50
53
  # this is just for informational purposes)
@@ -59,43 +62,25 @@ module ShellOpts
59
62
  object
60
63
  end
61
64
 
62
- # Return command object or option argument value if present, otherwise nil
65
+ # Return command or option object if present, otherwise nil. Returns a
66
+ # possibly empty array of option objects if the option is repeatable
63
67
  #
64
68
  # The key is the name or identifier of the object or any any option
65
69
  # alias. Eg. :f, '-f', :file, or '--file' are all usable as option keys
66
70
  # and :cmd! or 'cmd' as command keys
67
71
  #
68
- # For options, the returned value is the argument given by the user
69
- # optionally converted to Integer or Float or nil if the option doesn't
70
- # take arguments. If the option takes an argument and it is repeatable
71
- # the value is an array of the arguments. Repeatable options without
72
- # arguments have the number of occurences as the value
73
- #
74
72
  def [](key)
75
73
  case object = __grammar__[key]
76
74
  when ::ShellOpts::Grammar::Command
77
75
  object.ident == __subcommand__!.__ident__ ? __subcommand__! : nil
78
76
  when ::ShellOpts::Grammar::Option
79
- __options__[object.ident]
80
- else
81
- nil
82
- end
83
- end
84
-
85
- # Assign a value to an existing option. This can be used to implement
86
- # default values. #[]= doesn't currently check the type of the given
87
- # value so take care. Note that the corresponding option(s) in
88
- # #__option_list__ is not updated
89
- def []=(key, value)
90
- case object = __grammar__[key]
91
- when ::ShellOpts::Grammar::Command
92
- ::Kernel.raise ArgumentError, "#{key.inspect} is not an option"
93
- when ::ShellOpts::Grammar::Option
94
- object.argument? || object.repeatable? or
95
- ::Kernel.raise ArgumentError, "#{key.inspect} is not assignable"
96
- __options__[object.ident] = value
77
+ if object.repeatable?
78
+ __option_hash__[object.ident] || []
79
+ else
80
+ __option_hash__[object.ident]
81
+ end
97
82
  else
98
- ::Kernel.raise ArgumentError, "Unknown option or command: #{key.inspect}"
83
+ ::Kernel.raise ::ArgumentError, "Unknown command or option: '#{key}'"
99
84
  end
100
85
  end
101
86
 
@@ -103,11 +88,11 @@ module ShellOpts
103
88
  def key?(key)
104
89
  case object = __grammar__[key]
105
90
  when ::ShellOpts::Grammar::Command
106
- object.ident == __subcommand__!.ident ? __subcommand__! : nil
91
+ object.ident == __subcommand__
107
92
  when ::ShellOpts::Grammar::Option
108
- __options__.key?(object.ident)
93
+ __option_hash__.key?(object.ident)
109
94
  else
110
- nil
95
+ ::Kernel.raise ::ArgumentError, "Unknown command or option: '#{key}'"
111
96
  end
112
97
  end
113
98
 
@@ -153,13 +138,17 @@ module ShellOpts
153
138
  # depending on the option's type. Repeated options options without
154
139
  # arguments have the number of occurences as the value, with arguments
155
140
  # the value is an array of the given values
156
- attr_reader :__options__
141
+ attr_reader :__option_values__
157
142
 
158
143
  # List of Option objects for the subcommand in the same order as
159
144
  # given by the user but note that options are reordered to come after
160
145
  # their associated subcommand if float is true. Repeated options are not
161
146
  # collapsed
162
147
  attr_reader :__option_list__
148
+
149
+ # Map from identifier to option object or to a list of option objects if
150
+ # the option is repeatable
151
+ attr_reader :__option_hash__
163
152
 
164
153
  # The subcommand identifier (a Symbol incl. the exclamation mark) or nil
165
154
  # if not present. Use #subcommand!, or the dynamically generated
@@ -172,9 +161,10 @@ module ShellOpts
172
161
  private
173
162
  def __initialize__(grammar)
174
163
  @__grammar__ = grammar
175
- @__options__ = {}
164
+ @__option_values__ = {}
176
165
  @__option_list__ = []
177
- @__options__ = {}
166
+ @__option_hash__ = {}
167
+ @__option_values__ = {}
178
168
  @__subcommand__ = nil
179
169
 
180
170
  __define_option_methods__
@@ -182,36 +172,34 @@ module ShellOpts
182
172
 
183
173
  def __define_option_methods__
184
174
  @__grammar__.options.each { |opt|
185
- next if opt.attr.nil?
186
175
  if opt.argument? || opt.repeatable?
187
176
  if opt.optional?
188
177
  self.instance_eval %(
189
178
  def #{opt.attr}(default = nil)
190
- if @__options__.key?(:#{opt.attr})
191
- @__options__[:#{opt.attr}] || default
179
+ if @__option_values__.key?(:#{opt.attr})
180
+ @__option_values__[:#{opt.attr}]
192
181
  else
193
- nil
182
+ default
194
183
  end
195
184
  end
196
185
  )
197
- elsif !opt.argument?
186
+ elsif !opt.argument? # Repeatable w/o argument
198
187
  self.instance_eval %(
199
- def #{opt.attr}(default = nil)
200
- if @__options__.key?(:#{opt.attr})
201
- value = @__options__[:#{opt.attr}]
202
- value == 0 ? default : value
188
+ def #{opt.attr}(default = [])
189
+ if @__option_values__.key?(:#{opt.attr})
190
+ @__option_values__[:#{opt.attr}]
203
191
  else
204
- nil
192
+ default
205
193
  end
206
194
  end
207
195
  )
208
196
  else
209
- self.instance_eval("def #{opt.attr}() @__options__[:#{opt.attr}] end")
197
+ self.instance_eval("def #{opt.attr}() @__option_values__[:#{opt.attr}] end")
210
198
  end
211
- self.instance_eval("def #{opt.attr}=(value) @__options__[:#{opt.attr}] = value end")
212
- @__options__[opt.attr] = 0 if !opt.argument?
199
+ self.instance_eval("def #{opt.attr}=(value) @__option_values__[:#{opt.attr}] = value end")
200
+ @__option_values__[opt.attr] = 0 if !opt.argument?
213
201
  end
214
- self.instance_eval("def #{opt.attr}?() @__options__.key?(:#{opt.attr}) end")
202
+ self.instance_eval("def #{opt.attr}?() @__option_values__.key?(:#{opt.attr}) end")
215
203
  }
216
204
 
217
205
  @__grammar__.commands.each { |cmd|
@@ -228,14 +216,15 @@ module ShellOpts
228
216
  ident = option.grammar.ident
229
217
  @__option_list__ << option
230
218
  if option.repeatable?
219
+ (@__option_hash__[ident] ||= []) << option
231
220
  if option.argument?
232
- (@__options__[ident] ||= []) << option.argument
221
+ (@__option_values__[ident] ||= []) << option.argument
233
222
  else
234
- @__options__[ident] ||= 0
235
- @__options__[ident] += 1
223
+ @__option_values__[ident] = (@__option_values__[ident] || 0) + 1
236
224
  end
237
225
  else
238
- @__options__[ident] = option.argument
226
+ @__option_hash__[ident] = option
227
+ @__option_values__[ident] = option.argument
239
228
  end
240
229
  end
241
230
 
@@ -254,7 +243,7 @@ module ShellOpts
254
243
 
255
244
  # Option models an option as given by the user on the subcommand line.
256
245
  # Compiled options (and possibly aggregated) options are stored in the
257
- # Command#__options__ array
246
+ # Command#__option_values__ array
258
247
  class Option
259
248
  # Associated Grammar::Option object
260
249
  attr_reader :grammar
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.4"
3
3
  end
data/lib/shellopts.rb CHANGED
@@ -201,9 +201,9 @@ module ShellOpts
201
201
  def brief() Formatter.brief(@grammar) end
202
202
 
203
203
  # Print help for the given subject or the full documentation if +subject+
204
- # is nil
204
+ # is nil. Clears the screen beforehand if :clear is true
205
205
  #
206
- def help(subject = nil)
206
+ def help(subject = nil, clear: false)
207
207
  node = (subject ? @grammar[subject] : @grammar) or
208
208
  raise ArgumentError, "No such command: '#{subject&.sub(".", " ")}'"
209
209
  Formatter.help(node)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shellopts
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-28 00:00:00.000000000 Z
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forward_to
@@ -187,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
187
  - !ruby/object:Gem::Version
188
188
  version: '0'
189
189
  requirements: []
190
- rubygems_version: 3.2.26
190
+ rubygems_version: 3.1.4
191
191
  signing_key:
192
192
  specification_version: 4
193
193
  summary: Parse command line options and arguments