ark-cli 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -10
- data/lib/ark/cli.rb +6 -4
- data/lib/ark/cli/interface.rb +43 -15
- data/lib/ark/cli/option.rb +14 -9
- data/lib/ark/cli/report.rb +25 -14
- data/lib/ark/cli/spec.rb +42 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a54741976deb70204c112ab5ee3ec996463ddaf6
|
4
|
+
data.tar.gz: bf135aed0b692a6d591dff1160773a83b896ad32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b84c3e4562701df554ab07d821140ff4cb02c765c6aebe8d633f4a54f30e595b8d5f7eda3bf0c3b6046f2c4bca6c03eee032c790139cdcc5b431f7ef72207811
|
7
|
+
data.tar.gz: 819682f6427f6d4e0397a43f11ae91cb83ad54b6e4ef411dacded492c7384a6bfa43af917248cb9b1ff6f4fd8a57986f31ee3debb82f3ba59ad5242aa26b95c2
|
data/README.md
CHANGED
@@ -32,9 +32,9 @@ r = Ark::CLI.report do |s|
|
|
32
32
|
end
|
33
33
|
|
34
34
|
r.args # Get all arguments received, including trailing args
|
35
|
-
r.arg
|
36
|
-
r.opt
|
37
|
-
r.count
|
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
38
|
```
|
39
39
|
|
40
40
|
The `CLI.report` method yields a `Spec` instance, which we'll call `s`. Calls to
|
@@ -72,7 +72,7 @@ Arguments with default values are optional - no error will be raised if they
|
|
72
72
|
aren't given.
|
73
73
|
|
74
74
|
```ruby
|
75
|
-
s.args 'file
|
75
|
+
s.args 'file:/tmp/foo'
|
76
76
|
s.args 'host', 'port:22', "user:#{ENV['USER']}"
|
77
77
|
```
|
78
78
|
|
@@ -122,21 +122,21 @@ host, path = r.args
|
|
122
122
|
Get the value of a named argument with the `r.arg` method:
|
123
123
|
|
124
124
|
```ruby
|
125
|
-
host = r.arg
|
126
|
-
path = r.arg
|
125
|
+
host = r.arg(:host)
|
126
|
+
path = r.arg(:path)
|
127
127
|
```
|
128
128
|
|
129
129
|
Inspect the value of an option with `r.opt`:
|
130
130
|
|
131
131
|
```ruby
|
132
|
-
verbose = r.opt
|
133
|
-
port = r.opt
|
132
|
+
verbose = r.opt(:v)
|
133
|
+
port = r.opt(:port)
|
134
134
|
```
|
135
135
|
|
136
136
|
Get a count of the number of times a flag was specified with `r.count`:
|
137
137
|
|
138
138
|
```ruby
|
139
|
-
verbosity = r.count
|
139
|
+
verbosity = r.count(:verbose)
|
140
140
|
```
|
141
141
|
|
142
142
|
Get an array of trailing arguments with `r.trailing`:
|
@@ -156,7 +156,7 @@ CLI declaration.
|
|
156
156
|
|
157
157
|
Usage information for the above declaration would look like this:
|
158
158
|
|
159
|
-
example [
|
159
|
+
example [-p --port NUMBER] [-v --verbose] [-h --help] HOST PATH
|
160
160
|
|
161
161
|
An example demonstrating usage of ark-cli
|
162
162
|
|
data/lib/ark/cli.rb
CHANGED
@@ -28,12 +28,14 @@ module Ark # :nodoc:
|
|
28
28
|
|
29
29
|
# A library for handling options and arguments from the command line.
|
30
30
|
#
|
31
|
-
# Call #
|
31
|
+
# Call #report to define a new interface and parse the command line. See
|
32
32
|
# +README.md+ or +example/hello.rb+ for more information.
|
33
33
|
module CLI
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
34
|
+
# :call-seq:
|
35
|
+
# report(input=ARGV) { |spec| ... } => Report
|
36
|
+
#
|
37
|
+
# Convenience method for interface declarations. Yields a +Spec+ instance and
|
38
|
+
# returns a +Report+ instance for inspection.
|
37
39
|
#
|
38
40
|
# +args+ is an array of strings, which defaults to ARGV
|
39
41
|
def self.report(args=ARGV, &block)
|
data/lib/ark/cli/interface.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
-
module Ark
|
1
|
+
module Ark # :nodoc:
|
2
2
|
module CLI
|
3
3
|
|
4
|
+
# Main class for ark-cli. Defines a +Spec+, parses the command line and returns
|
5
|
+
# +Report+ objects.
|
4
6
|
class Interface
|
5
7
|
|
6
8
|
# Raised when the command line is malformed
|
7
9
|
class SyntaxError < ArgumentError
|
8
10
|
end
|
9
11
|
|
12
|
+
# Raised when a required argument is not given
|
13
|
+
class InterfaceError < ArgumentError
|
14
|
+
end
|
15
|
+
|
16
|
+
# :call-seq:
|
17
|
+
# rebuild(input=ARGV) { |spec| ... } => Interface
|
18
|
+
#
|
10
19
|
# Initialize an Interface instance.
|
11
20
|
#
|
12
21
|
# +args+ must be an array of strings, like ARGV
|
@@ -14,8 +23,11 @@ class Interface
|
|
14
23
|
self.rebuild(args, &block)
|
15
24
|
end
|
16
25
|
|
26
|
+
# The +Report+ object for this interface, for inspecting information parsed
|
27
|
+
# from the command line.
|
17
28
|
attr_reader :report
|
18
29
|
|
30
|
+
# Rebuild the interface with a new spec and args
|
19
31
|
def rebuild(input=ARGV, &block)
|
20
32
|
@input = input
|
21
33
|
@spec = Spec.new
|
@@ -30,7 +42,11 @@ class Interface
|
|
30
42
|
last_opt = nil
|
31
43
|
refargs = @spec.get_args.clone
|
32
44
|
|
33
|
-
|
45
|
+
args = []
|
46
|
+
trailing = []
|
47
|
+
named = {}
|
48
|
+
options = {}
|
49
|
+
counts = {}
|
34
50
|
|
35
51
|
@input.each do |word|
|
36
52
|
dbg "Parsing '#{word}'"
|
@@ -66,36 +82,47 @@ class Interface
|
|
66
82
|
else
|
67
83
|
dbg "Parsed output arg", 1
|
68
84
|
taking_options = false
|
69
|
-
|
85
|
+
args << word
|
70
86
|
key = refargs.shift
|
71
87
|
if key
|
72
88
|
if key == @spec.get_variad
|
73
|
-
|
74
|
-
|
89
|
+
named[key] = []
|
90
|
+
named[key] << word
|
75
91
|
else
|
76
|
-
|
92
|
+
named[key] = word
|
77
93
|
end
|
78
94
|
elsif @spec.is_variadic?
|
79
|
-
|
95
|
+
named[@spec.get_variad] << word
|
80
96
|
else
|
81
|
-
|
97
|
+
trailing << word
|
82
98
|
end
|
83
99
|
end
|
84
100
|
end
|
85
101
|
end
|
102
|
+
if @spec.trailing_error && !trailing.empty?
|
103
|
+
raise InterfaceError, "Error: got trailing option(s): #{trailing.join(', ')}"
|
104
|
+
end
|
86
105
|
@spec.get_opts.each do |name, opt|
|
87
|
-
|
88
|
-
|
106
|
+
options[name] = opt.value
|
107
|
+
counts[name] = opt.count
|
89
108
|
end
|
90
109
|
@spec.get_args.each do |name|
|
91
|
-
if
|
110
|
+
if named[name].nil?
|
92
111
|
if @spec.has_default?(name)
|
93
|
-
|
94
|
-
|
112
|
+
named[name] = @spec.get_default(name)
|
113
|
+
args << named[name]
|
114
|
+
else
|
115
|
+
unless @spec.is_variadic? && @spec.get_variad == name
|
116
|
+
raise InterfaceError, "Required argument '#{name.upcase}' was not given."
|
117
|
+
end
|
95
118
|
end
|
96
119
|
end
|
97
120
|
end
|
98
|
-
if @
|
121
|
+
if @spec.is_variadic?
|
122
|
+
named[@spec.get_variad] ||= []
|
123
|
+
end
|
124
|
+
@report = Report.new(args, named, trailing, options, counts)
|
125
|
+
if @report.opt(:help)
|
99
126
|
self.print_usage()
|
100
127
|
end
|
101
128
|
end
|
@@ -166,7 +193,8 @@ class Interface
|
|
166
193
|
puts self.usage
|
167
194
|
exit 0
|
168
195
|
end
|
169
|
-
|
196
|
+
|
197
|
+
end # class Interface
|
170
198
|
|
171
199
|
end # module CLI
|
172
200
|
end # module Ark
|
data/lib/ark/cli/option.rb
CHANGED
@@ -9,14 +9,15 @@ class Option
|
|
9
9
|
# [+keys+] A list of names this option will be identified by
|
10
10
|
# [+args+] A list of argument named this option will expect
|
11
11
|
# [+desc+] A short description of this option
|
12
|
-
def initialize(long, short=nil, args=nil, desc=nil)
|
13
|
-
@long
|
14
|
-
@short
|
15
|
-
@args
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
12
|
+
def initialize(long, short=nil, args=nil, defaults=nil, desc=nil)
|
13
|
+
@long = long
|
14
|
+
@short = short
|
15
|
+
@args = args || []
|
16
|
+
@defaults = defaults || {}
|
17
|
+
@vals = []
|
18
|
+
@flag = false
|
19
|
+
@count = 0
|
20
|
+
@desc = desc || ''
|
20
21
|
end
|
21
22
|
|
22
23
|
# A count of how many times this option has been given on the command line.
|
@@ -85,7 +86,11 @@ class Option
|
|
85
86
|
elsif self.full?
|
86
87
|
return @vals
|
87
88
|
else
|
88
|
-
|
89
|
+
if !@defaults.compact.empty?
|
90
|
+
return @defaults.length > 1 ? @defaults : @defaults.first
|
91
|
+
else
|
92
|
+
return nil
|
93
|
+
end
|
89
94
|
end
|
90
95
|
end
|
91
96
|
end
|
data/lib/ark/cli/report.rb
CHANGED
@@ -1,29 +1,40 @@
|
|
1
|
-
module Ark
|
1
|
+
module Ark # :nodoc:
|
2
2
|
module CLI
|
3
3
|
|
4
|
+
# Stores information parsed from the command line for later inspection
|
4
5
|
class Report
|
5
|
-
|
6
|
-
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@options
|
6
|
+
# Initialize a bare +Report+ object
|
7
|
+
def initialize(args, named, trailing, options, counts)
|
8
|
+
@args = args
|
9
|
+
@named = named
|
10
|
+
@trailing = trailing
|
11
|
+
@options = options
|
12
|
+
@counts = counts
|
11
13
|
end
|
12
14
|
|
15
|
+
# Return an array of all args parsed
|
13
16
|
def args
|
14
17
|
return @args
|
15
18
|
end
|
16
|
-
|
17
|
-
|
19
|
+
|
20
|
+
# Get an argument by +name+
|
21
|
+
def arg(name)
|
22
|
+
return @named[name.to_s]
|
18
23
|
end
|
24
|
+
|
25
|
+
# Return an array of any arguments without names
|
19
26
|
def trailing
|
20
|
-
return @
|
27
|
+
return @trailing
|
21
28
|
end
|
22
|
-
|
23
|
-
|
29
|
+
|
30
|
+
# Get the value of an option by +name+
|
31
|
+
def opt(name)
|
32
|
+
return @options[name.to_s]
|
24
33
|
end
|
25
|
-
|
26
|
-
|
34
|
+
|
35
|
+
# Get the toggle count for an option by +name+
|
36
|
+
def count(name)
|
37
|
+
return @counts[name.to_s]
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
data/lib/ark/cli/spec.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
module Ark
|
1
|
+
module Ark # :nodoc:
|
2
2
|
module CLI
|
3
3
|
|
4
|
+
# The +Spec+ class defines the properties of an interface, namely its expected
|
5
|
+
# arguments and option definitions, as well as the program name and
|
6
|
+
# description. The +Spec+ instance forms the DSL used for interface declarations
|
7
|
+
# with the methods +name+, +desc+, +args+, and +opt+.
|
4
8
|
class Spec
|
5
9
|
|
6
10
|
# Raised when a nonexistent option is received
|
@@ -11,7 +15,7 @@ class Spec
|
|
11
15
|
class ArgumentSyntaxError < ArgumentError
|
12
16
|
end
|
13
17
|
|
14
|
-
# Initialize a bare interface
|
18
|
+
# Initialize a bare interface +Spec+
|
15
19
|
def initialize()
|
16
20
|
@args = []
|
17
21
|
@options = {}
|
@@ -29,22 +33,28 @@ class Spec
|
|
29
33
|
|
30
34
|
private
|
31
35
|
|
36
|
+
# Strip any special syntax from a given argument. Used when parsing arguments
|
32
37
|
def strip(arg)
|
33
38
|
return arg[/^(\S+?)(:|\.\.\.|$)/, 1]
|
34
39
|
end
|
35
40
|
|
41
|
+
# Return +true+ if the given argument has a default value, like +'arg:defaultvalue'+
|
36
42
|
def defaulted?(arg)
|
37
43
|
return !arg[/^\S+?:.+/].nil?
|
38
44
|
end
|
39
45
|
|
46
|
+
# Parse the default value from an arg with one
|
40
47
|
def parse_default(arg)
|
41
48
|
return arg[/^.+?:(.+)/, 1]
|
42
49
|
end
|
43
50
|
|
51
|
+
# Return +true+ if the given argument is a glob, like +'arg...'+
|
44
52
|
def variadic?(arg)
|
45
53
|
return !arg[/\.\.\.$/].nil?
|
46
54
|
end
|
47
55
|
|
56
|
+
# Parse a given argument, interpreting any special syntax, and storing
|
57
|
+
# argument information as needed
|
48
58
|
def parse_arg(arg, default: nil, last: false)
|
49
59
|
stripped = strip(arg)
|
50
60
|
@args << stripped
|
@@ -64,55 +74,66 @@ class Spec
|
|
64
74
|
|
65
75
|
public
|
66
76
|
|
77
|
+
# Get the name defined for this spec
|
67
78
|
def get_name
|
68
79
|
return @name
|
69
80
|
end
|
70
81
|
|
82
|
+
# Get the description defined for this spec
|
71
83
|
def get_desc
|
72
84
|
return @desc
|
73
85
|
end
|
74
86
|
|
87
|
+
# Get an array of argument names defined for this spec
|
75
88
|
def get_args
|
76
89
|
return @args
|
77
90
|
end
|
78
91
|
|
92
|
+
# Return +true+ if this interface has any options defined for it
|
79
93
|
def has_options?
|
80
94
|
@options.values.uniq.length > 1
|
81
95
|
end
|
82
96
|
|
97
|
+
# Get a hash of any options defined on this spec
|
83
98
|
def get_opts
|
84
99
|
return @options
|
85
100
|
end
|
86
101
|
|
87
|
-
# Get an Option object for the given option +name+
|
102
|
+
# Get an +Option+ object for the given option +name+
|
88
103
|
def get_opt(name)
|
89
|
-
name = name.
|
104
|
+
name = name.to_s
|
90
105
|
if !@options.keys.member?(name)
|
91
106
|
raise NoSuchOptionError, "Error, no such option: '#{name}'"
|
92
107
|
end
|
93
108
|
return @options[name]
|
94
109
|
end
|
95
110
|
|
111
|
+
# Return +true+ if this interface is variadic
|
96
112
|
def is_variadic?
|
97
113
|
return @variadic
|
98
114
|
end
|
99
115
|
|
116
|
+
# Return the argument name of the variadic argument
|
100
117
|
def get_variad
|
101
118
|
return @variad
|
102
119
|
end
|
103
120
|
|
121
|
+
# Return +true+ if the given argument +arg+ has a default value
|
104
122
|
def has_default?(arg)
|
105
123
|
@defaults.key?(arg.to_s)
|
106
124
|
end
|
107
125
|
|
126
|
+
# Return a hash of all default values
|
108
127
|
def get_defaults
|
109
128
|
return @defaults
|
110
129
|
end
|
111
130
|
|
131
|
+
# Return the default value of the given argument +arg+
|
112
132
|
def get_default(arg)
|
113
133
|
@defaults[arg.to_s]
|
114
134
|
end
|
115
135
|
|
136
|
+
# Return +true+ if this interface has any arguments defined
|
116
137
|
def has_args?
|
117
138
|
@args.length > 0
|
118
139
|
end
|
@@ -143,6 +164,7 @@ class Spec
|
|
143
164
|
@defaults = {}
|
144
165
|
|
145
166
|
input.flatten.each_with_index do |item, i|
|
167
|
+
item = item.to_s
|
146
168
|
last = (input.length - (i + 1)) == 0
|
147
169
|
parse_arg(item, last: last)
|
148
170
|
end
|
@@ -155,11 +177,23 @@ class Spec
|
|
155
177
|
# [+args+] A list of arguments the option expects
|
156
178
|
# [+desc+] A short description of the option, used to provide usage info
|
157
179
|
def opt(long, short=nil, args: nil, desc: nil)
|
158
|
-
long = long.
|
159
|
-
short = short.
|
180
|
+
long = long.to_s
|
181
|
+
short = short.to_s if short
|
160
182
|
args = [args] if args.is_a?(String)
|
161
|
-
|
162
|
-
|
183
|
+
defaults = []
|
184
|
+
if args
|
185
|
+
args.map! do |arg|
|
186
|
+
arg = arg.to_s
|
187
|
+
if defaulted?(arg)
|
188
|
+
defaults << parse_default(arg)
|
189
|
+
arg = strip(arg)
|
190
|
+
else
|
191
|
+
defaults << nil
|
192
|
+
end
|
193
|
+
arg
|
194
|
+
end
|
195
|
+
end
|
196
|
+
o = Option.new(long, short, args, defaults, desc)
|
163
197
|
@options[long] = o
|
164
198
|
@options[short] = o if short
|
165
199
|
end
|
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.6.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-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ark-util
|