ark-cli 0.5.0 → 0.6.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 +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
|