ark-cli 0.4.4 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +180 -0
- data/lib/ark/cli.rb +9 -487
- data/lib/ark/cli/interface.rb +173 -0
- data/lib/ark/cli/option.rb +118 -0
- data/lib/ark/cli/report.rb +32 -0
- data/lib/ark/cli/spec.rb +183 -0
- metadata +15 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40d1e78d63af56864533187b51ab27bdf514cdcd
|
4
|
+
data.tar.gz: 7cc02dba83f021e537314dfccc03bc77592e39c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b80df1a67863e975e5d46633e9128a6fd6392a2bd1233e0b905e09d5b1158c347185ec12987561a6cc16229a8fa947dbacf1b7e3fd7a501e191e248280d7329b
|
7
|
+
data.tar.gz: c710c95aed57880c6a3f5cf01331f859ab766ef10850950466567725b1a14c36718ba0226ed08b30479fb86f78367df3b59ce75be726d265190e16906d92eccf
|
data/README.md
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
# ark-cli
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/ark-cli)
|
4
|
+
|
5
|
+
__ark-cli__ is a Ruby library for handling command line options and
|
6
|
+
arguments. See below for basic usage. Full documentation can be found at
|
7
|
+
http://www.rubydoc.info/github/grimheart/ark-cli
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
## Declaring an interface
|
12
|
+
|
13
|
+
The usual way to use ark-cli is to call `Ark::CLI.report`. This convenience
|
14
|
+
method builds a new interface and returns a `Report` object for inspection.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
require 'ark/cli'
|
18
|
+
|
19
|
+
# Declare an interface and parse the command line
|
20
|
+
# Returns a Report instance for inspection as `r`
|
21
|
+
r = Ark::CLI.report do |s|
|
22
|
+
s.name 'example'
|
23
|
+
s.args 'host', 'path'
|
24
|
+
s.desc "An example demonstrating usage of ark-cli"
|
25
|
+
|
26
|
+
s.opt :verbose, :v,
|
27
|
+
desc: "Increase verbosity"
|
28
|
+
|
29
|
+
s.opt :port, :p,
|
30
|
+
args: 'number',
|
31
|
+
desc: "Specify an alternate port number"
|
32
|
+
end
|
33
|
+
|
34
|
+
r.args # Get all arguments received, including trailing args
|
35
|
+
r.arg[:host] # Get the value of the `host` argument
|
36
|
+
r.opt[:port] # Get the value of the `port` option
|
37
|
+
r.count[:v] # Get the number of times an option was toggled
|
38
|
+
```
|
39
|
+
|
40
|
+
The `CLI.report` method yields a `Spec` instance, which we'll call `s`. Calls to
|
41
|
+
this instance will define how the command line is parsed. The online usage
|
42
|
+
information will also be generated from this spec.
|
43
|
+
|
44
|
+
`s` has four important methods:
|
45
|
+
|
46
|
+
### Name and description
|
47
|
+
|
48
|
+
The `name` method sets the name of the program to use in usage information. It
|
49
|
+
expects a string. This should probably be the same as the name of the
|
50
|
+
executable.
|
51
|
+
|
52
|
+
The `desc` method sets a description of the program for generating usage
|
53
|
+
information. It expects a string.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
s.name 'example'
|
57
|
+
s.desc "An example demonstrating usage of ark-cli"
|
58
|
+
```
|
59
|
+
|
60
|
+
### Declaring arguments
|
61
|
+
|
62
|
+
The `args` method defines what arguments the program will expect.
|
63
|
+
|
64
|
+
Declaring two named, expected arguments:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
s.args 'host', 'port'
|
68
|
+
```
|
69
|
+
|
70
|
+
Declare defaults with a colon after the argument name, like `'host:localhost'`.
|
71
|
+
Arguments with default values are optional - no error will be raised if they
|
72
|
+
aren't given.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
s.args 'file:~/.dcf'
|
76
|
+
s.args 'host', 'port:22', "user:#{ENV['USER']}"
|
77
|
+
```
|
78
|
+
|
79
|
+
Declaring a variadic interface with a glob, `'dest...'`
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
s.args 'target', 'dest...'
|
83
|
+
```
|
84
|
+
|
85
|
+
### Declaring options
|
86
|
+
|
87
|
+
The `opt` method defines options.
|
88
|
+
|
89
|
+
Flags are simple options without arguments:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
s.opt :verbose, :v,
|
93
|
+
desc: "Increase verbosity"
|
94
|
+
```
|
95
|
+
|
96
|
+
Flags are false by default and set true when given on the command line. A count
|
97
|
+
is kept of the number of times the flag was specified, and stored in the report
|
98
|
+
as `r.count`. The `desc` field is used to generate usage information.
|
99
|
+
|
100
|
+
Options can also take arguments:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
s.opt :port, :p,
|
104
|
+
args: 'number',
|
105
|
+
desc: "Specify an alternate port number"
|
106
|
+
```
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
## Inspecting the `Report` object
|
111
|
+
|
112
|
+
The `Ark::CLI#report` method returns a `Report` instance which we can inspect
|
113
|
+
for information parsed from the command line.
|
114
|
+
|
115
|
+
Supposing `r` is a returned `Report` instance, we can get all arguments with the
|
116
|
+
`r.args` method. This will include any trailing arguments.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
host, path = r.args
|
120
|
+
```
|
121
|
+
|
122
|
+
Get the value of a named argument with the `r.arg` method:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
host = r.arg[:host]
|
126
|
+
path = r.arg[:path]
|
127
|
+
```
|
128
|
+
|
129
|
+
Inspect the value of an option with `r.opt`:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
verbose = r.opt[:v]
|
133
|
+
port = r.opt[:port]
|
134
|
+
```
|
135
|
+
|
136
|
+
Get a count of the number of times a flag was specified with `r.count`:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
verbosity = r.count[:verbose]
|
140
|
+
```
|
141
|
+
|
142
|
+
Get an array of trailing arguments with `r.trailing`:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
path1, path2 = r.trailing
|
146
|
+
```
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
## Usage information
|
151
|
+
|
152
|
+
A help option is defined for all interfaces with the `-h` and `--help` flags.
|
153
|
+
When the help option is given, the program will print usage information and exit
|
154
|
+
immediately. Usage information is constructed from the `Spec` built during the
|
155
|
+
CLI declaration.
|
156
|
+
|
157
|
+
Usage information for the above declaration would look like this:
|
158
|
+
|
159
|
+
example [OPTION...] HOST PATH
|
160
|
+
|
161
|
+
An example demonstrating usage of ark-cli
|
162
|
+
|
163
|
+
OPTIONS:
|
164
|
+
|
165
|
+
-h --help
|
166
|
+
Print usage information
|
167
|
+
|
168
|
+
-v --verbose
|
169
|
+
Increase verbosity
|
170
|
+
|
171
|
+
-p --port NUMBER
|
172
|
+
Specify an alternate port number
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
## Example script
|
177
|
+
|
178
|
+
A working example script with comments can be found at `example/hello.rb` --
|
179
|
+
invoke the script with the `--help` option for usage information.
|
180
|
+
|
data/lib/ark/cli.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# ark-cli - a
|
1
|
+
# ark-cli - a command line interface library for Ruby
|
2
2
|
# Copyright 2015 Macquarie Sharpless <macquarie.sharpless@gmail.com>
|
3
3
|
#
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
@@ -18,6 +18,11 @@
|
|
18
18
|
require 'ark/utility'
|
19
19
|
include Ark::Log
|
20
20
|
|
21
|
+
require_relative 'cli/interface.rb'
|
22
|
+
require_relative 'cli/option.rb'
|
23
|
+
require_relative 'cli/spec.rb'
|
24
|
+
require_relative 'cli/report.rb'
|
25
|
+
|
21
26
|
|
22
27
|
module Ark # :nodoc:
|
23
28
|
|
@@ -25,499 +30,16 @@ module Ark # :nodoc:
|
|
25
30
|
#
|
26
31
|
# Call #begin to define a new interface and parse the command line. See
|
27
32
|
# +README.md+ or +example/hello.rb+ for more information.
|
28
|
-
|
29
|
-
# Represents an option and stores the option's current state, as well as
|
30
|
-
# usage information.
|
31
|
-
class Option
|
32
|
-
# Initialize a new Option instance
|
33
|
-
# [+keys+] A list of names this option will be identified by
|
34
|
-
# [+args+] A list of argument named this option will expect
|
35
|
-
# [+desc+] A short description of this option
|
36
|
-
def initialize(long, short=nil, args=nil, desc=nil)
|
37
|
-
@long = long
|
38
|
-
@short = short
|
39
|
-
@args = args || []
|
40
|
-
@vals = []
|
41
|
-
@flag = false
|
42
|
-
@count = 0
|
43
|
-
@desc = desc || ''
|
44
|
-
end
|
45
|
-
# A count of how many times this option has been given on the command line.
|
46
|
-
# Useful for flags that might be specified repeatedly, like +-vvv+ to raise
|
47
|
-
# verbosity three times.
|
48
|
-
attr_reader :count
|
49
|
-
# A short description of the option, if given
|
50
|
-
attr_reader :desc
|
51
|
-
# Long name for this option
|
52
|
-
attr_reader :long
|
53
|
-
# Short name for this option
|
54
|
-
attr_reader :short
|
55
|
-
|
56
|
-
# Return the number of arguments this option expects
|
57
|
-
def arity()
|
58
|
-
return @args.length
|
59
|
-
end
|
60
|
-
|
61
|
-
# Return a count of how many arguments this option still expects
|
62
|
-
def vals_needed()
|
63
|
-
if self.flag?
|
64
|
-
return 0
|
65
|
-
else
|
66
|
-
return @args.length - @vals.length
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# True if this option has received all the arguments it expects, or if this
|
71
|
-
# option expects no arguments
|
72
|
-
def full?
|
73
|
-
return self.vals_needed == 0
|
74
|
-
end
|
75
|
-
|
76
|
-
# True if this option expects no arguments; opposite of #has_args?
|
77
|
-
def flag?
|
78
|
-
return @args.empty?
|
79
|
-
end
|
80
|
-
|
81
|
-
# Toggle this option to the true state and increment the toggle count. Only
|
82
|
-
# valid for options which expect no argument (flags). Attempting to toggle
|
83
|
-
# a option with expected arguments will raise an error.
|
84
|
-
def toggle()
|
85
|
-
if self.flag?
|
86
|
-
@count += 1
|
87
|
-
@flag = true
|
88
|
-
else
|
89
|
-
raise StandardError, "Tried to toggle an option which expects an argument"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Pass an argument +arg+ to this option
|
94
|
-
def push(arg)
|
95
|
-
@vals << arg
|
96
|
-
end
|
97
|
-
|
98
|
-
# Return the current value of this option
|
99
|
-
def value()
|
100
|
-
if self.flag?
|
101
|
-
return @flag
|
102
|
-
else
|
103
|
-
if self.full? && @vals.length == 1
|
104
|
-
return @vals[0]
|
105
|
-
elsif self.full?
|
106
|
-
return @vals
|
107
|
-
else
|
108
|
-
return nil
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# True if this option expects an argument. Opposite of #flag?
|
114
|
-
def has_args?
|
115
|
-
return @args.length > 0
|
116
|
-
end
|
117
|
-
|
118
|
-
# Return basic usage information: the option's names and arguments
|
119
|
-
def header()
|
120
|
-
if self.flag?
|
121
|
-
args = ''
|
122
|
-
else
|
123
|
-
args = ' ' + @args.join(', ').upcase
|
124
|
-
end
|
125
|
-
short = @short ? "-#{@short} " : ''
|
126
|
-
return "#{short}--#{@long}#{args}"
|
127
|
-
end
|
128
|
-
|
129
|
-
# Represent this option as a string
|
130
|
-
def to_s()
|
131
|
-
return "(#{self.header})"
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
class CLI
|
137
|
-
|
138
|
-
# Raised when the command line is malformed
|
139
|
-
class SyntaxError < ArgumentError
|
140
|
-
end
|
141
|
-
|
33
|
+
module CLI
|
142
34
|
# Convenience method for interface declarations. Yields the CLI instance and
|
143
35
|
# then returns it after parsing. Equivalent to instantiating a CLI instance
|
144
36
|
# with #new, modifying it, and then calling #parse
|
145
37
|
#
|
146
38
|
# +args+ is an array of strings, which defaults to ARGV
|
147
39
|
def self.report(args=ARGV, &block)
|
148
|
-
|
149
|
-
return
|
150
|
-
end
|
151
|
-
|
152
|
-
# Initialize a CLI instance.
|
153
|
-
#
|
154
|
-
# +args+ must be an array of strings, like ARGV
|
155
|
-
def initialize(args, &block)
|
156
|
-
self.rebuild(args, &block)
|
157
|
-
end
|
158
|
-
|
159
|
-
attr_reader :report
|
160
|
-
|
161
|
-
def rebuild(input=ARGV, &block)
|
162
|
-
@input = input
|
163
|
-
@spec = Spec.new
|
164
|
-
yield @spec
|
165
|
-
@spec.opt :help, :h, desc: "Print usage information"
|
166
|
-
self.parse
|
167
|
-
end
|
168
|
-
|
169
|
-
# Parse the command line
|
170
|
-
def parse()
|
171
|
-
taking_options = true
|
172
|
-
last_opt = nil
|
173
|
-
refargs = @spec.get_args.clone
|
174
|
-
|
175
|
-
@report = Report.new()
|
176
|
-
|
177
|
-
@input.each do |word|
|
178
|
-
dbg "Parsing '#{word}'"
|
179
|
-
if last_opt && last_opt.has_args? && !last_opt.full?
|
180
|
-
dbg "Got argument '#{word}' for '#{last_opt}'", 1
|
181
|
-
last_opt.push(word)
|
182
|
-
else
|
183
|
-
if word[/^-/] && taking_options
|
184
|
-
if word[/^-[^-]/]
|
185
|
-
dbg "Identified short option(s)", 1
|
186
|
-
shorts = word[/[^-]+$/].split('')
|
187
|
-
shorts.each_with_index do |short, i|
|
188
|
-
last_short = i == (shorts.length - 1)
|
189
|
-
opt = @spec.get_opt(short)
|
190
|
-
last_opt = opt
|
191
|
-
if opt.has_args? && shorts.length > 1 && !last_short
|
192
|
-
raise SyntaxError, "Error: -#{short} in compound option '#{word}' expects an argument"
|
193
|
-
elsif opt.flag?
|
194
|
-
opt.toggle()
|
195
|
-
dbg "Toggled flag '#{opt}'", 1
|
196
|
-
end
|
197
|
-
end
|
198
|
-
elsif word[/^--/]
|
199
|
-
dbg "Identified long option", 1
|
200
|
-
key = word[/[^-]+$/]
|
201
|
-
opt = @spec.get_opt(key)
|
202
|
-
last_opt = opt
|
203
|
-
if opt.flag?
|
204
|
-
opt.toggle()
|
205
|
-
dbg "Toggled #{opt}", 1
|
206
|
-
end
|
207
|
-
end
|
208
|
-
else
|
209
|
-
dbg "Parsed output arg", 1
|
210
|
-
taking_options = false
|
211
|
-
@report.args << word
|
212
|
-
key = refargs.shift
|
213
|
-
if key
|
214
|
-
if key == @spec.get_variad
|
215
|
-
@report.arg[key] = []
|
216
|
-
@report.arg[key] << word
|
217
|
-
else
|
218
|
-
@report.arg[key] = word
|
219
|
-
end
|
220
|
-
elsif @spec.is_variadic?
|
221
|
-
@report.arg[@spec.get_variad] << word
|
222
|
-
else
|
223
|
-
@report.trailing << word
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
@spec.get_opts.each do |name, opt|
|
229
|
-
@report.opt[name] = opt.value
|
230
|
-
@report.count[name] = opt.count
|
231
|
-
end
|
232
|
-
@spec.get_args.each do |name|
|
233
|
-
if @report.arg[name].nil?
|
234
|
-
if @spec.has_default?(name)
|
235
|
-
@report.arg[name] = @spec.get_default(name)
|
236
|
-
@report.args << @report.arg[name]
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
if @report.opt[:help]
|
241
|
-
self.print_usage()
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
# Construct usage information
|
246
|
-
def usage()
|
247
|
-
tb = TextBuilder.new()
|
248
|
-
|
249
|
-
tb.next 'USAGE:'
|
250
|
-
tb.push @spec.get_name if @spec.get_name
|
251
|
-
|
252
|
-
tb.push '[OPTION'
|
253
|
-
tb.add '...' if @spec.has_options?
|
254
|
-
tb.add ']'
|
255
|
-
|
256
|
-
if @spec.has_args?
|
257
|
-
if @spec.is_variadic?
|
258
|
-
singles = @spec.get_args[0..-2].map do |a|
|
259
|
-
if @spec.has_default?(a)
|
260
|
-
a = "[#{a}]"
|
261
|
-
end
|
262
|
-
a.upcase
|
263
|
-
end
|
264
|
-
tb.push singles
|
265
|
-
v = @spec.get_args.last.upcase
|
266
|
-
tb.push "[#{v}1 #{v}2...]"
|
267
|
-
else
|
268
|
-
argmap = @spec.get_args.map do |a|
|
269
|
-
if @spec.has_default?(a)
|
270
|
-
a = "[#{a}]"
|
271
|
-
end
|
272
|
-
a.upcase
|
273
|
-
end
|
274
|
-
tb.push argmap
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
if @spec.get_desc
|
279
|
-
tb.skip @spec.get_desc
|
280
|
-
tb.wrap(indent: 4)
|
281
|
-
end
|
282
|
-
|
283
|
-
tb.skip 'OPTIONS:'
|
284
|
-
tb.skip
|
285
|
-
|
286
|
-
@spec.get_opts.values.uniq.each do |opt|
|
287
|
-
tb.indent 4
|
288
|
-
tb.push opt.header
|
289
|
-
if opt.desc
|
290
|
-
tb.next
|
291
|
-
tb.indent 8
|
292
|
-
tb.push opt.desc
|
293
|
-
end
|
294
|
-
tb.skip
|
295
|
-
end
|
296
|
-
|
297
|
-
return tb.print
|
298
|
-
end
|
299
|
-
|
300
|
-
# Print usage information and exit
|
301
|
-
def print_usage()
|
302
|
-
puts self.usage
|
303
|
-
exit 0
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
class Spec
|
308
|
-
|
309
|
-
# Raised when a nonexistent option is received
|
310
|
-
class NoSuchOptionError < ArgumentError
|
311
|
-
end
|
312
|
-
|
313
|
-
# Raised when there is a syntax error in the args declaration
|
314
|
-
class ArgumentSyntaxError < ArgumentError
|
315
|
-
end
|
316
|
-
|
317
|
-
# Initialize a bare interface spec
|
318
|
-
def initialize()
|
319
|
-
@args = []
|
320
|
-
@options = {}
|
321
|
-
@variadic = false
|
322
|
-
@option_listing = false
|
323
|
-
@trailing_error = false
|
324
|
-
end
|
325
|
-
# If true, the full option list will always be displayed in the usage info
|
326
|
-
# header
|
327
|
-
attr_reader :option_listing
|
328
|
-
# If true, an error will be raised if trailing arguments are given
|
329
|
-
attr_reader :trailing_error
|
330
|
-
|
331
|
-
private
|
332
|
-
|
333
|
-
def strip(arg)
|
334
|
-
return arg[/^(.+?)(\.\.\.$|_$|$)/, 1]
|
335
|
-
end
|
336
|
-
|
337
|
-
def optional?(arg)
|
338
|
-
return !arg[/_$/].nil?
|
339
|
-
end
|
340
|
-
|
341
|
-
def variadic?(arg)
|
342
|
-
return !arg[/\.\.\.$/].nil?
|
343
|
-
end
|
344
|
-
|
345
|
-
def parse_arg(arg, default: nil, last: false)
|
346
|
-
stripped = strip(arg)
|
347
|
-
@args << stripped
|
348
|
-
if optional?(arg)
|
349
|
-
@optional << stripped
|
350
|
-
end
|
351
|
-
unless default.nil?
|
352
|
-
@defaults[stripped] = default
|
353
|
-
end
|
354
|
-
if variadic?(arg)
|
355
|
-
if last
|
356
|
-
@variadic = true
|
357
|
-
@variad = stripped
|
358
|
-
else
|
359
|
-
raise ArgumentSyntaxError,
|
360
|
-
"Variadic arguments must come last. Offending variad is '#{arg}'"
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
public
|
366
|
-
|
367
|
-
def get_name
|
368
|
-
return @name
|
369
|
-
end
|
370
|
-
|
371
|
-
def get_desc
|
372
|
-
return @desc
|
373
|
-
end
|
374
|
-
|
375
|
-
def get_args
|
376
|
-
return @args
|
377
|
-
end
|
378
|
-
|
379
|
-
def get_opts
|
380
|
-
return @options
|
381
|
-
end
|
382
|
-
|
383
|
-
def is_variadic?
|
384
|
-
return @variadic
|
385
|
-
end
|
386
|
-
|
387
|
-
def get_variad
|
388
|
-
return @variad
|
389
|
-
end
|
390
|
-
|
391
|
-
def get_defaults
|
392
|
-
return @defaults
|
393
|
-
end
|
394
|
-
|
395
|
-
# Get an Option object for the given option +name+
|
396
|
-
def get_opt(name)
|
397
|
-
name = name.to_sym
|
398
|
-
if !@options.keys.member?(name)
|
399
|
-
raise NoSuchOptionError, "Error, no such option: '#{name}'"
|
400
|
-
end
|
401
|
-
return @options[name]
|
402
|
-
end
|
403
|
-
|
404
|
-
def is_optional?(arg)
|
405
|
-
@optional.member?(arg.to_s)
|
406
|
-
end
|
407
|
-
|
408
|
-
def has_default?(arg)
|
409
|
-
@defaults.key?(arg.to_s)
|
410
|
-
end
|
411
|
-
|
412
|
-
def get_default(arg)
|
413
|
-
@defaults[arg.to_s]
|
40
|
+
i = Interface.new(args, &block)
|
41
|
+
return i.report
|
414
42
|
end
|
415
|
-
|
416
|
-
def has_args?
|
417
|
-
@args.length > 0
|
418
|
-
end
|
419
|
-
|
420
|
-
def has_options?
|
421
|
-
@options.values.uniq.length > 1
|
422
|
-
end
|
423
|
-
|
424
|
-
# Specify general information about the program
|
425
|
-
# [+name+] Name of the program
|
426
|
-
# [+desc+] Short description of the program
|
427
|
-
# [+args+] A list of named arguments
|
428
|
-
def header(name: nil, desc: nil, args: [])
|
429
|
-
self.name(name)
|
430
|
-
self.desc(desc)
|
431
|
-
self.args(args)
|
432
|
-
end
|
433
|
-
|
434
|
-
# Set the name of the program to +str+
|
435
|
-
def name(str)
|
436
|
-
@name = str.to_s if str
|
437
|
-
end
|
438
|
-
|
439
|
-
# Set the description of the program to +str+
|
440
|
-
def desc(str)
|
441
|
-
@desc = str.to_s if str
|
442
|
-
end
|
443
|
-
|
444
|
-
# Define what arguments the program will accept
|
445
|
-
def args(*input)
|
446
|
-
@args = []
|
447
|
-
@optional = []
|
448
|
-
@defaults = {}
|
449
|
-
|
450
|
-
input.flatten.each_with_index do |item, i|
|
451
|
-
list_last = (input.length - (i + 1)) == 0
|
452
|
-
if item.is_a?(Hash)
|
453
|
-
item.each_with_index do |pair,ii|
|
454
|
-
k = pair[0].to_s
|
455
|
-
v = pair[1]
|
456
|
-
hash_last = (item.length - (ii + 1)) == 0
|
457
|
-
last = hash_last && list_last
|
458
|
-
parse_arg(k, default: v, last: last)
|
459
|
-
end
|
460
|
-
else
|
461
|
-
parse_arg(item, last: list_last)
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
@refargs = @args.clone
|
466
|
-
end
|
467
|
-
|
468
|
-
# Define an Option
|
469
|
-
# [+keys+] A list of names for this option
|
470
|
-
# [+args+] A list of arguments the option expects
|
471
|
-
# [+desc+] A short description of the option, used to provide usage info
|
472
|
-
def opt(long, short=nil, args: nil, desc: nil)
|
473
|
-
long = long.to_sym
|
474
|
-
short = short.to_sym if short
|
475
|
-
args = [args] if args.is_a?(String)
|
476
|
-
args.map!(&:to_sym) if args
|
477
|
-
o = Option.new(long, short, args, desc)
|
478
|
-
@options[long] = o
|
479
|
-
@options[short] = o if short
|
480
|
-
end
|
481
|
-
|
482
|
-
# Force the full option list display in the usage info, no matter how many
|
483
|
-
# options the program has
|
484
|
-
def force_option_list()
|
485
|
-
@option_list = true
|
486
|
-
end
|
487
|
-
|
488
|
-
# The parser will raise an error on finding trailing arguments (default
|
489
|
-
# behavior is to ignore and stuff the trailing args into Report.trailing_args)
|
490
|
-
def raise_on_trailing()
|
491
|
-
@trailing_error = true
|
492
|
-
end
|
493
|
-
|
494
|
-
end
|
495
|
-
|
496
|
-
class Report
|
497
|
-
def initialize()
|
498
|
-
@args = []
|
499
|
-
@named_args = {}
|
500
|
-
@trailing_args = []
|
501
|
-
@counts = {}
|
502
|
-
@options = {}
|
503
|
-
end
|
504
|
-
|
505
|
-
def args
|
506
|
-
return @args
|
507
|
-
end
|
508
|
-
def arg
|
509
|
-
return @named_args
|
510
|
-
end
|
511
|
-
def trailing
|
512
|
-
return @trailing_args
|
513
|
-
end
|
514
|
-
def opt
|
515
|
-
return @options
|
516
|
-
end
|
517
|
-
def count
|
518
|
-
return @counts
|
519
|
-
end
|
520
|
-
|
521
43
|
end
|
522
44
|
|
523
45
|
end # module Ark
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Ark
|
2
|
+
module CLI
|
3
|
+
|
4
|
+
class Interface
|
5
|
+
|
6
|
+
# Raised when the command line is malformed
|
7
|
+
class SyntaxError < ArgumentError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initialize an Interface instance.
|
11
|
+
#
|
12
|
+
# +args+ must be an array of strings, like ARGV
|
13
|
+
def initialize(args, &block)
|
14
|
+
self.rebuild(args, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :report
|
18
|
+
|
19
|
+
def rebuild(input=ARGV, &block)
|
20
|
+
@input = input
|
21
|
+
@spec = Spec.new
|
22
|
+
yield @spec
|
23
|
+
@spec.opt :help, :h, desc: "Print usage information"
|
24
|
+
self.parse
|
25
|
+
end
|
26
|
+
|
27
|
+
# Parse the command line
|
28
|
+
def parse()
|
29
|
+
taking_options = true
|
30
|
+
last_opt = nil
|
31
|
+
refargs = @spec.get_args.clone
|
32
|
+
|
33
|
+
@report = Report.new()
|
34
|
+
|
35
|
+
@input.each do |word|
|
36
|
+
dbg "Parsing '#{word}'"
|
37
|
+
if last_opt && last_opt.has_args? && !last_opt.full?
|
38
|
+
dbg "Got argument '#{word}' for '#{last_opt}'", 1
|
39
|
+
last_opt.push(word)
|
40
|
+
else
|
41
|
+
if word[/^-/] && taking_options
|
42
|
+
if word[/^-[^-]/]
|
43
|
+
dbg "Identified short option(s)", 1
|
44
|
+
shorts = word[/[^-]+$/].split('')
|
45
|
+
shorts.each_with_index do |short, i|
|
46
|
+
last_short = i == (shorts.length - 1)
|
47
|
+
opt = @spec.get_opt(short)
|
48
|
+
last_opt = opt
|
49
|
+
if opt.has_args? && shorts.length > 1 && !last_short
|
50
|
+
raise SyntaxError, "Error: -#{short} in compound option '#{word}' expects an argument"
|
51
|
+
elsif opt.flag?
|
52
|
+
opt.toggle()
|
53
|
+
dbg "Toggled flag '#{opt}'", 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
elsif word[/^--/]
|
57
|
+
dbg "Identified long option", 1
|
58
|
+
key = word[/[^-]+$/]
|
59
|
+
opt = @spec.get_opt(key)
|
60
|
+
last_opt = opt
|
61
|
+
if opt.flag?
|
62
|
+
opt.toggle()
|
63
|
+
dbg "Toggled #{opt}", 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
else
|
67
|
+
dbg "Parsed output arg", 1
|
68
|
+
taking_options = false
|
69
|
+
@report.args << word
|
70
|
+
key = refargs.shift
|
71
|
+
if key
|
72
|
+
if key == @spec.get_variad
|
73
|
+
@report.arg[key] = []
|
74
|
+
@report.arg[key] << word
|
75
|
+
else
|
76
|
+
@report.arg[key] = word
|
77
|
+
end
|
78
|
+
elsif @spec.is_variadic?
|
79
|
+
@report.arg[@spec.get_variad] << word
|
80
|
+
else
|
81
|
+
@report.trailing << word
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
@spec.get_opts.each do |name, opt|
|
87
|
+
@report.opt[name] = opt.value
|
88
|
+
@report.count[name] = opt.count
|
89
|
+
end
|
90
|
+
@spec.get_args.each do |name|
|
91
|
+
if @report.arg[name].nil?
|
92
|
+
if @spec.has_default?(name)
|
93
|
+
@report.arg[name] = @spec.get_default(name)
|
94
|
+
@report.args << @report.arg[name]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
if @report.opt[:help]
|
99
|
+
self.print_usage()
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Construct usage information
|
104
|
+
def usage()
|
105
|
+
tb = TextBuilder.new()
|
106
|
+
|
107
|
+
tb.next 'USAGE:'
|
108
|
+
tb.push @spec.get_name if @spec.get_name
|
109
|
+
|
110
|
+
if @spec.get_opts.values.uniq.length < 5 || @spec.option_listing
|
111
|
+
@spec.get_opts.values.uniq.each do |opt|
|
112
|
+
tb.push "[#{opt.header}]"
|
113
|
+
end
|
114
|
+
else
|
115
|
+
tb.push '[OPTION...]'
|
116
|
+
end
|
117
|
+
|
118
|
+
if @spec.has_args?
|
119
|
+
if @spec.is_variadic?
|
120
|
+
singles = @spec.get_args[0..-2].map do |a|
|
121
|
+
if @spec.has_default?(a)
|
122
|
+
a = "[#{a}]"
|
123
|
+
end
|
124
|
+
a.upcase
|
125
|
+
end
|
126
|
+
tb.push singles
|
127
|
+
v = @spec.get_args.last.upcase
|
128
|
+
tb.push "[#{v}1 #{v}2...]"
|
129
|
+
else
|
130
|
+
argmap = @spec.get_args.map do |a|
|
131
|
+
if @spec.has_default?(a)
|
132
|
+
a = "[#{a}]"
|
133
|
+
end
|
134
|
+
a.upcase
|
135
|
+
end
|
136
|
+
tb.push argmap
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
tb.wrap indent: 7, indent_after: true, segments: true
|
141
|
+
|
142
|
+
if @spec.get_desc
|
143
|
+
tb.skip @spec.get_desc
|
144
|
+
tb.wrap(indent: 4)
|
145
|
+
end
|
146
|
+
|
147
|
+
tb.skip 'OPTIONS:'
|
148
|
+
tb.skip
|
149
|
+
|
150
|
+
@spec.get_opts.values.uniq.each do |opt|
|
151
|
+
tb.indent 4
|
152
|
+
tb.push opt.header
|
153
|
+
if opt.desc
|
154
|
+
tb.next
|
155
|
+
tb.indent 8
|
156
|
+
tb.push opt.desc
|
157
|
+
end
|
158
|
+
tb.skip
|
159
|
+
end
|
160
|
+
|
161
|
+
return tb.print
|
162
|
+
end
|
163
|
+
|
164
|
+
# Print usage information and exit
|
165
|
+
def print_usage()
|
166
|
+
puts self.usage
|
167
|
+
exit 0
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end # module CLI
|
172
|
+
end # module Ark
|
173
|
+
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Ark
|
2
|
+
module CLI
|
3
|
+
|
4
|
+
# Represents an option and stores the option's current state, as well as
|
5
|
+
# usage information.
|
6
|
+
class Option
|
7
|
+
|
8
|
+
# Initialize a new Option instance
|
9
|
+
# [+keys+] A list of names this option will be identified by
|
10
|
+
# [+args+] A list of argument named this option will expect
|
11
|
+
# [+desc+] A short description of this option
|
12
|
+
def initialize(long, short=nil, args=nil, desc=nil)
|
13
|
+
@long = long
|
14
|
+
@short = short
|
15
|
+
@args = args || []
|
16
|
+
@vals = []
|
17
|
+
@flag = false
|
18
|
+
@count = 0
|
19
|
+
@desc = desc || ''
|
20
|
+
end
|
21
|
+
|
22
|
+
# A count of how many times this option has been given on the command line.
|
23
|
+
# Useful for flags that might be specified repeatedly, like +-vvv+ to raise
|
24
|
+
# verbosity three times.
|
25
|
+
attr_reader :count
|
26
|
+
|
27
|
+
# A short description of the option, if given
|
28
|
+
attr_reader :desc
|
29
|
+
|
30
|
+
# Long name for this option
|
31
|
+
attr_reader :long
|
32
|
+
|
33
|
+
# Short name for this option
|
34
|
+
attr_reader :short
|
35
|
+
|
36
|
+
# Return the number of arguments this option expects
|
37
|
+
def arity()
|
38
|
+
return @args.length
|
39
|
+
end
|
40
|
+
|
41
|
+
# Return a count of how many arguments this option still expects
|
42
|
+
def vals_needed()
|
43
|
+
if self.flag?
|
44
|
+
return 0
|
45
|
+
else
|
46
|
+
return @args.length - @vals.length
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# True if this option has received all the arguments it expects, or if this
|
51
|
+
# option expects no arguments
|
52
|
+
def full?
|
53
|
+
return self.vals_needed == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
# True if this option expects no arguments; opposite of #has_args?
|
57
|
+
def flag?
|
58
|
+
return @args.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Toggle this option to the true state and increment the toggle count. Only
|
62
|
+
# valid for options which expect no argument (flags). Attempting to toggle
|
63
|
+
# a option with expected arguments will raise an error.
|
64
|
+
def toggle()
|
65
|
+
if self.flag?
|
66
|
+
@count += 1
|
67
|
+
@flag = true
|
68
|
+
else
|
69
|
+
raise StandardError, "Tried to toggle an option which expects an argument"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Pass an argument +arg+ to this option
|
74
|
+
def push(arg)
|
75
|
+
@vals << arg
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return the current value of this option
|
79
|
+
def value()
|
80
|
+
if self.flag?
|
81
|
+
return @flag
|
82
|
+
else
|
83
|
+
if self.full? && @vals.length == 1
|
84
|
+
return @vals[0]
|
85
|
+
elsif self.full?
|
86
|
+
return @vals
|
87
|
+
else
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# True if this option expects an argument. Opposite of #flag?
|
94
|
+
def has_args?
|
95
|
+
return @args.length > 0
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return basic usage information: the option's names and arguments
|
99
|
+
def header()
|
100
|
+
if self.flag?
|
101
|
+
args = ''
|
102
|
+
else
|
103
|
+
args = ' ' + @args.join(', ').upcase
|
104
|
+
end
|
105
|
+
short = @short ? "-#{@short} " : ''
|
106
|
+
return "#{short}--#{@long}#{args}"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Represent this option as a string
|
110
|
+
def to_s()
|
111
|
+
return "(#{self.header})"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end # module CLI
|
117
|
+
end # module Ark
|
118
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Ark
|
2
|
+
module CLI
|
3
|
+
|
4
|
+
class Report
|
5
|
+
def initialize()
|
6
|
+
@args = []
|
7
|
+
@named_args = {}
|
8
|
+
@trailing_args = []
|
9
|
+
@counts = {}
|
10
|
+
@options = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def args
|
14
|
+
return @args
|
15
|
+
end
|
16
|
+
def arg
|
17
|
+
return @named_args
|
18
|
+
end
|
19
|
+
def trailing
|
20
|
+
return @trailing_args
|
21
|
+
end
|
22
|
+
def opt
|
23
|
+
return @options
|
24
|
+
end
|
25
|
+
def count
|
26
|
+
return @counts
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # module CLI
|
31
|
+
end # module Ark
|
32
|
+
|
data/lib/ark/cli/spec.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
module Ark
|
2
|
+
module CLI
|
3
|
+
|
4
|
+
class Spec
|
5
|
+
|
6
|
+
# Raised when a nonexistent option is received
|
7
|
+
class NoSuchOptionError < ArgumentError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Raised when there is a syntax error in the args declaration
|
11
|
+
class ArgumentSyntaxError < ArgumentError
|
12
|
+
end
|
13
|
+
|
14
|
+
# Initialize a bare interface spec
|
15
|
+
def initialize()
|
16
|
+
@args = []
|
17
|
+
@options = {}
|
18
|
+
@variadic = false
|
19
|
+
@option_listing = false
|
20
|
+
@trailing_error = false
|
21
|
+
end
|
22
|
+
|
23
|
+
# If true, the full option list will always be displayed in the usage info
|
24
|
+
# header
|
25
|
+
attr_reader :option_listing
|
26
|
+
|
27
|
+
# If true, an error will be raised if trailing arguments are given
|
28
|
+
attr_reader :trailing_error
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def strip(arg)
|
33
|
+
return arg[/^(\S+?)(:|\.\.\.|$)/, 1]
|
34
|
+
end
|
35
|
+
|
36
|
+
def defaulted?(arg)
|
37
|
+
return !arg[/^\S+?:.+/].nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_default(arg)
|
41
|
+
return arg[/^.+?:(.+)/, 1]
|
42
|
+
end
|
43
|
+
|
44
|
+
def variadic?(arg)
|
45
|
+
return !arg[/\.\.\.$/].nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_arg(arg, default: nil, last: false)
|
49
|
+
stripped = strip(arg)
|
50
|
+
@args << stripped
|
51
|
+
if defaulted?(arg)
|
52
|
+
@defaults[stripped] = parse_default(arg)
|
53
|
+
end
|
54
|
+
if variadic?(arg)
|
55
|
+
if last
|
56
|
+
@variadic = true
|
57
|
+
@variad = stripped
|
58
|
+
else
|
59
|
+
raise ArgumentSyntaxError,
|
60
|
+
"Variadic arguments must come last. Offending variad is '#{arg}'"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
public
|
66
|
+
|
67
|
+
def get_name
|
68
|
+
return @name
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_desc
|
72
|
+
return @desc
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_args
|
76
|
+
return @args
|
77
|
+
end
|
78
|
+
|
79
|
+
def has_options?
|
80
|
+
@options.values.uniq.length > 1
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_opts
|
84
|
+
return @options
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get an Option object for the given option +name+
|
88
|
+
def get_opt(name)
|
89
|
+
name = name.to_sym
|
90
|
+
if !@options.keys.member?(name)
|
91
|
+
raise NoSuchOptionError, "Error, no such option: '#{name}'"
|
92
|
+
end
|
93
|
+
return @options[name]
|
94
|
+
end
|
95
|
+
|
96
|
+
def is_variadic?
|
97
|
+
return @variadic
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_variad
|
101
|
+
return @variad
|
102
|
+
end
|
103
|
+
|
104
|
+
def has_default?(arg)
|
105
|
+
@defaults.key?(arg.to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_defaults
|
109
|
+
return @defaults
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_default(arg)
|
113
|
+
@defaults[arg.to_s]
|
114
|
+
end
|
115
|
+
|
116
|
+
def has_args?
|
117
|
+
@args.length > 0
|
118
|
+
end
|
119
|
+
|
120
|
+
# Specify general information about the program
|
121
|
+
# [+name+] Name of the program
|
122
|
+
# [+desc+] Short description of the program
|
123
|
+
# [+args+] A list of named arguments
|
124
|
+
def header(name: nil, desc: nil, args: [])
|
125
|
+
self.name(name)
|
126
|
+
self.desc(desc)
|
127
|
+
self.args(args)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Set the name of the program to +str+
|
131
|
+
def name(str)
|
132
|
+
@name = str.to_s if str
|
133
|
+
end
|
134
|
+
|
135
|
+
# Set the description of the program to +str+
|
136
|
+
def desc(str)
|
137
|
+
@desc = str.to_s if str
|
138
|
+
end
|
139
|
+
|
140
|
+
# Define what arguments the program will accept
|
141
|
+
def args(*input)
|
142
|
+
@args = []
|
143
|
+
@defaults = {}
|
144
|
+
|
145
|
+
input.flatten.each_with_index do |item, i|
|
146
|
+
last = (input.length - (i + 1)) == 0
|
147
|
+
parse_arg(item, last: last)
|
148
|
+
end
|
149
|
+
|
150
|
+
@refargs = @args.clone
|
151
|
+
end
|
152
|
+
|
153
|
+
# Define an Option
|
154
|
+
# [+keys+] A list of names for this option
|
155
|
+
# [+args+] A list of arguments the option expects
|
156
|
+
# [+desc+] A short description of the option, used to provide usage info
|
157
|
+
def opt(long, short=nil, args: nil, desc: nil)
|
158
|
+
long = long.to_sym
|
159
|
+
short = short.to_sym if short
|
160
|
+
args = [args] if args.is_a?(String)
|
161
|
+
args.map!(&:to_sym) if args
|
162
|
+
o = Option.new(long, short, args, desc)
|
163
|
+
@options[long] = o
|
164
|
+
@options[short] = o if short
|
165
|
+
end
|
166
|
+
|
167
|
+
# Force the full option list display in the usage info, no matter how many
|
168
|
+
# options the program has
|
169
|
+
def force_option_list()
|
170
|
+
@option_list = true
|
171
|
+
end
|
172
|
+
|
173
|
+
# The parser will raise an error on finding trailing arguments (default
|
174
|
+
# behavior is to ignore and stuff the trailing args into Report.trailing_args)
|
175
|
+
def raise_on_trailing()
|
176
|
+
@trailing_error = true
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end # module CLI
|
182
|
+
end # module Ark
|
183
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ark-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Macquarie Sharpless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ark-util
|
@@ -16,31 +16,36 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.3'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.3.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '0.
|
29
|
+
version: '0.3'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: 0.3.0
|
33
33
|
description: |
|
34
|
-
A
|
35
|
-
|
36
|
-
|
34
|
+
A library for parsing options and arguments from the commandline. Parses ARGV
|
35
|
+
and returns an object holding information about what options were set on the
|
36
|
+
commandline, and what arguments were given.
|
37
37
|
email:
|
38
38
|
- macquarie.sharpless@gmail.com
|
39
39
|
executables: []
|
40
40
|
extensions: []
|
41
41
|
extra_rdoc_files: []
|
42
42
|
files:
|
43
|
+
- README.md
|
43
44
|
- lib/ark/cli.rb
|
45
|
+
- lib/ark/cli/interface.rb
|
46
|
+
- lib/ark/cli/option.rb
|
47
|
+
- lib/ark/cli/report.rb
|
48
|
+
- lib/ark/cli/spec.rb
|
44
49
|
homepage: https://github.com/grimheart/ark-cli
|
45
50
|
licenses:
|
46
51
|
- GPL-3.0
|
@@ -64,5 +69,5 @@ rubyforge_project:
|
|
64
69
|
rubygems_version: 2.4.5
|
65
70
|
signing_key:
|
66
71
|
specification_version: 4
|
67
|
-
summary:
|
72
|
+
summary: Command line interface library
|
68
73
|
test_files: []
|