shellopts 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/shellopts/program.rb +52 -63
- data/lib/shellopts/version.rb +1 -1
- data/lib/shellopts.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0170d9ce5144afcf716b90a3904250c0afa5d769b7a64f39db0b8084e77b4fb7
|
4
|
+
data.tar.gz: 81495a3802c472c65812594d847c43b0f59849ea0ebe093c74c2fb7d3e822658
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 195801ea89b22920fca88216ed4bd7ac426b3370e482b61547dac085d1c7d9f1bd0a2d0edc7c3368bf126cd5f4da815dd882ee3149cd291549ff631d6302e93a
|
7
|
+
data.tar.gz: 6dcd50871438db9f5b0520e4f670f6df6ad04756685838d309874a9601770ee79a7370ebc11b0469d19a9f2be89868c7cfd12cfe028c0c01719b4d8d0593fc59
|
data/lib/shellopts/program.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
#
|
26
|
-
#
|
27
|
-
#
|
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
|
-
# #
|
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
|
-
|
47
|
-
|
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
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
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__
|
91
|
+
object.ident == __subcommand__
|
107
92
|
when ::ShellOpts::Grammar::Option
|
108
|
-
|
93
|
+
__option_hash__.key?(object.ident)
|
109
94
|
else
|
110
|
-
|
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 :
|
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
|
-
@
|
164
|
+
@__option_values__ = {}
|
176
165
|
@__option_list__ = []
|
177
|
-
@
|
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 @
|
191
|
-
@
|
179
|
+
if @__option_values__.key?(:#{opt.attr})
|
180
|
+
@__option_values__[:#{opt.attr}]
|
192
181
|
else
|
193
|
-
|
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 =
|
200
|
-
if @
|
201
|
-
|
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
|
-
|
192
|
+
default
|
205
193
|
end
|
206
194
|
end
|
207
195
|
)
|
208
196
|
else
|
209
|
-
self.instance_eval("def #{opt.attr}() @
|
197
|
+
self.instance_eval("def #{opt.attr}() @__option_values__[:#{opt.attr}] end")
|
210
198
|
end
|
211
|
-
self.instance_eval("def #{opt.attr}=(value) @
|
212
|
-
@
|
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}?() @
|
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
|
-
(@
|
221
|
+
(@__option_values__[ident] ||= []) << option.argument
|
233
222
|
else
|
234
|
-
@
|
235
|
-
@__options__[ident] += 1
|
223
|
+
@__option_values__[ident] = (@__option_values__[ident] || 0) + 1
|
236
224
|
end
|
237
225
|
else
|
238
|
-
@
|
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#
|
246
|
+
# Command#__option_values__ array
|
258
247
|
class Option
|
259
248
|
# Associated Grammar::Option object
|
260
249
|
attr_reader :grammar
|
data/lib/shellopts/version.rb
CHANGED
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.
|
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-
|
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.
|
190
|
+
rubygems_version: 3.1.4
|
191
191
|
signing_key:
|
192
192
|
specification_version: 4
|
193
193
|
summary: Parse command line options and arguments
|