argy 0.1.0 → 0.2.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/Gemfile.lock +1 -7
- data/README.md +71 -9
- data/bin/example +21 -7
- data/lib/argy.rb +10 -2
- data/lib/argy/help.rb +16 -13
- data/lib/argy/options.rb +38 -0
- data/lib/argy/parameter.rb +1 -0
- data/lib/argy/parser.rb +21 -19
- data/lib/argy/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '01379049c1a1d66874589c09735fba37dbfbf39b'
|
4
|
+
data.tar.gz: fb593767af624cc2c3dc06ec32a8c2286fea7f9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3addec730a4dce220927c0518d52a1e2188fc27ff67de5ffddc89f0e91956b62dd31d7204968de26ff14b654e5b10cd9cc10f202a00f178e6a64819ce1f9b4f4
|
7
|
+
data.tar.gz: f034dc884c0b9bad616f2daedba4068cfcf1ea8adfc27862466e6afd2c80446b880e1a36e19b5a1e7bc44d588b71ce435bbf8565398da64b109dbb7942f7a381
|
data/Gemfile.lock
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
argy (0.
|
4
|
+
argy (0.2.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
coderay (1.1.2)
|
10
10
|
diff-lcs (1.3)
|
11
|
-
equatable (0.6.1)
|
12
11
|
method_source (0.9.2)
|
13
|
-
pastel (0.7.3)
|
14
|
-
equatable (~> 0.6)
|
15
|
-
tty-color (~> 0.5)
|
16
12
|
pry (0.12.2)
|
17
13
|
coderay (~> 1.1.0)
|
18
14
|
method_source (~> 0.9.0)
|
@@ -30,7 +26,6 @@ GEM
|
|
30
26
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
27
|
rspec-support (~> 3.9.0)
|
32
28
|
rspec-support (3.9.0)
|
33
|
-
tty-color (0.5.0)
|
34
29
|
|
35
30
|
PLATFORMS
|
36
31
|
ruby
|
@@ -38,7 +33,6 @@ PLATFORMS
|
|
38
33
|
DEPENDENCIES
|
39
34
|
argy!
|
40
35
|
bundler (~> 2.0)
|
41
|
-
pastel
|
42
36
|
pry
|
43
37
|
rake (~> 10.0)
|
44
38
|
rspec (~> 3.0)
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Argy
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Yet another command-line option parser.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -22,17 +20,81 @@ Or install it yourself as:
|
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
Here's an example:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require "argy"
|
27
|
+
|
28
|
+
parser = Argy.new do |o|
|
29
|
+
o.description "Prints messages"
|
30
|
+
o.usage "example"
|
31
|
+
o.example "$ example hello"
|
32
|
+
|
33
|
+
o.argument :message, desc: "message to print", required: true
|
34
|
+
|
35
|
+
o.option :loud, type: :boolean, desc: "say the message loudly"
|
36
|
+
o.option :count, type: :integer, desc: "number of times to print", default: 1
|
37
|
+
|
38
|
+
o.on "-v", "print the verison and exit" do
|
39
|
+
puts Example::VERSION
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
o.on "-h", "--help", "show this help and exit" do
|
44
|
+
puts o.help
|
45
|
+
puts o.help.section "SECTION"
|
46
|
+
puts o.help.entry "foo", desc: "bar"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
options = parser.parse(ARGV)
|
53
|
+
message = options.message
|
54
|
+
message = message.upcase if options.loud?
|
55
|
+
options.count.times { puts message }
|
56
|
+
rescue Argy::Error => err
|
57
|
+
abort err.message
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
## Option Types
|
26
62
|
|
27
|
-
|
63
|
+
Argy supports the following option types:
|
28
64
|
|
29
|
-
|
65
|
+
- `:string`
|
66
|
+
- `:boolean`
|
67
|
+
- `:integer`
|
68
|
+
- `:float`
|
69
|
+
- `:array`
|
70
|
+
- `:pathname`
|
71
|
+
|
72
|
+
However, Argy also supports custom option types. For example:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class NameOption
|
76
|
+
def self.call(input)
|
77
|
+
parts = input.split(" ")
|
78
|
+
raise Argy::CoersionError, "Invalid name" if parts.length != 2
|
79
|
+
new(*parts)
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize(first, last)
|
83
|
+
@first = first
|
84
|
+
@last = last
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Argy.new do |o|
|
89
|
+
o.option :name, type: NameOption
|
90
|
+
end
|
91
|
+
```
|
30
92
|
|
31
|
-
|
93
|
+
An option type is anything that responds to `call`. So, your option type could just be a lambda.
|
32
94
|
|
33
95
|
## Contributing
|
34
96
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
97
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/rzane/argy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
98
|
|
37
99
|
## License
|
38
100
|
|
@@ -40,4 +102,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
40
102
|
|
41
103
|
## Code of Conduct
|
42
104
|
|
43
|
-
Everyone interacting in the Argy project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
105
|
+
Everyone interacting in the Argy project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rzane/argy/blob/master/CODE_OF_CONDUCT.md).
|
data/bin/example
CHANGED
@@ -3,16 +3,30 @@
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "argy"
|
5
5
|
|
6
|
-
|
6
|
+
parser = Argy.new do |o|
|
7
|
+
o.description "Prints messages"
|
7
8
|
o.usage "example"
|
8
|
-
o.
|
9
|
-
o.
|
10
|
-
o.
|
11
|
-
o.option :
|
12
|
-
o.option :foo_bar, aliases: ["-f"], default: "jawn"
|
9
|
+
o.example "$ example hello"
|
10
|
+
o.argument :message, desc: "message to print", required: true
|
11
|
+
o.option :loud, type: :boolean, desc: "say the message loudly"
|
12
|
+
o.option :times, type: :integer, desc: "number of times to print", default: 1
|
13
13
|
o.on "-v", "print the verison and exit" do
|
14
14
|
puts Argy::VERSION
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
o.on "-h", "--help", "show this help and exit" do
|
18
|
+
puts o.help
|
19
|
+
puts o.help.section "SECTION"
|
20
|
+
puts o.help.entry "foo", desc: "bar"
|
21
|
+
exit
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
18
|
-
|
25
|
+
begin
|
26
|
+
options = parser.parse(ARGV)
|
27
|
+
message = options.message
|
28
|
+
message = message.upcase if options.loud?
|
29
|
+
options.times.times { puts message }
|
30
|
+
rescue Argy::Error => err
|
31
|
+
abort err.message
|
32
|
+
end
|
data/lib/argy.rb
CHANGED
@@ -5,13 +5,21 @@ module Argy
|
|
5
5
|
Error = Class.new(StandardError)
|
6
6
|
CoersionError = Class.new(Error)
|
7
7
|
ValidationError = Class.new(Error)
|
8
|
-
|
8
|
+
|
9
|
+
class ParseError < Error
|
10
|
+
attr_reader :original
|
11
|
+
|
12
|
+
def initialize(original)
|
13
|
+
@original = original
|
14
|
+
super(original.message)
|
15
|
+
end
|
16
|
+
end
|
9
17
|
|
10
18
|
def self.new(&block)
|
11
19
|
Argy::Parser.new(&block)
|
12
20
|
end
|
13
21
|
|
14
|
-
def self.parse(argv, &block)
|
22
|
+
def self.parse(argv: ARGV, &block)
|
15
23
|
new(&block).parse(argv)
|
16
24
|
end
|
17
25
|
end
|
data/lib/argy/help.rb
CHANGED
@@ -19,6 +19,18 @@ module Argy
|
|
19
19
|
out.join("\n") + "\n"
|
20
20
|
end
|
21
21
|
|
22
|
+
def section(title)
|
23
|
+
bold "\n#{title}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def entry(name, desc: nil, required: false, default: nil)
|
27
|
+
out = " #{name.ljust(column)}"
|
28
|
+
out += dim("#{desc} ") if desc
|
29
|
+
out += dim("(required) ") if required
|
30
|
+
out += dim("[default: #{default.inspect}]") if default
|
31
|
+
out.rstrip
|
32
|
+
end
|
33
|
+
|
22
34
|
private
|
23
35
|
|
24
36
|
def description(out)
|
@@ -41,7 +53,7 @@ module Argy
|
|
41
53
|
end
|
42
54
|
|
43
55
|
def argument(a)
|
44
|
-
|
56
|
+
entry(a.label, desc: a.desc, required: a.required?, default: a.default)
|
45
57
|
end
|
46
58
|
|
47
59
|
def options(out)
|
@@ -52,19 +64,18 @@ module Argy
|
|
52
64
|
def option(o)
|
53
65
|
label = [option_label(o.label, o.type)]
|
54
66
|
label += o.aliases.map { |a| option_label(a, o.type) }
|
55
|
-
|
67
|
+
entry(label.join(", "), desc: o.desc, required: o.required?, default: o.default)
|
56
68
|
end
|
57
69
|
|
58
70
|
def flags(out)
|
59
|
-
out << bold("\nFLAGS")
|
71
|
+
out << bold("\nFLAGS") if parser.flags.any?
|
60
72
|
out.concat parser.flags.map { |f, _| flag(f) }
|
61
|
-
out << parameter("--help, -h", "show this help and exit")
|
62
73
|
end
|
63
74
|
|
64
75
|
def flag(flag)
|
65
76
|
flag = flag.dup
|
66
77
|
desc = flag.pop unless flag.last.match?(/^-/)
|
67
|
-
|
78
|
+
entry(flag.reverse.join(", "), desc: desc)
|
68
79
|
end
|
69
80
|
|
70
81
|
def option_label(label, type)
|
@@ -72,14 +83,6 @@ module Argy
|
|
72
83
|
label.start_with?("--") ? "#{label}=VALUE" : "#{label} VALUE"
|
73
84
|
end
|
74
85
|
|
75
|
-
def parameter(left, right, required = false, default = nil)
|
76
|
-
label = " #{left.ljust(column)}"
|
77
|
-
label += dim("#{right} ") if right
|
78
|
-
label += dim("(required) ") if required
|
79
|
-
label += dim("[default: #{default.inspect}]") if default
|
80
|
-
label.rstrip
|
81
|
-
end
|
82
|
-
|
83
86
|
def bold(text)
|
84
87
|
color? ? "\e[1m#{text}\e[0m" : text
|
85
88
|
end
|
data/lib/argy/options.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Argy
|
2
|
+
class Options
|
3
|
+
def initialize(values)
|
4
|
+
@values = values
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_h
|
8
|
+
@values
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
@values[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(*args, &block)
|
16
|
+
@values.fetch(*args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def respond_to_missing?(meth, *)
|
22
|
+
@values.key?(meth.to_s.sub(/\?$/, "").to_sym) || super
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(meth, *args)
|
26
|
+
query = meth[-1] == "?"
|
27
|
+
key = query ? meth[0..-2].to_sym : meth.to_sym
|
28
|
+
|
29
|
+
return super unless @values.key?(key)
|
30
|
+
|
31
|
+
unless args.empty?
|
32
|
+
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 0)"
|
33
|
+
end
|
34
|
+
|
35
|
+
query ? !!@values[key] : @values[key]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/argy/parameter.rb
CHANGED
data/lib/argy/parser.rb
CHANGED
@@ -2,6 +2,7 @@ require "optparse"
|
|
2
2
|
require "argy/help"
|
3
3
|
require "argy/option"
|
4
4
|
require "argy/argument"
|
5
|
+
require "argy/options"
|
5
6
|
|
6
7
|
module Argy
|
7
8
|
class Parser
|
@@ -52,25 +53,37 @@ module Argy
|
|
52
53
|
end
|
53
54
|
|
54
55
|
def default_values
|
55
|
-
|
56
|
+
parameters.reduce(unused_args: []) do |acc, opt|
|
56
57
|
acc[opt.name] = opt.default
|
57
58
|
acc
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
|
-
def parse(argv)
|
62
|
+
def parse(argv, strategy: nil)
|
62
63
|
argv = argv.dup
|
63
64
|
values = default_values
|
64
|
-
|
65
65
|
parser = build_parser(values)
|
66
|
-
|
66
|
+
|
67
|
+
case strategy
|
68
|
+
when :order
|
69
|
+
parser.order!(argv)
|
70
|
+
when :permute
|
71
|
+
parser.permute!(argv)
|
72
|
+
else
|
73
|
+
parser.parse!(argv)
|
74
|
+
end
|
67
75
|
|
68
76
|
populate_arguments(values, argv)
|
69
|
-
validate!(values)
|
77
|
+
Options.new validate!(values)
|
78
|
+
rescue OptionParser::ParseError => error
|
79
|
+
raise ParseError.new(error)
|
80
|
+
end
|
70
81
|
|
82
|
+
def validate!(values)
|
83
|
+
parameters.each do |param|
|
84
|
+
param.validate(values[param.name])
|
85
|
+
end
|
71
86
|
values
|
72
|
-
rescue OptionParser::MissingArgument => error
|
73
|
-
raise MissingArgumentError, error.message
|
74
87
|
end
|
75
88
|
|
76
89
|
private
|
@@ -78,19 +91,13 @@ module Argy
|
|
78
91
|
def populate_arguments(values, argv)
|
79
92
|
argv.zip(arguments).each do |value, arg|
|
80
93
|
if arg.nil?
|
81
|
-
values[:
|
94
|
+
values[:unused_args] << value
|
82
95
|
else
|
83
96
|
values[arg.name] = arg.coerce(value)
|
84
97
|
end
|
85
98
|
end
|
86
99
|
end
|
87
100
|
|
88
|
-
def validate!(values)
|
89
|
-
parameters.each do |param|
|
90
|
-
param.validate(values[param.name])
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
101
|
def build_parser(values)
|
95
102
|
OptionParser.new do |o|
|
96
103
|
options.each do |opt|
|
@@ -102,11 +109,6 @@ module Argy
|
|
102
109
|
flags.each do |flag, action|
|
103
110
|
o.on(*flag, &action)
|
104
111
|
end
|
105
|
-
|
106
|
-
o.on("-h", "--help") do
|
107
|
-
puts help
|
108
|
-
exit
|
109
|
-
end
|
110
112
|
end
|
111
113
|
end
|
112
114
|
end
|
data/lib/argy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Zane
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/argy/argument.rb
|
77
77
|
- lib/argy/help.rb
|
78
78
|
- lib/argy/option.rb
|
79
|
+
- lib/argy/options.rb
|
79
80
|
- lib/argy/parameter.rb
|
80
81
|
- lib/argy/parser.rb
|
81
82
|
- lib/argy/version.rb
|