clingon 0.0.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 +7 -0
- data/README.md +218 -0
- data/lib/clingon.rb +151 -0
- data/lib/clingon/checks/checks.rb +34 -0
- data/lib/clingon/checks/type_regex.rb +6 -0
- data/lib/clingon/errors.rb +68 -0
- data/lib/clingon/helpers/input_store.rb +23 -0
- data/lib/clingon/helpers/parser_configuration.rb +43 -0
- data/lib/clingon/helpers/structure_checker.rb +24 -0
- data/lib/clingon/version.rb +3 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5abedd0654d50025ee7f73c7167dc19a37013edb
|
4
|
+
data.tar.gz: b84f98b0327be4704dd3d7269b9116e57606805c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40db83ed840a2090c225a728a47d2a054f672dad3baf60a283b85d8a1e4fbe6861c3ba7c6891e84b60cf51499a154c2e995a44d44fcbc1cb20bd5598942db120
|
7
|
+
data.tar.gz: 51578191d232fd15be7397712ee13203261d8dfc9318672d81409db4554e497751db9f0b3e5866fcb805f555283c2f1d081a2272c066bdbe17e6ffde3b65121e
|
data/README.md
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
# Clingon
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/clingon)
|
4
|
+
[](https://github.com/mardotio/clingon/issues)
|
5
|
+
[](https://rubygems.org/gems/clingon)
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
The clingon gem can be used to easily parse command line input from a user.
|
10
|
+
It can also be configured so that you can validate the inputs you receive. This
|
11
|
+
gem can be used to parse something like this:
|
12
|
+
|
13
|
+
```
|
14
|
+
--first_name bob --last_name smith --email bob.smith@email.com -h
|
15
|
+
```
|
16
|
+
|
17
|
+
into this:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
[
|
21
|
+
{
|
22
|
+
:name => 'first_name',
|
23
|
+
:value => 'bob'
|
24
|
+
},{
|
25
|
+
:name => 'last_name',
|
26
|
+
:value => 'smith'
|
27
|
+
},{
|
28
|
+
:name => 'email',
|
29
|
+
:value => 'bob.smith@email.com'
|
30
|
+
},{
|
31
|
+
:name => 'help',
|
32
|
+
:value => true
|
33
|
+
}
|
34
|
+
]
|
35
|
+
```
|
36
|
+
|
37
|
+
## Table of Contents
|
38
|
+
|
39
|
+
<!-- TOC -->
|
40
|
+
|
41
|
+
- [Clingon](#clingon)
|
42
|
+
- [Overview](#overview)
|
43
|
+
- [Installation](#installation)
|
44
|
+
- [Setup](#setup)
|
45
|
+
- [Name](#name)
|
46
|
+
- [Short Name](#short-name)
|
47
|
+
- [Required](#required)
|
48
|
+
- [Empty](#empty)
|
49
|
+
- [Type](#type)
|
50
|
+
- [Check](#check)
|
51
|
+
- [Values](#values)
|
52
|
+
- [Use](#use)
|
53
|
+
- [Configuration](#configuration)
|
54
|
+
- [Parsing](#parsing)
|
55
|
+
- [Accessing Values](#accessing-values)
|
56
|
+
- [Examples](#examples)
|
57
|
+
|
58
|
+
<!-- /TOC -->
|
59
|
+
|
60
|
+
## Installation
|
61
|
+
|
62
|
+
To install simply use Ruby's gem installer:
|
63
|
+
|
64
|
+
```
|
65
|
+
gem install clingon
|
66
|
+
```
|
67
|
+
|
68
|
+
## Setup
|
69
|
+
|
70
|
+
In order to use the library, you must provide a structure that defines all
|
71
|
+
of the values you expect. This structure is expected to be an array of hashes
|
72
|
+
containing all the options you want. Each hash can contain any of the following
|
73
|
+
options:
|
74
|
+
|
75
|
+
|Option|Expected Value|Required|
|
76
|
+
|------|--------------|:------:|
|
77
|
+
|name|string|*|
|
78
|
+
|short_name|string||
|
79
|
+
|required|boolean||
|
80
|
+
|empty|boolean||
|
81
|
+
|type|string (see below)||
|
82
|
+
|check|regex/string||
|
83
|
+
|values|array||
|
84
|
+
|
85
|
+
**All keys in each hash must be ruby symbols**
|
86
|
+
|
87
|
+
`values`, `type`, and `check` are all used to validate that the received values
|
88
|
+
match what you were expecting. The parser will only use one of these settings to
|
89
|
+
validate an input, so you should only define the of those values per input. If
|
90
|
+
more than one of these values are defined, the parser will use them in the
|
91
|
+
following order: `values`, `type`, `check`.
|
92
|
+
|
93
|
+
### Name
|
94
|
+
|
95
|
+
This value will be used as the long name for the command line flag. This value
|
96
|
+
must be defined in your structure for any value that you want to parse. This
|
97
|
+
value should be a `string`.
|
98
|
+
|
99
|
+
### Short Name
|
100
|
+
|
101
|
+
The value will be used to create a shortened version of the flag. It is an
|
102
|
+
optional value, and it is recommended that it be a single character if possible,
|
103
|
+
but there is no limit on length.
|
104
|
+
|
105
|
+
### Required
|
106
|
+
|
107
|
+
Specifies if the flag must be present. If the flag is not found when parsing,
|
108
|
+
it will throw an error. This value is optional, but if defined, value must
|
109
|
+
be either `true` or `false`; defaults to `false`.
|
110
|
+
|
111
|
+
### Empty
|
112
|
+
|
113
|
+
This can be used if the flag does not require any value and is simply an option
|
114
|
+
marker (i.e -r for recursive or -h for help). This value is optional, but if
|
115
|
+
defined, value must be either `true` or `false`; defaults to `false`.
|
116
|
+
|
117
|
+
The `empty` flag is used for flags that don't need an additional value. It is
|
118
|
+
essentially a boolean value (`false` if absent `true` is present). If a value is
|
119
|
+
required it should not have the `empty` flag. Required values that have and
|
120
|
+
`empty` flag will simply ignore the `empty` option.
|
121
|
+
|
122
|
+
### Type
|
123
|
+
|
124
|
+
This option allows you to define what type of value the flag is expecting. If
|
125
|
+
the received value does not match the expected type an error will be thrown.
|
126
|
+
Currently supported types are:
|
127
|
+
|
128
|
+
|Type|Description|
|
129
|
+
|----|--------|
|
130
|
+
|num|Any number, integer or float|
|
131
|
+
|int|Any integer|
|
132
|
+
|float|A decimal number|
|
133
|
+
|bool|`true` or `false`|
|
134
|
+
|
135
|
+
Additionally, when the values are parsed, the user input will be converted to
|
136
|
+
the specified type (int, float, bool). If `num` is specified, input will be
|
137
|
+
converted to either `float` or `int`. When specified in your structure, the type
|
138
|
+
must be specified as a string.
|
139
|
+
|
140
|
+
### Check
|
141
|
+
|
142
|
+
Regular expression that should be used to check the input value against. This
|
143
|
+
can be a string (it will be converted to a regular expression), or a a regular
|
144
|
+
expression (i.e. `/^\d+$/`). If the received value does not match the specified
|
145
|
+
regex, an error will be thrown.
|
146
|
+
|
147
|
+
**If using a YAML configuration file, it is recommended that you use single
|
148
|
+
quotes (`'`) when specifing a regular expression. Not doing so may cause the
|
149
|
+
YAML parser to interpret some of the charaters as escape charaters.**
|
150
|
+
|
151
|
+
### Values
|
152
|
+
|
153
|
+
An array of values that are acceptable for the flag. All elements of the array
|
154
|
+
should be strings since all inputs from a terminal are received by ruby as
|
155
|
+
strings. If the received value is not a member of the array, an error will be
|
156
|
+
thown.
|
157
|
+
|
158
|
+
## Use
|
159
|
+
|
160
|
+
### Configuration
|
161
|
+
|
162
|
+
To use the parser, you must first configure the library with your structure and
|
163
|
+
the inputs you wish to parse. There are four values you can configure.
|
164
|
+
|
165
|
+
|Setting|Description|Value|Required|
|
166
|
+
|-------|-----------|-----|:------:|
|
167
|
+
|structure|The structure to be used|Array|*|
|
168
|
+
|inputs|The inputs you need to parse|Array|*|
|
169
|
+
|delimiter|Delimiter for the flags (defaults to `-`)|String||
|
170
|
+
|strict|Whether parser should accept inputs that look like flags|Bool||
|
171
|
+
|
172
|
+
Optionally, you can use a YAML configuration file to set some or all of these
|
173
|
+
values (at the minimum, the file should contain the structure). To use this
|
174
|
+
option, pass a relative or absolute path to a YAML file. The parser expects to
|
175
|
+
find the same values as the table above as sybols (i.e `:structure`, `:strict`).
|
176
|
+
The only value that cannot be configured through the file are the inputs. To
|
177
|
+
use a file to configure the parser, just do:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
Clingon.configure do |c|
|
181
|
+
c.conf_file = 'conf_file.yaml'
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
### Parsing
|
186
|
+
|
187
|
+
After you have configured the parser, you simply need to call the `parse`
|
188
|
+
method.
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
Clingon.parse
|
192
|
+
```
|
193
|
+
|
194
|
+
### Accessing Values
|
195
|
+
|
196
|
+
The parser has a `fetch` method that allows you to retrieve one or all of the
|
197
|
+
parsed values. To access the parsed values, simply call the method with the
|
198
|
+
value you want, or leave the arguments empty if you want to retrive all values.
|
199
|
+
|
200
|
+
if you query for a specific value, you must use the `name` that was used in the
|
201
|
+
configuration structure.
|
202
|
+
|
203
|
+
```ruby
|
204
|
+
# This will return all parsed values as an array of hashes
|
205
|
+
all_values = Clingon.fetch
|
206
|
+
|
207
|
+
# This will return a hash containing the value that was requested, or nil if the
|
208
|
+
# value was not found
|
209
|
+
name = Clingon.fetch('name')
|
210
|
+
```
|
211
|
+
|
212
|
+
## Examples
|
213
|
+
|
214
|
+
[`structure.yaml`](/examples/structure.yaml) contains a structure in YAML
|
215
|
+
format. [`example_1.rb`](/examples/example_1.rb) makes use of the YAML file
|
216
|
+
configuration file. If you are not interested in using a YAML configuration
|
217
|
+
file, and instead want to define your structure within your script,
|
218
|
+
[`example_2.rb`](/examples/example_2.rb) defines an inline structure.
|
data/lib/clingon.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'clingon/errors'
|
2
|
+
require 'clingon/version'
|
3
|
+
require 'clingon/helpers/input_store'
|
4
|
+
require 'clingon/helpers/structure_checker'
|
5
|
+
require 'clingon/checks/checks'
|
6
|
+
require 'clingon/helpers/parser_configuration'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
module Clingon
|
10
|
+
class << self
|
11
|
+
attr_accessor :conf, :store, :reserved
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.configure
|
15
|
+
self.store ||= InputStore.new
|
16
|
+
self.conf ||= ParserConfiguration.new
|
17
|
+
yield(conf)
|
18
|
+
self.reserved = conf.structure.inject([]) do |all, current|
|
19
|
+
arr = ["#{conf.delimiter * 2}#{current[:name]}"]
|
20
|
+
arr << "#{conf.delimiter}#{current[:short_name]}" if current[:short_name]
|
21
|
+
all + arr
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fetch(value = nil)
|
26
|
+
if value
|
27
|
+
store.fetch(value)
|
28
|
+
else
|
29
|
+
store.inputs
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.strict_parse
|
34
|
+
cli_inputs = conf.inputs.clone
|
35
|
+
cli_inputs.each do |input|
|
36
|
+
if input =~ /^#{conf.delimiter}{1,2}/ && !Clingon.reserved?(input)
|
37
|
+
raise(ReservedKeywordError.new(received: input, reserved: [/^-{1,2}/]))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.parse
|
43
|
+
Clingon.strict_parse if conf.strict
|
44
|
+
required_values = Clingon.get_required
|
45
|
+
Clingon.parse_required(required_values)
|
46
|
+
optional_values = Clingon.get_optional
|
47
|
+
Clingon.parse_optional(optional_values)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.get_required_value(flag)
|
51
|
+
name = "#{conf.delimiter * 2}#{flag[:name]}"
|
52
|
+
short_name = "#{conf.delimiter}#{flag[:short_name]}" if flag[:short_name]
|
53
|
+
index = conf.inputs.index(short_name) if short_name
|
54
|
+
index ||= conf.inputs.index(name)
|
55
|
+
raise(MissingArgumentError.new(name: name, short_name: short_name)) unless index
|
56
|
+
conf.inputs[index + 1]
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.get_optional_value(flag)
|
60
|
+
empty = flag[:empty]
|
61
|
+
name = "#{conf.delimiter * 2}#{flag[:name]}"
|
62
|
+
short_name = "#{conf.delimiter}#{flag[:short_name]}" if flag[:short_name]
|
63
|
+
index = conf.inputs.index(short_name) if short_name
|
64
|
+
index ||= conf.inputs.index(name)
|
65
|
+
if index && empty
|
66
|
+
true
|
67
|
+
elsif empty
|
68
|
+
false
|
69
|
+
elsif index
|
70
|
+
conf.inputs[index + 1]
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.get_required
|
77
|
+
conf.structure.select { |flag| flag[:required] }
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.get_optional
|
81
|
+
conf.structure.reject { |flag| flag[:required] }
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.reserved?(value)
|
85
|
+
reserved.include?(value)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.convert_to_type(value, type)
|
89
|
+
value_to_convert = value.to_s
|
90
|
+
case type
|
91
|
+
when 'int'
|
92
|
+
value_to_convert.to_i
|
93
|
+
when 'float'
|
94
|
+
value_to_convert.to_f
|
95
|
+
when 'num'
|
96
|
+
if value_to_convert =~ /^\d+$/
|
97
|
+
value_to_convert.to_i
|
98
|
+
else
|
99
|
+
value_to_convert.to_f
|
100
|
+
end
|
101
|
+
when 'bool'
|
102
|
+
value_to_convert == 'true'
|
103
|
+
else
|
104
|
+
value_to_convert
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.parse_required(required_structure)
|
109
|
+
required_structure.each do |flag|
|
110
|
+
check = flag[:check]
|
111
|
+
type = flag[:type]
|
112
|
+
allowed_values = flag[:values]
|
113
|
+
user_input = Clingon.get_required_value(flag)
|
114
|
+
if Clingon.reserved?(user_input)
|
115
|
+
raise(ReservedKeywordError.new(received: user_input, reserved: reserved))
|
116
|
+
end
|
117
|
+
if allowed_values
|
118
|
+
Clingon.check_allowed_value(user_input, allowed_values)
|
119
|
+
elsif type
|
120
|
+
Clingon.check_against_type(user_input, type)
|
121
|
+
elsif check
|
122
|
+
Clingon.check_against_regex(user_input, check)
|
123
|
+
end
|
124
|
+
store.store(flag[:name], user_input)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.parse_optional(optional_structure)
|
129
|
+
optional_structure.each do |flag|
|
130
|
+
check = flag[:check]
|
131
|
+
type = flag[:type]
|
132
|
+
allowed_values = flag[:values]
|
133
|
+
empty = flag[:empty]
|
134
|
+
user_input = Clingon.get_optional_value(flag)
|
135
|
+
if user_input && !empty
|
136
|
+
if Clingon.reserved?(user_input)
|
137
|
+
raise(ReservedKeywordError.new(received: user_input, reserved: reserved))
|
138
|
+
end
|
139
|
+
if allowed_values
|
140
|
+
Clingon.check_allowed_value(user_input, allowed_values)
|
141
|
+
elsif type
|
142
|
+
Clingon.check_against_type(user_input, type)
|
143
|
+
user_input = Clingon.convert_to_type(user_input, type)
|
144
|
+
elsif check
|
145
|
+
Clingon.check_against_regex(user_input, check)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
store.store(flag[:name], user_input)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'clingon/checks/type_regex'
|
2
|
+
|
3
|
+
module Clingon
|
4
|
+
def self.check_against_type(value, type)
|
5
|
+
case type
|
6
|
+
when 'int'
|
7
|
+
check = Clingon::INT.dup
|
8
|
+
when 'float'
|
9
|
+
check = Clingon::FLOAT.dup
|
10
|
+
when 'num'
|
11
|
+
check = Clingon::NUM.dup
|
12
|
+
when 'bool'
|
13
|
+
check = Clingon::BOOL.dup
|
14
|
+
else
|
15
|
+
raise(UnexpectedTypeError.new(received: type))
|
16
|
+
end
|
17
|
+
|
18
|
+
value_to_check = value.to_s
|
19
|
+
|
20
|
+
return if value_to_check =~ check
|
21
|
+
raise(TypeMatchError.new(expected: type, received: value))
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.check_against_regex(value, check)
|
25
|
+
regex_check = Regexp.new(check)
|
26
|
+
return if value =~ regex_check
|
27
|
+
raise(MatchError.new(expected: regex_check, received: value))
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.check_allowed_value(value, allowed)
|
31
|
+
return if allowed.index(value)
|
32
|
+
raise(UnexpectedValueError.new(expected: allowed, received: value))
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Clingon
|
2
|
+
class ConfigurationFileError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class YAMLSyntaxError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class MatchError < StandardError
|
9
|
+
attr_reader :expected, :received
|
10
|
+
def initialize(payload)
|
11
|
+
@expected = payload[:expected]
|
12
|
+
@received = payload[:received]
|
13
|
+
msg = "Value #{received} does not match #{expected}"
|
14
|
+
super(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MissingArgumentError < StandardError
|
19
|
+
attr_reader :name, :short_name
|
20
|
+
def initialize(payload)
|
21
|
+
@name = payload[:name]
|
22
|
+
@short_name = payload[:short_name]
|
23
|
+
name_arr = [name]
|
24
|
+
name_arr << short_name if short_name
|
25
|
+
msg = "Missing required input #{name_arr.join('/')}"
|
26
|
+
super(msg)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class UnexpectedValueError < StandardError
|
31
|
+
attr_reader :expected, :received
|
32
|
+
def initialize(payload)
|
33
|
+
@expected = payload[:expected]
|
34
|
+
@received = payload[:received]
|
35
|
+
msg = "Received #{received}, expected one of (#{expected.join(', ')})"
|
36
|
+
super(msg)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class UnexpectedTypeError < StandardError
|
41
|
+
attr_reader :received
|
42
|
+
def initialize(payload)
|
43
|
+
@received = payload[:received]
|
44
|
+
msg = "Type #{received} is not valid"
|
45
|
+
super(msg)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class TypeMatchError < StandardError
|
50
|
+
attr_reader :expected, :received
|
51
|
+
def initialize(payload)
|
52
|
+
@expected = payload[:expected]
|
53
|
+
@received = payload[:received]
|
54
|
+
msg = "Received #{received}, expected type #{expected}"
|
55
|
+
super(msg)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class ReservedKeywordError < StandardError
|
60
|
+
attr_reader :received, :reserved
|
61
|
+
def initialize(payload)
|
62
|
+
@received = payload[:received]
|
63
|
+
@reserved = payload[:reserved]
|
64
|
+
msg = "Value #{received} is a reserved keyword"
|
65
|
+
super(msg)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class InputStore
|
2
|
+
attr_reader :inputs
|
3
|
+
def initialize
|
4
|
+
@inputs = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def store(name, value)
|
8
|
+
@inputs << {
|
9
|
+
name: name,
|
10
|
+
value: value
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(value)
|
15
|
+
inputs.inject(nil) do |val, current|
|
16
|
+
if current[:name] == value
|
17
|
+
current
|
18
|
+
else
|
19
|
+
val
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Clingon
|
2
|
+
class ParserConfiguration
|
3
|
+
attr_accessor :inputs, :delimiter, :strict
|
4
|
+
attr_reader :conf_file, :structure
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@delimiter = '-'
|
8
|
+
@strict = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def conf_file=(file)
|
12
|
+
unless File.exist?(file)
|
13
|
+
msg = "Configuration file (#{file}) does not exist"
|
14
|
+
raise(Clingon::ConfigurationFileError, msg)
|
15
|
+
end
|
16
|
+
if File.directory?(file)
|
17
|
+
msg = "Configuration file (#{file}) is a directory"
|
18
|
+
raise(Clingon::ConfigurationFileError, msg)
|
19
|
+
end
|
20
|
+
if File.zero?(file)
|
21
|
+
msg = "Configuration file (#{file}) is empty"
|
22
|
+
raise(Clingon::ConfigurationFileError, msg)
|
23
|
+
end
|
24
|
+
begin
|
25
|
+
yaml_contents = YAML.load_file(file)
|
26
|
+
rescue Psych::SyntaxError => e
|
27
|
+
raise(Clingon::YAMLSyntaxError, e)
|
28
|
+
end
|
29
|
+
if yaml_contents.key?(:structure)
|
30
|
+
self.structure = yaml_contents[:structure]
|
31
|
+
else
|
32
|
+
msg = "Configuration file (#{file}) must contain :structure key"
|
33
|
+
raise(Clingon::ConfigurationFileError, msg)
|
34
|
+
end
|
35
|
+
self.strict = yaml_contents[:strict] if yaml_contents.key?(:strict)
|
36
|
+
self.delimiter = yaml_contents[:delimiter] if yaml_contents.key?(:delimiter)
|
37
|
+
end
|
38
|
+
|
39
|
+
def structure=(struct)
|
40
|
+
@structure = StructureChecker.check(struct)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module StructureChecker
|
2
|
+
def self.check(structure)
|
3
|
+
raise('Structure must be an array') unless structure.instance_of?(Array)
|
4
|
+
StructureChecker.verify_contents(structure)
|
5
|
+
structure
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.verify_contents(structure)
|
9
|
+
structure.each do |el|
|
10
|
+
raise('Each element of structure must contain name key') unless el[:name]
|
11
|
+
if el[:type]
|
12
|
+
valid = [
|
13
|
+
'int',
|
14
|
+
'float',
|
15
|
+
'num',
|
16
|
+
'bool'
|
17
|
+
]
|
18
|
+
unless valid.include?(el[:type])
|
19
|
+
raise("Valid types are: #{valid.join(', ')}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clingon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mario Lopez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |-
|
14
|
+
Clingon is a parser for command line inputs. It can help you parse flags,
|
15
|
+
and options for your script, as well as convert user inputs to specific ruby
|
16
|
+
types. With clingon you can forget about dealing with user inputs, and focus
|
17
|
+
on adding functionality to your scripts.
|
18
|
+
email: lopezrobles.mario@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files:
|
22
|
+
- README.md
|
23
|
+
files:
|
24
|
+
- README.md
|
25
|
+
- lib/clingon.rb
|
26
|
+
- lib/clingon/checks/checks.rb
|
27
|
+
- lib/clingon/checks/type_regex.rb
|
28
|
+
- lib/clingon/errors.rb
|
29
|
+
- lib/clingon/helpers/input_store.rb
|
30
|
+
- lib/clingon/helpers/parser_configuration.rb
|
31
|
+
- lib/clingon/helpers/structure_checker.rb
|
32
|
+
- lib/clingon/version.rb
|
33
|
+
homepage: https://github.com/mardotio/clingon
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 2.4.5.2
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: Flexible command line parser.
|
57
|
+
test_files: []
|