argy 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dff9d90b687d261bae2c0820b5ea7b7f812d472d
4
- data.tar.gz: 5543ca5b69b14891cbd8e1744df8b7b7480edcd0
3
+ metadata.gz: '01379049c1a1d66874589c09735fba37dbfbf39b'
4
+ data.tar.gz: fb593767af624cc2c3dc06ec32a8c2286fea7f9d
5
5
  SHA512:
6
- metadata.gz: 3ee7ec946a02ce9200fbf9318d708e5ae1a652092f9891050253e34b0ad628ba1aad81e0aa1431e655ebb20a1805b79d3e0800be67e9ed881cb7ad4a5c98673e
7
- data.tar.gz: 8372f49e4daca19886b4850bfd1e6f04929a81a6584af4c57babccc0a9aa561bf5eaac035147c786a555e954639fe6ad5b35b301d603514db388d91a185c21a8
6
+ metadata.gz: 3addec730a4dce220927c0518d52a1e2188fc27ff67de5ffddc89f0e91956b62dd31d7204968de26ff14b654e5b10cd9cc10f202a00f178e6a64819ce1f9b4f4
7
+ data.tar.gz: f034dc884c0b9bad616f2daedba4068cfcf1ea8adfc27862466e6afd2c80446b880e1a36e19b5a1e7bc44d588b71ce435bbf8565398da64b109dbb7942f7a381
@@ -1,18 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- argy (0.1.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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/argy`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Write usage instructions here
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
- ## Development
63
+ Argy supports the following option types:
28
64
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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/[USERNAME]/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.
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/[USERNAME]/argy/blob/master/CODE_OF_CONDUCT.md).
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).
@@ -3,16 +3,30 @@
3
3
  require "bundler/setup"
4
4
  require "argy"
5
5
 
6
- options = Argy.parse(ARGV) do |o|
6
+ parser = Argy.new do |o|
7
+ o.description "Prints messages"
7
8
  o.usage "example"
8
- o.description "A cool thing that does stuff"
9
- o.example "$ example foo"
10
- o.argument :jint, desc: "do a thing"
11
- o.option :fizz, required: true, desc: "blah"
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
- puts options
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
@@ -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
- MissingArgumentError = Class.new(Error)
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
@@ -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
- parameter(a.label, a.desc, a.required?, a.default)
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
- parameter(label.join(", "), o.desc, o.required?, o.default)
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
- parameter(flag.reverse.join(", "), desc)
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
@@ -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
@@ -1,3 +1,4 @@
1
+ require "pathname"
1
2
  require "argy/parameter"
2
3
 
3
4
  module Argy
@@ -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
- (arguments + options).reduce(unused_arguments: []) do |acc, opt|
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
- parser.parse!(argv)
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[:unused_arguments] << value
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
@@ -1,3 +1,3 @@
1
1
  module Argy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.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-06 00:00:00.000000000 Z
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