argument_parser 0.0.0 → 0.1.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/lib/argument_parser/version.rb +1 -1
- data/lib/argument_parser.rb +121 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5422411476cd13036bd0c77fe5d2a7dccdbfda4283c8291b02659277bebd14cd
|
4
|
+
data.tar.gz: 7cbc193dea73812eb5c280c842e79e7af3306a1fd8b4215e6d1ad391c2f3ffc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 903fdc56168e1a8f6e82e37c55f94b1bb1605e1d4e5575d6e62975932e7c454f2e48fda27dc5778d68a2666aa25670578e8ec7cfdfbe51947bccffdf43e9733a
|
7
|
+
data.tar.gz: '094e60864b261af857b88cc2bc8687d83325df3a2cc6cbf25804f5ba4984e38ef464033a305f9e35adbdeaa66ca7cf99859840af4d40926db8a5537542718df2'
|
data/lib/argument_parser.rb
CHANGED
@@ -3,4 +3,125 @@
|
|
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_pattern!(arg, rule.options)
|
23
|
+
|
24
|
+
result[rule.name] = arg
|
25
|
+
i += 1
|
26
|
+
in :optional
|
27
|
+
arg = validate_pattern!(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
|
+
validate_size(rest_args, rule.options)
|
34
|
+
rest_args.map! { |it| validate_pattern!(it, rule.options) }
|
35
|
+
|
36
|
+
result[rule.name] = rest_args
|
37
|
+
i = argv.size
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
argv.shift(i)
|
42
|
+
|
43
|
+
args
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def validate_pattern!(arg, options)
|
49
|
+
coerced_arg = coerce!(arg, options)
|
50
|
+
return coerced_arg unless options[:pattern]
|
51
|
+
return coerced_arg unless arg
|
52
|
+
return coerced_arg if options[:pattern] === coerced_arg
|
53
|
+
|
54
|
+
raise InvalidArgument, "invalid argument: #{arg}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_size(args, options)
|
58
|
+
if (min = options[:min])
|
59
|
+
raise InvalidArgument, "expected at least #{min} argument(s)" if args.size < min
|
60
|
+
end
|
61
|
+
|
62
|
+
if (max = options[:max])
|
63
|
+
raise InvalidArgument, "expected at most #{max} argument(s)" if args.size > max
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def coerce!(arg, options)
|
68
|
+
return arg unless arg
|
69
|
+
return arg unless options[:type]
|
70
|
+
|
71
|
+
if options[:type] == Integer
|
72
|
+
Integer(arg)
|
73
|
+
elsif options[:type] == Float
|
74
|
+
Float(arg)
|
75
|
+
elsif options[:type] == String
|
76
|
+
arg
|
77
|
+
else
|
78
|
+
raise SchemaError, "type not supported: #{options[:type]}"
|
79
|
+
end
|
80
|
+
rescue ArgumentError
|
81
|
+
raise InvalidArgument, "invalid argument: #{arg}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
module Schema
|
86
|
+
class Builder
|
87
|
+
def initialize
|
88
|
+
@current_stage = Schema::RequiredStage.new([])
|
89
|
+
end
|
90
|
+
|
91
|
+
def required(...) = @current_stage = @current_stage.required(...)
|
92
|
+
def optional(...) = @current_stage = @current_stage.optional(...)
|
93
|
+
def rest(...) = @current_stage = @current_stage.rest(...)
|
94
|
+
def build = @current_stage.build
|
95
|
+
end
|
96
|
+
|
97
|
+
Rule = Data.define(:kind, :name, :options)
|
98
|
+
|
99
|
+
RequiredStage = Data.define(:schema) do
|
100
|
+
def required(name, **opts)
|
101
|
+
self.class.new(schema + [Rule.new(:required, name, opts)])
|
102
|
+
end
|
103
|
+
|
104
|
+
def optional(name, **opts)
|
105
|
+
OptionalStage.new(schema + [Rule.new(:optional, name, opts)])
|
106
|
+
end
|
107
|
+
|
108
|
+
def rest(name, **opts)
|
109
|
+
RestStage.new(schema + [Rule.new(:rest, name, opts)])
|
110
|
+
end
|
111
|
+
|
112
|
+
def build = Parser.new(schema)
|
113
|
+
end
|
114
|
+
|
115
|
+
class OptionalStage < RequiredStage
|
116
|
+
def required(*) = raise SchemaError, "cannot add required arguments after optional/rest"
|
117
|
+
def optional(*) = raise SchemaError, "only one optional argument is allowed"
|
118
|
+
end
|
119
|
+
|
120
|
+
class RestStage < OptionalStage
|
121
|
+
def rest(*) = raise SchemaError, "only one rest argument is allowed"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def schema = Schema::RequiredStage.new([])
|
126
|
+
def build(&block) = Schema::Builder.new.instance_eval(&block).build
|
6
127
|
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.
|
4
|
+
version: 0.1.1
|
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-
|
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:
|