argument_parser 0.0.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de34c01a224dda66a54884deaf0818e83855515d33281a8b7191a96e27c8f987
4
- data.tar.gz: 8ae1418b2bdeb6c9fb25b339e3cc70e335d91bc42de9871f1e889c789303d1dc
3
+ metadata.gz: feb0e8be78d5fc392980f1ac65520b131c34641207cc31b11d05badb7edf7fcc
4
+ data.tar.gz: a74b6300dec4d61257f941e57ff93cd7106190da441d1f09da621e6025f35320
5
5
  SHA512:
6
- metadata.gz: 7ad9f308dd95fceb6bae98c97d65075312fb0133937fd8367ab37d04188ab061d5ae640926f805433f916468ef88adc287ae810bfaf55937b7a35ed0f0cd1683
7
- data.tar.gz: 6fb21b3496c06b8ab9ce58ee60071e6f703c0edfbbf371b4d50affb0b73bd1f4ffbfb58706e138e29310a88d359d796dd0485639989c5edd3eda7e718cf494ab
6
+ metadata.gz: 9ad1572e3a661121609cfeffed61b1654bdbb94862e317944a5a1c1da9317b6315c5a6219258743275b670bb9c002ddee4188059526e1b2b55a333c34c2b1d0d
7
+ data.tar.gz: 9656697885fe68d0de72bcf459796f2cf16cb85c94aff6d258ac9ad595a2ccd6f92615f0eb419f6f7068c4e47d8a080013143bf63e994e0cb8813776b85fd76f
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArgumentParser
4
- VERSION = "0.0.0"
4
+ VERSION = "0.1.0"
5
5
  end
@@ -3,4 +3,114 @@
3
3
  require_relative "argument_parser/version"
4
4
 
5
5
  module ArgumentParser
6
+ extend self
7
+
8
+ Error = Class.new(StandardError)
9
+ SchemaError = Class.new(Error)
10
+ MissingArgument = Class.new(Error)
11
+ InvalidArgument = Class.new(Error)
12
+
13
+ class Parser < Data.define(:schema)
14
+ def parse!(argv = ARGV)
15
+ i = 0
16
+
17
+ args = schema.each_with_object({}) do |rule, result|
18
+ case rule.kind
19
+ in :required
20
+ arg = argv[i]
21
+ raise MissingArgument, "missing required argument: #{rule.name}" if arg.nil?
22
+ arg = validate!(arg, rule.options)
23
+
24
+ result[rule.name] = arg
25
+ i += 1
26
+ in :optional
27
+ arg = validate!(argv[i], rule.options)
28
+
29
+ result[rule.name] = arg || rule.options[:default]
30
+ i += 1 if arg
31
+ in :rest
32
+ rest_args = argv.dup[i..] || []
33
+ rest_args.map! { |it| validate!(it, rule.options) }
34
+
35
+ result[rule.name] = rest_args
36
+ i = argv.size
37
+ end
38
+ end
39
+
40
+ argv.shift(i)
41
+
42
+ args
43
+ end
44
+
45
+ private
46
+
47
+ def validate!(arg, options)
48
+ coerced_arg = coerce!(arg, options)
49
+ return coerced_arg unless options[:pattern]
50
+ return coerced_arg unless arg
51
+ return coerced_arg if options[:pattern] === coerced_arg
52
+
53
+ raise InvalidArgument, "invalid argument: #{arg}"
54
+ end
55
+
56
+ def coerce!(arg, options)
57
+ return arg unless arg
58
+ return arg unless options[:type]
59
+
60
+ if options[:type] == Integer
61
+ Integer(arg)
62
+ elsif options[:type] == Float
63
+ Float(arg)
64
+ elsif options[:type] == String
65
+ arg
66
+ else
67
+ raise SchemaError, "type not supported: #{options[:type]}"
68
+ end
69
+ rescue ArgumentError
70
+ raise InvalidArgument, "invalid argument: #{arg}"
71
+ end
72
+ end
73
+
74
+ module Schema
75
+ class Builder
76
+ def initialize
77
+ @current_stage = Schema::RequiredStage.new([])
78
+ end
79
+
80
+ def required(...) = @current_stage = @current_stage.required(...)
81
+ def optional(...) = @current_stage = @current_stage.optional(...)
82
+ def rest(...) = @current_stage = @current_stage.rest(...)
83
+ def build = @current_stage.build
84
+ end
85
+
86
+ Rule = Data.define(:kind, :name, :options)
87
+
88
+ RequiredStage = Data.define(:schema) do
89
+ def required(name, **opts)
90
+ self.class.new(schema + [Rule.new(:required, name, opts)])
91
+ end
92
+
93
+ def optional(name, **opts)
94
+ OptionalStage.new(schema + [Rule.new(:optional, name, opts)])
95
+ end
96
+
97
+ def rest(name, **opts)
98
+ RestStage.new(schema + [Rule.new(:rest, name, opts)])
99
+ end
100
+
101
+ def build = Parser.new(schema)
102
+ end
103
+
104
+ class OptionalStage < RequiredStage
105
+ def required(*) = raise SchemaError, "cannot add required arguments after optional/rest"
106
+ def optional(*) = raise SchemaError, "only one optional argument is allowed"
107
+ end
108
+
109
+ class RestStage < OptionalStage
110
+ def rest(*) = raise SchemaError, "only one rest argument is allowed"
111
+ end
112
+ end
113
+
114
+ def schema = Schema::RequiredStage.new([])
115
+ def build(&block) = Schema::Builder.new.instance_eval(&block).build
6
116
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: argument_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matheus Richard
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-16 00:00:00.000000000 Z
11
+ date: 2025-09-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parse command line arguments with like you parse options with OptionParser.
14
14
  email: