argy 0.2.0 → 0.2.1
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/.yardopts +6 -0
- data/lib/argy.rb +26 -0
- data/lib/argy/argument.rb +3 -0
- data/lib/argy/help.rb +15 -0
- data/lib/argy/option.rb +13 -0
- data/lib/argy/options.rb +15 -0
- data/lib/argy/parameter.rb +35 -1
- data/lib/argy/parser.rb +75 -1
- data/lib/argy/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39b5a23a831916297c03424c7b40e43991a0b69c
|
4
|
+
data.tar.gz: c0d027d704e117f89016d8d512ab3b59c801f856
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83a1ec9cad3de44f46233287df5487ffe0fd1d4eb7d19ee9a0922c05ea494f999b692ba72d040e55a409fb7b1465c806e8e7b088689e809870c279adc78d7592
|
7
|
+
data.tar.gz: a4ff6936385c154d67a2f33a2197dd2c7c201f39a5a7c2b61964f2fff76245dd5f9dfa44a3ba9fe68c231855893f78e59fa991fed67b3922ad2636fc654c867e
|
data/.yardopts
ADDED
data/lib/argy.rb
CHANGED
@@ -2,11 +2,21 @@ require "argy/version"
|
|
2
2
|
require "argy/parser"
|
3
3
|
|
4
4
|
module Argy
|
5
|
+
# Base class for all of Argy's errors.
|
5
6
|
Error = Class.new(StandardError)
|
7
|
+
|
8
|
+
# An error that is raised when an option
|
9
|
+
# cannot be coerced to the correct type
|
6
10
|
CoersionError = Class.new(Error)
|
11
|
+
|
12
|
+
# An error that is raised when an option
|
13
|
+
# is not valid.
|
7
14
|
ValidationError = Class.new(Error)
|
8
15
|
|
16
|
+
# An error that is raised when parsing fails.
|
9
17
|
class ParseError < Error
|
18
|
+
# The original error from OptionParser.
|
19
|
+
# @return [OptionParser::ParseError]
|
10
20
|
attr_reader :original
|
11
21
|
|
12
22
|
def initialize(original)
|
@@ -15,10 +25,26 @@ module Argy
|
|
15
25
|
end
|
16
26
|
end
|
17
27
|
|
28
|
+
# Define a new parser.
|
29
|
+
# @see Parser
|
30
|
+
# @example
|
31
|
+
# parser = Argy.new do |o|
|
32
|
+
# o.argument :input, desc: "the input file"
|
33
|
+
# o.option :verbose, type: :boolean
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# options = parser.parse(ARGV)
|
18
37
|
def self.new(&block)
|
19
38
|
Argy::Parser.new(&block)
|
20
39
|
end
|
21
40
|
|
41
|
+
# Define a parser and return the options in one go.
|
42
|
+
# @see Parser
|
43
|
+
# @example
|
44
|
+
# options = Argy.parse do
|
45
|
+
# o.argument :input, desc: "the input file"
|
46
|
+
# o.option :verbose, type: :boolean
|
47
|
+
# end
|
22
48
|
def self.parse(argv: ARGV, &block)
|
23
49
|
new(&block).parse(argv)
|
24
50
|
end
|
data/lib/argy/argument.rb
CHANGED
data/lib/argy/help.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
module Argy
|
2
|
+
# Builds help information
|
2
3
|
class Help
|
4
|
+
# Create a new Help
|
5
|
+
# @param parser [Parser] the parser to generate help for
|
6
|
+
# @param column [Integer] the column width of the help
|
7
|
+
# @param color [TrueClass,FalseClass] whether or not to print with color
|
3
8
|
def initialize(parser, column: 30, color: $stdout.tty?)
|
4
9
|
@parser = parser
|
5
10
|
@column = column
|
6
11
|
@color = color
|
7
12
|
end
|
8
13
|
|
14
|
+
# The help information
|
15
|
+
# @return [String]
|
9
16
|
def to_s
|
10
17
|
out = []
|
11
18
|
|
@@ -19,10 +26,18 @@ module Argy
|
|
19
26
|
out.join("\n") + "\n"
|
20
27
|
end
|
21
28
|
|
29
|
+
# Format the title of a custom section
|
30
|
+
# @return [String]
|
22
31
|
def section(title)
|
23
32
|
bold "\n#{title}"
|
24
33
|
end
|
25
34
|
|
35
|
+
# Format an entry of a section
|
36
|
+
# @param name [String] left column of the entry
|
37
|
+
# @param desc [String] right column of the entry
|
38
|
+
# @param required [TrueClass,FalseClass] whether or not the entry is required
|
39
|
+
# @param default [Object] default value for the entry
|
40
|
+
# @return [String]
|
26
41
|
def entry(name, desc: nil, required: false, default: nil)
|
27
42
|
out = " #{name.ljust(column)}"
|
28
43
|
out += dim("#{desc} ") if desc
|
data/lib/argy/option.rb
CHANGED
@@ -1,14 +1,26 @@
|
|
1
1
|
require "argy/parameter"
|
2
2
|
|
3
3
|
module Argy
|
4
|
+
# An option to be parsed from the command line
|
4
5
|
class Option < Parameter
|
6
|
+
# A list of alternative flags
|
7
|
+
# @return [Array<String>]
|
5
8
|
attr_reader :aliases
|
6
9
|
|
10
|
+
# Create a new Option
|
11
|
+
# @param name [Symbol] name of the parameter
|
12
|
+
# @param aliases [Array<String>] a list of alternative flags
|
13
|
+
# @param desc [String,nil] description for the parameter
|
14
|
+
# @param type [Symbol,#call] type of parameter
|
15
|
+
# @param default [Object] default value for the parameter
|
16
|
+
# @param required [TrueClass,FalseClass] whether or not the field is required
|
7
17
|
def initialize(*args, aliases: [], **opts)
|
8
18
|
super(*args, **opts)
|
9
19
|
@aliases = aliases
|
10
20
|
end
|
11
21
|
|
22
|
+
# The display label for the argument
|
23
|
+
# @return [String]
|
12
24
|
def label
|
13
25
|
case type
|
14
26
|
when :boolean
|
@@ -18,6 +30,7 @@ module Argy
|
|
18
30
|
end
|
19
31
|
end
|
20
32
|
|
33
|
+
# @private
|
21
34
|
def to_option_parser
|
22
35
|
options = []
|
23
36
|
options << aliases.join(" ") unless aliases.empty?
|
data/lib/argy/options.rb
CHANGED
@@ -1,17 +1,32 @@
|
|
1
1
|
module Argy
|
2
|
+
# The resulting options that were parsed from the command line.
|
3
|
+
# @example Getting a value
|
4
|
+
# options = Options.new(foo: "bar")
|
5
|
+
# options.foo #=> "bar"
|
6
|
+
# @example Querying for a value's truthiness
|
7
|
+
# options = Options.new(foo: "bar")
|
8
|
+
# options.foo? #=> true
|
2
9
|
class Options
|
10
|
+
# Create a new Options
|
11
|
+
# @param values [Hash{Symbol => Object}]
|
3
12
|
def initialize(values)
|
4
13
|
@values = values
|
5
14
|
end
|
6
15
|
|
16
|
+
# The values as a hash
|
17
|
+
# @return [Hash{Symbol => Object}]
|
7
18
|
def to_h
|
8
19
|
@values
|
9
20
|
end
|
10
21
|
|
22
|
+
# Get a value by key
|
23
|
+
# @see Hash#[]
|
11
24
|
def [](key)
|
12
25
|
@values[key]
|
13
26
|
end
|
14
27
|
|
28
|
+
# Fetch a value by key or provide a default.
|
29
|
+
# @see Hash#fetch
|
15
30
|
def fetch(*args, &block)
|
16
31
|
@values.fetch(*args, &block)
|
17
32
|
end
|
data/lib/argy/parameter.rb
CHANGED
@@ -2,9 +2,30 @@ require "pathname"
|
|
2
2
|
require "argy/parameter"
|
3
3
|
|
4
4
|
module Argy
|
5
|
+
# @abstract Subclasses must implement {#label}
|
5
6
|
class Parameter
|
6
|
-
|
7
|
+
# The name of the parameter
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :name
|
7
10
|
|
11
|
+
# The type of the parameter
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
# The default value for the parameter
|
16
|
+
# @return [Object]
|
17
|
+
attr_reader :default
|
18
|
+
|
19
|
+
# The description for the parameter
|
20
|
+
# @return [String]
|
21
|
+
attr_reader :desc
|
22
|
+
|
23
|
+
# Create a new Parameter
|
24
|
+
# @param name [Symbol] name of the parameter
|
25
|
+
# @param desc [String,nil] description for the parameter
|
26
|
+
# @param type [Symbol,#call] type of parameter
|
27
|
+
# @param default [Object] default value for the parameter
|
28
|
+
# @param required [TrueClass,FalseClass] whether or not the field is required
|
8
29
|
def initialize(name, desc: nil, type: :string, default: nil, required: false)
|
9
30
|
@name = name
|
10
31
|
@type = type
|
@@ -13,20 +34,33 @@ module Argy
|
|
13
34
|
@required = required
|
14
35
|
end
|
15
36
|
|
37
|
+
# The display label for the paramter
|
38
|
+
# @abstract
|
39
|
+
# @return [String]
|
16
40
|
def label
|
17
41
|
raise NotImplementedError, __method__
|
18
42
|
end
|
19
43
|
|
44
|
+
# Check if the parameter is required
|
45
|
+
# @return [TrueClass,FalseClass]
|
20
46
|
def required?
|
21
47
|
@required
|
22
48
|
end
|
23
49
|
|
50
|
+
# Validates a value.
|
51
|
+
# @return [Object] the value
|
52
|
+
# @raise [ValidationError] if the valid is invalid
|
24
53
|
def validate(value)
|
25
54
|
if required? && value.nil?
|
26
55
|
raise ValidationError, "`#{label}` is a required parameter"
|
27
56
|
end
|
57
|
+
|
58
|
+
value
|
28
59
|
end
|
29
60
|
|
61
|
+
# Coerces a value to the correct type.
|
62
|
+
# @param value [Object] the value to coerce
|
63
|
+
# @raise [CoersionError] if the value cannot be coerced
|
30
64
|
def coerce(value)
|
31
65
|
case type
|
32
66
|
when :string, :boolean
|
data/lib/argy/parser.rb
CHANGED
@@ -5,8 +5,23 @@ require "argy/argument"
|
|
5
5
|
require "argy/options"
|
6
6
|
|
7
7
|
module Argy
|
8
|
+
# Parses command line arguments.
|
8
9
|
class Parser
|
9
|
-
|
10
|
+
# The examples that were declared
|
11
|
+
# @return [Array<String>]
|
12
|
+
attr_reader :examples
|
13
|
+
|
14
|
+
# The arguments that were declared
|
15
|
+
# @return [Array<Argument>]
|
16
|
+
attr_reader :arguments
|
17
|
+
|
18
|
+
# The options that were declared
|
19
|
+
# @return [Array<Option>]
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
# The flags that were declared
|
23
|
+
# @return [Array<Array(Array<String>, Proc)>]
|
24
|
+
attr_reader :flags
|
10
25
|
|
11
26
|
def initialize
|
12
27
|
@usage = $0
|
@@ -18,40 +33,89 @@ module Argy
|
|
18
33
|
yield self if block_given?
|
19
34
|
end
|
20
35
|
|
36
|
+
# Gets or sets the usage for your program. If the
|
37
|
+
# provided usage is nil, the usage will not change.
|
38
|
+
# @param usage [String,nil] sets the usage if not nil
|
39
|
+
# @return [String] usage
|
40
|
+
# @example
|
41
|
+
# Argy.new do |o|
|
42
|
+
# o.usage "example [INPUT]"
|
43
|
+
# end
|
21
44
|
def usage(usage = nil)
|
22
45
|
@usage = usage if usage
|
23
46
|
@usage
|
24
47
|
end
|
25
48
|
|
49
|
+
# Gets or sets a description for your program. If the
|
50
|
+
# provided description is nil, the description will
|
51
|
+
# not change.
|
52
|
+
# @param description [String,nil]
|
53
|
+
# @return [String]
|
54
|
+
# @example
|
55
|
+
# Argy.new do |o|
|
56
|
+
# o.description "a really useful program"
|
57
|
+
# end
|
26
58
|
def description(description = nil)
|
27
59
|
@description = description if description
|
28
60
|
@description
|
29
61
|
end
|
30
62
|
|
63
|
+
# Adds an example
|
64
|
+
# @example
|
65
|
+
# Argy.new do |o|
|
66
|
+
# o.example "$ example foo"
|
67
|
+
# end
|
31
68
|
def example(example)
|
32
69
|
@examples << example
|
33
70
|
end
|
34
71
|
|
72
|
+
# Adds an argument
|
73
|
+
# @see Argument#initialize
|
74
|
+
# @example
|
75
|
+
# Argy.new do |o|
|
76
|
+
# o.argument :input
|
77
|
+
# end
|
35
78
|
def argument(*args)
|
36
79
|
@arguments << Argument.new(*args)
|
37
80
|
end
|
38
81
|
|
82
|
+
# Adds an option
|
83
|
+
# @see Option#initialize
|
84
|
+
# @example
|
85
|
+
# Argy.new do |o|
|
86
|
+
# o.option :verbose, type: :boolean
|
87
|
+
# end
|
39
88
|
def option(*args)
|
40
89
|
@options << Option.new(*args)
|
41
90
|
end
|
42
91
|
|
92
|
+
# Adds a flag
|
93
|
+
# @example
|
94
|
+
# Argy.new do |o|
|
95
|
+
# o.on "-v", "--version" do
|
96
|
+
# puts Example::VERSION
|
97
|
+
# exit
|
98
|
+
# end
|
99
|
+
# end
|
43
100
|
def on(*args, &action)
|
44
101
|
@flags << [args, action]
|
45
102
|
end
|
46
103
|
|
104
|
+
# All parameters that are defined
|
105
|
+
# @return [Array<Argument, Option>]
|
47
106
|
def parameters
|
48
107
|
arguments + options
|
49
108
|
end
|
50
109
|
|
110
|
+
# Generate help for this parser.
|
111
|
+
# @see Help#initialize
|
112
|
+
# @return [Help]
|
51
113
|
def help(**opts)
|
52
114
|
Help.new(self, **opts)
|
53
115
|
end
|
54
116
|
|
117
|
+
# Build the default values for the declared paramters.
|
118
|
+
# @return [Hash{Symbol => Object}]
|
55
119
|
def default_values
|
56
120
|
parameters.reduce(unused_args: []) do |acc, opt|
|
57
121
|
acc[opt.name] = opt.default
|
@@ -59,6 +123,12 @@ module Argy
|
|
59
123
|
end
|
60
124
|
end
|
61
125
|
|
126
|
+
# Build the default values for the declared paramters.
|
127
|
+
# @param argv [Array<String>] the command line arguments to parse
|
128
|
+
# @param strategy [Symbol,nil] can be either `:order` or `:permute`. See
|
129
|
+
# `OptionParser#order!` and `OptionParser#permute!` for more info.
|
130
|
+
# @raise [ParseError] when the arguments can't be parsed
|
131
|
+
# @return [Hash{Symbol => Object}]
|
62
132
|
def parse(argv, strategy: nil)
|
63
133
|
argv = argv.dup
|
64
134
|
values = default_values
|
@@ -79,6 +149,10 @@ module Argy
|
|
79
149
|
raise ParseError.new(error)
|
80
150
|
end
|
81
151
|
|
152
|
+
# Validate the values
|
153
|
+
# @param values [Hash{Symbol => Object}]
|
154
|
+
# @return [Hash{Symbol => Object}]
|
155
|
+
# @raise [ValidationError] when the input is invalid
|
82
156
|
def validate!(values)
|
83
157
|
parameters.each do |param|
|
84
158
|
param.validate(values[param.name])
|
data/lib/argy/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Zane
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- ".gitignore"
|
63
63
|
- ".rspec"
|
64
64
|
- ".travis.yml"
|
65
|
+
- ".yardopts"
|
65
66
|
- CODE_OF_CONDUCT.md
|
66
67
|
- Gemfile
|
67
68
|
- Gemfile.lock
|