argser 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +186 -0
- data/examples/greetings.rb +51 -0
- data/lib/argser/parser.rb +300 -0
- data/lib/argser.rb +10 -0
- metadata +59 -0
data/README.md
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
# INTRODUCTION
|
2
|
+
|
3
|
+
Argser (from "ARGuments parSER") is a library that aims to simplify the process of parsing arguments in command line scripts written in Ruby. It provides an easy way to specify which parameters are valid, their type or format, error conditions, description, etc. In that way, it reduces the need to write code specificaly to parse and validate such arguments.
|
4
|
+
|
5
|
+
The idea is pretty simple. To be able to use the arguments passed when the script was executed in a easy and consistent way, you only need to specify some general options for the application, a list of parameters and some properties that must hold for both, parameters and what is called the 'remaining array' (an array with strings that don't belong to any parameter).
|
6
|
+
|
7
|
+
# INSTALLATION
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install argser
|
11
|
+
```
|
12
|
+
|
13
|
+
# USAGE
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'argser'
|
17
|
+
|
18
|
+
Argser::Parser.new({
|
19
|
+
options: {...general options...},
|
20
|
+
params: {...parameters options...},
|
21
|
+
remaining: {...remaining array options...}
|
22
|
+
})
|
23
|
+
```
|
24
|
+
|
25
|
+
## GENERAL OPTIONS
|
26
|
+
|
27
|
+
- <code>:description</code>, a string containing the description of the application (default: "")
|
28
|
+
- <code>:usage</code>, a string describing how to use the application (default: "")
|
29
|
+
- <code>:details</code>, a string containing details about the application (default: "")
|
30
|
+
- <code>:info</code>, a string printer bellow errors indicating how to find more information about them (default: "For more information try '--help'")
|
31
|
+
- <code>:unknown</code>, a string with the message to show when a parameter is not known (default: "Unknown parameter '$p'")
|
32
|
+
- <code>:fatal</code>, a string with the message to show when an internal error is found while parsing parameters (default: "An internal error was found")
|
33
|
+
- <code>:help</code>, a boolean value indicating if the parser should automatically display the help if parameter :help is given (default: true)
|
34
|
+
|
35
|
+
## PARAMETERS OPTIONS
|
36
|
+
|
37
|
+
- <code>:shortcut</code>, a symbol used as a shortcut for this parameter (default: nil)
|
38
|
+
- <code>:type</code>, symbol indicating the type of this parameter (default: :string)
|
39
|
+
- <code>:default</code>, the default value if not other value is provided (default: '')
|
40
|
+
- <code>:required</code>, a boolean value indicating if this parameter is required or not
|
41
|
+
- <code>:sanitize</code>, a function to sanitize the value given (return the identifier of a message to show it or the sanitized value the parser should save)
|
42
|
+
- <code>:callback</code>, a function to call to do something with the parameter
|
43
|
+
- <code>:messages</code> A hash with all available messages to show where the key is used as an identifier (:help, :type and :required are created by default)
|
44
|
+
|
45
|
+
## REMAINING ARRAY OPTIONS
|
46
|
+
|
47
|
+
- <code>:type</code>, a symbol indicating the type of this parameter (default: :string)
|
48
|
+
- <code>:default</code>, the default value if not other value is provided (default: '')
|
49
|
+
- <code>:minimum</code>, minimum number of strings allowed
|
50
|
+
- <code>:maximum</code>, maximum number of strings allowed
|
51
|
+
- <code>:sanitize</code>, a function to sanitize the value given (return the identifier of a message to show it or the sanitized value the parser should save)
|
52
|
+
- <code>:callback</code>, a function to call to do something with the parameter
|
53
|
+
- <code>:messages</code>, hash with all available messages to show where the key is used as an identifier (:help, :type and :required are created by default)
|
54
|
+
|
55
|
+
## AVAILABLE TYPES
|
56
|
+
|
57
|
+
Here is the list of types:
|
58
|
+
|
59
|
+
- <code>:integer</code>, integer value (default: 0)
|
60
|
+
- <code>:float</code>, float value (default: 0.0)
|
61
|
+
- <code>:boolean</code>, boolean value (default: false)
|
62
|
+
- <code>:alpanumeric</code>, letters and numbers (default: '')
|
63
|
+
- <code>:letters</code>, letters (default: '')
|
64
|
+
- <code>:words</code>, words (default: '')
|
65
|
+
- <code>:range</code>, integer range (default: [0, 0])
|
66
|
+
- <code>:interval</code>, float range (default: [0.0, 0.0])
|
67
|
+
- <code>:string</code>, string (default: '')
|
68
|
+
|
69
|
+
The default type is <code>:string</code>
|
70
|
+
|
71
|
+
# EXAMPLE
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require '../lib/argser/parser.rb'
|
75
|
+
|
76
|
+
parser = Argser::Parser.new({
|
77
|
+
options: {
|
78
|
+
description: "This is a greeting application",
|
79
|
+
usage: "greeting [OPTIONS] NAME",
|
80
|
+
details: "Provided your age and your name, this application will greet you in a unique way.",
|
81
|
+
info: "For more information contact me at foo@/dev/null.com or try '--help'",
|
82
|
+
unknown: "What's '$p'?",
|
83
|
+
fatal: "There has been a weird error!!",
|
84
|
+
help: true
|
85
|
+
},
|
86
|
+
params: {
|
87
|
+
age: {
|
88
|
+
shortcut: :a,
|
89
|
+
default: 18,
|
90
|
+
type: :integer,
|
91
|
+
sanitize: lambda {|value, default| (value >= 18) ? value : :young},
|
92
|
+
messages: {
|
93
|
+
help: "Specify your age",
|
94
|
+
type: "I can't believe you're '$v' years old",
|
95
|
+
young: "You can't use this application unless you're older than 18!"
|
96
|
+
}
|
97
|
+
}
|
98
|
+
},
|
99
|
+
remaining: {
|
100
|
+
type: /[A-Z][A-Za-z]+\s[A-Z][A-Za-z]+/,
|
101
|
+
minimum: 1,
|
102
|
+
maximum: 1,
|
103
|
+
callback: lambda {|values, default| puts "Alright, I got your name!"},
|
104
|
+
messages: {
|
105
|
+
help: "Specify your name and surname",
|
106
|
+
type: "What!? Your name is '$v'!?"
|
107
|
+
}
|
108
|
+
}
|
109
|
+
})
|
110
|
+
|
111
|
+
parser.parse(ARGV)
|
112
|
+
|
113
|
+
comment = ''
|
114
|
+
if (parser.param? :age)
|
115
|
+
comment = case parser.param(:age)
|
116
|
+
when 18..20 then "you're a teenager!"
|
117
|
+
when 21..30 then "you're a young man!"
|
118
|
+
when 30..99 then "you're a little adult!"
|
119
|
+
end
|
120
|
+
else
|
121
|
+
comment = 'how old are you?'
|
122
|
+
end
|
123
|
+
|
124
|
+
puts "What's up #{parser.remaining[0]}? #{comment}"
|
125
|
+
```
|
126
|
+
|
127
|
+
## TESTS
|
128
|
+
|
129
|
+
```bash
|
130
|
+
$ ruby greetings.rb --help
|
131
|
+
```
|
132
|
+
```
|
133
|
+
This is a greeting application
|
134
|
+
|
135
|
+
greeting [OPTIONS] NAME
|
136
|
+
|
137
|
+
-a --age Specify your age
|
138
|
+
-h --help Display this help and exit
|
139
|
+
|
140
|
+
Provided your age and your name, this application will greet you in a unique way.
|
141
|
+
```
|
142
|
+
|
143
|
+
```bash
|
144
|
+
$ ruby greetings.rb --age 20
|
145
|
+
```
|
146
|
+
```
|
147
|
+
Incorrect number of remaining arguments
|
148
|
+
For more information contact me at foo@/dev/null.com or try '--help'
|
149
|
+
```
|
150
|
+
|
151
|
+
```bash
|
152
|
+
$ ruby greetings.rb --age 10 "Dummy Name"
|
153
|
+
```
|
154
|
+
```
|
155
|
+
You can't use this application unless you're older than 18!
|
156
|
+
For more information contact me at foo@/dev/null.com or try '--help'
|
157
|
+
```
|
158
|
+
|
159
|
+
```bash
|
160
|
+
$ ruby greetings.rb --age 20 "Dummy Name" "Another Name"
|
161
|
+
```
|
162
|
+
```
|
163
|
+
Incorrect number of remaining arguments
|
164
|
+
For more information contact me at foo@/dev/null.com or try '--help'
|
165
|
+
```
|
166
|
+
|
167
|
+
```bash
|
168
|
+
$ ruby greetings.rb --age 20 "Dummy Name"
|
169
|
+
```
|
170
|
+
```
|
171
|
+
Alright, I got your name!
|
172
|
+
What's up Dummy Name? you're a teenager!
|
173
|
+
```
|
174
|
+
|
175
|
+
```bash
|
176
|
+
$ ruby greetings.rb "Dummy Name" --age 25
|
177
|
+
```
|
178
|
+
```
|
179
|
+
Alright, I got your name!
|
180
|
+
What's up Dummy Name? you're a young man!
|
181
|
+
```
|
182
|
+
|
183
|
+
# AUTHOR
|
184
|
+
|
185
|
+
Matías Parodi © 2013
|
186
|
+
mparodilabs@gmail.com
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require '../lib/argser/parser.rb'
|
2
|
+
|
3
|
+
parser = Argser::Parser.new({
|
4
|
+
options: {
|
5
|
+
description: "This is a greeting application",
|
6
|
+
usage: "greeting [OPTIONS] NAME",
|
7
|
+
details: "Provided your age and your name, this application will greet you in a unique way.",
|
8
|
+
info: "For more information contact me at foo@/dev/null.com or try '--help'",
|
9
|
+
unknown: "What's '$p'?",
|
10
|
+
fatal: "There has been a weird error!!",
|
11
|
+
help: true
|
12
|
+
},
|
13
|
+
params: {
|
14
|
+
age: {
|
15
|
+
shortcut: :a,
|
16
|
+
default: 18,
|
17
|
+
type: :integer,
|
18
|
+
sanitize: lambda {|value, default| (value >= 18) ? value : :young},
|
19
|
+
messages: {
|
20
|
+
help: "Specify your age",
|
21
|
+
type: "I can't believe you're '$v' years old",
|
22
|
+
young: "You can't use this application unless you're older than 18!"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
},
|
26
|
+
remaining: {
|
27
|
+
type: /[A-Z][A-Za-z]+\s[A-Z][A-Za-z]+/,
|
28
|
+
minimum: 1,
|
29
|
+
maximum: 1,
|
30
|
+
callback: lambda {|values, default| puts "Alright, I got your name!"},
|
31
|
+
messages: {
|
32
|
+
help: "Specify your name and surname",
|
33
|
+
type: "What!? Your name is '$v'!?"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
})
|
37
|
+
|
38
|
+
parser.parse(ARGV)
|
39
|
+
|
40
|
+
comment = ''
|
41
|
+
if (parser.param? :age)
|
42
|
+
comment = case parser.param(:age)
|
43
|
+
when 18..20 then "you're a teenager!"
|
44
|
+
when 21..30 then "you're a young man!"
|
45
|
+
when 30..99 then "you're a little adult!"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
comment = 'how old are you?'
|
49
|
+
end
|
50
|
+
|
51
|
+
puts "What's up #{parser.remaining[0]}? #{comment}"
|
@@ -0,0 +1,300 @@
|
|
1
|
+
module Argser
|
2
|
+
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
@tokens
|
6
|
+
@options
|
7
|
+
@params
|
8
|
+
@remaining
|
9
|
+
|
10
|
+
#Available types (:integer, :float, :boolean, :alpanumeric, :letters, :words, :range, :interval and :string)
|
11
|
+
TYPES = {
|
12
|
+
integer: [/^\s*\d+\s*$/, lambda {|value, match, default| value.to_i || 0}],
|
13
|
+
float: [/^\s*\d+\.\d+\s*$/, lambda {|value, match, default| value.to_f || 0.0}],
|
14
|
+
boolean: [/^\s*$/, lambda {|value, match, default| !default || false}],
|
15
|
+
letters: [/^\s*[A-Za-z]+\s*$/, lambda {|value, match, default| (!default) ? value.strip : (value || '').strip}],
|
16
|
+
alphanumeric: [/^\s*\w+\s*$/, lambda {|value, match, default| (!default) ? value.strip : (value || '').strip}],
|
17
|
+
words: [/^\s*[A-Za-z]+(?:\s+[A-Za-z]+)*\s*$/, lambda {|value, match, default| (!default) ? value.strip : (value || '').strip}],
|
18
|
+
range: [/^\s*(?:(\d+)\.\.(\d+)|(\d*)\.\.|\.\.(\d+))\s*$/, lambda {|value, match, default| (!default) ? [(match[0] || match[3]).to_i, (match[2] || match[4]).to_i] : [0,0]}],
|
19
|
+
interval: [/^\s*(?:(\d+(?:\.\d+)?)\.\.(\d+(?:\.\d+)?)|(\d*(?:\.\d+)?)\.\.|\.\.(\d+(?:\.\d+)?))\s*$/, lambda {|value, match, default| (!default) ? [(match[0] || match[3]).to_f, (match[2] || match[4]).to_f] : [0.0,0.0]}],
|
20
|
+
string: [/^.*$/, lambda {|value, match, default| value || ''}]
|
21
|
+
}
|
22
|
+
|
23
|
+
#Initialize the parser
|
24
|
+
def initialize(config)
|
25
|
+
@tokens, @options, @params, @remaining = {}, {}, {}, {}
|
26
|
+
init_options(config[:options] || {})
|
27
|
+
init_params(config[:params] || {})
|
28
|
+
init_remaining(config[:remaining] || {})
|
29
|
+
end
|
30
|
+
|
31
|
+
#Parse an array with arguments and associate each element to one of the parameters or to the remaining array
|
32
|
+
def parse(args)
|
33
|
+
begin
|
34
|
+
#Identify each element in the array of arguments
|
35
|
+
last_param = nil
|
36
|
+
args.each do |arg|
|
37
|
+
if (arg =~ /^--?\w+$/)
|
38
|
+
arg = arg.downcase
|
39
|
+
|
40
|
+
raise_message(@options[:unknown], arg) unless @tokens.has_key? arg
|
41
|
+
param = @params[@tokens[arg]]
|
42
|
+
param[:given] = arg
|
43
|
+
if (@params[@tokens[arg]][:type] != :boolean)
|
44
|
+
last_param = param
|
45
|
+
end
|
46
|
+
|
47
|
+
#If parameter :help was given and the parser is supposed to automatically display the help, do so
|
48
|
+
help if (param? :help) and (@options[:help])
|
49
|
+
else
|
50
|
+
if (last_param)
|
51
|
+
last_param[:value] = arg
|
52
|
+
last_param = nil
|
53
|
+
else
|
54
|
+
@remaining[:value] = [] if @remaining[:given] == 0
|
55
|
+
@remaining[:given] += 1
|
56
|
+
@remaining[:value].push arg
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#Iterate over all parameters and process their values
|
62
|
+
@params.each do |token, param|
|
63
|
+
raise_message(param[:messages][:required], "--#{param[:token].to_s}") unless param?(token) or !param[:required]
|
64
|
+
validate_param(param)
|
65
|
+
sanitize(param)
|
66
|
+
end
|
67
|
+
|
68
|
+
#Process the value of the remaining array
|
69
|
+
raise_message(@remaining[:messages][:required]) unless (@remaining[:minimum] <= remaining?) and (remaining? <= @remaining[:maximum])
|
70
|
+
validate_remaining()
|
71
|
+
sanitize(@remaining)
|
72
|
+
|
73
|
+
#Invoke all callbacks
|
74
|
+
invoke_callbacks
|
75
|
+
rescue ParserError => error
|
76
|
+
#In case of error, print the reason and how to find more information
|
77
|
+
puts error.message
|
78
|
+
puts @options[:info] unless @options[:info].empty?
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#Check if a parameter was given
|
84
|
+
def param?(param)
|
85
|
+
(@tokens.has_key? param) ? !!@params[@tokens[param]][:given] : false
|
86
|
+
end
|
87
|
+
|
88
|
+
#Return the value of a parameter
|
89
|
+
def param(param)
|
90
|
+
(@tokens.has_key? param) ? @params[@tokens[param]][:value] : ''
|
91
|
+
end
|
92
|
+
|
93
|
+
#Returns the number of remaining strings that were found
|
94
|
+
def remaining?()
|
95
|
+
@remaining[:given]
|
96
|
+
end
|
97
|
+
|
98
|
+
#Return the remaining values
|
99
|
+
def remaining()
|
100
|
+
@remaining[:value]
|
101
|
+
end
|
102
|
+
|
103
|
+
#Return both parameters and remaining values in a hash
|
104
|
+
def dump
|
105
|
+
values = {}
|
106
|
+
@params.each do |token, param|
|
107
|
+
values[token] = param[:value]
|
108
|
+
end
|
109
|
+
{params: values, remaining: @remaining[:value]}
|
110
|
+
end
|
111
|
+
|
112
|
+
#Display the help and exit
|
113
|
+
def help
|
114
|
+
puts "#{@options[:description]}\n\n" unless @options[:description].empty?
|
115
|
+
puts "#{@options[:usage]}\n\n" unless @options[:usage].empty?
|
116
|
+
@params.each do |token, param|
|
117
|
+
token = "--#{token.to_s}"
|
118
|
+
shortcut = (param[:shortcut].is_a? Symbol) ? "-#{param[:shortcut]}" : ''
|
119
|
+
help = param[:messages][:help]
|
120
|
+
puts " #{shortcut.ljust(5, ' ')}#{token.ljust(20, ' ')}#{help}"
|
121
|
+
end
|
122
|
+
puts "\n"
|
123
|
+
puts "#{@options[:details]}" unless @options[:details].empty?
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
#Available general options:
|
130
|
+
# :description A string containing the description of the application (default: "")
|
131
|
+
# :usage A string describing how to use the application (default: "")
|
132
|
+
# :details A string containing details about the application (default: "")
|
133
|
+
# :info A string printer bellow errors indicating how to find more information about them (default: "For more information try '--help'")
|
134
|
+
# :unknown A string with the message to show when a parameter is not known (default: "Unknown parameter '$p'")
|
135
|
+
# :fatal A string with the message to show when an internal error is found while parsing parameters (default: "An internal error was found")
|
136
|
+
# :help A boolean value indicating if the parser should automatically display the help if parameter :help is given (default: true)
|
137
|
+
|
138
|
+
#Save all options for the parser
|
139
|
+
def init_options(options={})
|
140
|
+
@options = {
|
141
|
+
description: "",
|
142
|
+
usage: "",
|
143
|
+
details: "",
|
144
|
+
info: "For more information try '--help'",
|
145
|
+
unknown: "Unknown parameter '$p'",
|
146
|
+
fatal: "An internal error was found",
|
147
|
+
help: true
|
148
|
+
}.merge options
|
149
|
+
end
|
150
|
+
|
151
|
+
#Available parameter options:
|
152
|
+
# :shortcut A symbol used as a shortcut for this parameter (default: nil)
|
153
|
+
# :type A symbol indicating the type of this parameter (default: :string)
|
154
|
+
# :default The default value if not other value is provided (default: '')
|
155
|
+
# :required A boolean value indicating if this parameter is required or not
|
156
|
+
# :sanitize A function to sanitize the value given (return the identifier of a message to show it or the sanitized value the parser should save)
|
157
|
+
# :callback A function to call to do something with the parameter
|
158
|
+
# :messages A hash with all available messages to show where the key is used as an identifier (:help, :type and :required are created by default)
|
159
|
+
|
160
|
+
#Save all parameters the parser should recognize
|
161
|
+
def init_params(params={})
|
162
|
+
#If the parser should recognize :help, add it
|
163
|
+
if (!params.has_key? :help) and (@options[:help])
|
164
|
+
params[:help] = {
|
165
|
+
shortcut: :h,
|
166
|
+
type: :boolean,
|
167
|
+
default: false,
|
168
|
+
messages: {
|
169
|
+
help: 'Display this help and exit'
|
170
|
+
}
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
#Save each param and overwrite default options
|
175
|
+
params.each do |token, param|
|
176
|
+
@params[token] = {
|
177
|
+
shortcut: nil,
|
178
|
+
type: :string,
|
179
|
+
default: '',
|
180
|
+
required: false,
|
181
|
+
sanitize: lambda {|value, default| value},
|
182
|
+
callback: lambda {|value, default|},
|
183
|
+
messages: {}
|
184
|
+
}.merge param
|
185
|
+
|
186
|
+
@params[token][:token] = token
|
187
|
+
@params[token][:value] = @params[token][:default]
|
188
|
+
@params[token][:given] = false
|
189
|
+
|
190
|
+
#Save messages, make sure :help, :type and :required is available
|
191
|
+
@params[token][:messages] = {
|
192
|
+
help: "",
|
193
|
+
type: "Invalid value '$v' for parameter '$p'",
|
194
|
+
required: "Parameter '$p' is required"
|
195
|
+
}.merge @params[token][:messages]
|
196
|
+
|
197
|
+
#Register all tokens for the parameter
|
198
|
+
@tokens[token] = token
|
199
|
+
@tokens["--#{token}"] = token
|
200
|
+
if (param[:shortcut].is_a? Symbol)
|
201
|
+
@tokens[param[:shortcut]] = token
|
202
|
+
@tokens["-#{param[:shortcut]}"] = token
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
#Available remaining array options:
|
208
|
+
# :type A symbol indicating the type of this parameter (default: :string)
|
209
|
+
# :default The default value if not other value is provided (default: '')
|
210
|
+
# :minimum Minimum number of strings allowed (default: 0)
|
211
|
+
# :maximum Maximum number of strings allowed (default: Infinity)
|
212
|
+
# :sanitize A function to sanitize the value given (return the identifier of a message to show it or the sanitized value the parser should save)
|
213
|
+
# :callback A function to call to do something with the parameter
|
214
|
+
# :messages A hash with all available messages to show where the key is used as an identifier (:help, :type and :required are created by default)
|
215
|
+
|
216
|
+
#Save options for remaining strings
|
217
|
+
def init_remaining(remaining={})
|
218
|
+
@remaining = {
|
219
|
+
type: :string,
|
220
|
+
default: [],
|
221
|
+
minimum: 0,
|
222
|
+
maximum: Float::INFINITY,
|
223
|
+
sanitize: lambda {|value, default| value},
|
224
|
+
callback: lambda {|value, default|},
|
225
|
+
messages: {}
|
226
|
+
}.merge remaining
|
227
|
+
|
228
|
+
@remaining[:value] = @remaining[:default]
|
229
|
+
@remaining[:given] = 0
|
230
|
+
|
231
|
+
#Save messages, make sure :help, :type and :required is available
|
232
|
+
@remaining[:messages] = {
|
233
|
+
help: "",
|
234
|
+
type: "Invalid value '$v'",
|
235
|
+
required: "Incorrect number of remaining arguments"
|
236
|
+
}.merge @remaining[:messages]
|
237
|
+
end
|
238
|
+
|
239
|
+
#Validate the value of a parameter based on its type
|
240
|
+
def validate_param(param)
|
241
|
+
#If the type is a symbol, it must be a valid type
|
242
|
+
if (param[:type].is_a? Symbol)
|
243
|
+
type = TYPES[param[:type]]
|
244
|
+
raise_message(param[:messages][:type], param[:token], param[:value]) if (param[:given]) and (param[:value].is_a? String) and !(match = type[0].match param[:value])
|
245
|
+
#Convert value to the correct type
|
246
|
+
param[:value] = type[1].call(param[:value], match, !param[:given])
|
247
|
+
else #Otherwise it must be a regexp and the value must match
|
248
|
+
raise_message(param[:messages][:type], param[:token], param[:value]) unless param[:value] =~ param[:type]
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
#Validate the value of the remaining array based on its type
|
253
|
+
def validate_remaining()
|
254
|
+
#If the type is a symbol, it must be a valid type
|
255
|
+
if (@remaining[:type].is_a? Symbol)
|
256
|
+
type = TYPES[@remaining[:type]]
|
257
|
+
@remaining[:value].each_with_index do |value, i|
|
258
|
+
raise_message(@remaining[:messages][:type], @remaining[:token], value) unless (@remaining[:given] == 0) or (match = type[0].match value)
|
259
|
+
#Convert value to the correct type
|
260
|
+
@remaining[:value][i] = type[1].call(value, match, @remaining[:given] == 0)
|
261
|
+
end
|
262
|
+
else #Otherwise it must be a regexp and the values must match
|
263
|
+
@remaining[:value].each do |value|
|
264
|
+
raise_message(@remaining[:messages][:type], @remaining[:token], value) unless value =~ @remaining[:type]
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
#Sanitize the value of the parameter, if a symbol is returned the associated message is shown
|
270
|
+
def sanitize(param)
|
271
|
+
value = param[:sanitize].call(param[:value], !param[:given])
|
272
|
+
raise_message(param[:messages][value], param[:token], param[:value]) if value.is_a? Symbol
|
273
|
+
#Update the value
|
274
|
+
param[:value] = value
|
275
|
+
end
|
276
|
+
|
277
|
+
#Invoke parameters and remaining array callbacks
|
278
|
+
def invoke_callbacks
|
279
|
+
@params.each do |token, param|
|
280
|
+
param[:callback].call(param[:value], !param[:given])
|
281
|
+
end
|
282
|
+
@remaining[:callback].call(@remaining[:value], !@remaining[:given])
|
283
|
+
end
|
284
|
+
|
285
|
+
#Raise an error message
|
286
|
+
def raise_message(message, token='', value='')
|
287
|
+
raise ParserError.new(message || @options[:fatal], token, value)
|
288
|
+
end
|
289
|
+
|
290
|
+
#Parser errors used to display messages ($p is replaced by the parameter used by the user, $v is replaced by the value given)
|
291
|
+
class ParserError < Exception
|
292
|
+
attr_reader :message
|
293
|
+
def initialize(message, token='', value='')
|
294
|
+
@message = message.gsub('$p', token.to_s).gsub('$v', value.to_s)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
data/lib/argser.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#Argser is a library that aims to simplify the process of parsing arguments in command
|
2
|
+
#line scripts written in Ruby. It provides an easy way to specify which parameters are
|
3
|
+
#valid, their type or format, error conditions, description, etc. In that way, it
|
4
|
+
#reduces the need to write code specificaly to parse and validate such arguments.
|
5
|
+
#
|
6
|
+
#Author: Matías Parodi © 2013
|
7
|
+
#
|
8
|
+
module Argser
|
9
|
+
require 'argser/parser'
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: argser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matías Parodi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Argser (from 'ARGuments parSER') is a library that aims to simplify the
|
15
|
+
process of parsing arguments in command line scripts written in Ruby. It provides
|
16
|
+
an easy way to specify which parameters are valid, their type or format, error conditions,
|
17
|
+
description, etc. In that way, it reduces the need to write code specificaly to
|
18
|
+
parse and validate such arguments. The idea is pretty simple. To be able to use
|
19
|
+
the arguments passed when the script was executed in a easy and consistent way,
|
20
|
+
you only need to specify some general options for the application, a list of parameters
|
21
|
+
and some properties that must hold for both, parameters and what is called the 'remaining
|
22
|
+
array' (an array with strings that don't belong to any parameter).
|
23
|
+
email:
|
24
|
+
- mparodilabs@gmail.com
|
25
|
+
executables: []
|
26
|
+
extensions: []
|
27
|
+
extra_rdoc_files: []
|
28
|
+
files:
|
29
|
+
- README.md
|
30
|
+
- lib/argser.rb
|
31
|
+
- lib/argser/parser.rb
|
32
|
+
- examples/greetings.rb
|
33
|
+
homepage: http://rubygems.org/gems/argser
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.23
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: Argser is a library that aims to simplify the process of parsing arguments
|
57
|
+
in command line scripts written in Ruby
|
58
|
+
test_files: []
|
59
|
+
has_rdoc:
|