rationalist 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8633e4aa82d70469c295b72f899595f3f2213735
4
+ data.tar.gz: 7f9bb97172fbdfc790f678330c358c8708676e9a
5
+ SHA512:
6
+ metadata.gz: 3b267e19bb7a9c15b719268dcc10d6fd4b4c29cac268b2769ef965ffb017e94a0048a6f31311e0458c1c42b25331c081e753ff9ca8adf94fd3123f6f2fc6555d
7
+ data.tar.gz: 938dac9c1c6750e4dedbe63a9a248281871d257ae7c634c002a599f26138ac5602236aab0a66bcf8f13992c030748f33e937d07be2967d95147dbaa0ca7370ae
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,13 @@
1
+ sudo: false
2
+ language: ruby
3
+
4
+ rvm:
5
+ - 2.2
6
+ - ruby-head
7
+ - jruby-head
8
+
9
+ cache:
10
+ - bundler
11
+
12
+ # matrix:
13
+ # fast_finish: true
@@ -0,0 +1,6 @@
1
+ ## CHANGELOG
2
+
3
+ ### 2.0.0
4
+
5
+ * Inital release
6
+
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'minitest'
6
+ gem 'rake'
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ This software is released under the MIT license:
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,105 @@
1
+ # rationalist [![[version]](https://badge.fury.io/rb/Rationalist.svg)](http://badge.fury.io/rb/rationalist) [![[travis]](https://travis-ci.org/janlelis/Rationalist.png)](https://travis-ci.org/janlelis/rationalist)
2
+
3
+ Rationalist parses command-line arguments into a hash. It is strongly influenced
4
+ by substack's [minimist](https://github.com/substack/minimist) nodejs module.
5
+
6
+ ## setup
7
+
8
+ Add to your `Gemfile`:
9
+
10
+ ```ruby
11
+ gem 'rationalist'
12
+ ```
13
+
14
+ For more info, see the original README below, with all JS replaced with Ruby.
15
+
16
+ # minimist
17
+
18
+ parse argument options
19
+
20
+ This module is the guts of optimist's argument parser without all the
21
+ fanciful decoration.
22
+
23
+ # example
24
+
25
+ ```ruby
26
+ require 'rationlist'
27
+ argv = Rationalist.parse(ARGV)
28
+ p argv
29
+ ```
30
+
31
+ ```
32
+ $ ruby example/parse.rb -a beep -b boop
33
+ {:_=>[], :a=>"beep", :b=>"boop"}
34
+ ```
35
+
36
+ ```
37
+ $ ruby example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
38
+ { :_=>["foo", "bar", "baz"],
39
+ :x=>3,
40
+ :y=>4,
41
+ :n=>5,
42
+ :a=>true,
43
+ :b=>true,
44
+ :c=>true,
45
+ :beep=>"boop" }
46
+ ```
47
+
48
+ # methods
49
+
50
+ ```ruby
51
+ require 'rationalist'
52
+ ```
53
+
54
+ ## argv = Rationalist.parse(args = ARGV, **opts, &unknown_block)
55
+
56
+ Return an argument object `argv` populated with the array arguments from `args`.
57
+
58
+ `argv[:_]` contains all the arguments that didn't have an option associated with
59
+ them.
60
+
61
+ Numeric-looking arguments will be returned as numbers unless `opts[:string]` or
62
+ `opts[:boolean]` is set for that argument name.
63
+
64
+ Any arguments after `'--'` will not be parsed and will end up in `argv[:_]`.
65
+
66
+ options can be:
67
+
68
+ * `opts[:string]` - a string or array of strings argument names to always treat as
69
+ strings
70
+ * `opts[:boolean]` - a boolean, string or array of strings to always treat as
71
+ booleans. if `true` will treat all double hyphenated arguments without equal signs
72
+ as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`)
73
+ * `opts[:alias]` - an object mapping string names to strings or arrays of string
74
+ argument names to use as aliases
75
+ * `opts[:default]` - an object mapping string argument names to default values
76
+ * `opts[:stop_early]` - when true, populate `argv[:_]` with everything after the
77
+ first non-option
78
+ * `opts[:'--']` - when true, populate `argv._` with everything before the `--`
79
+ and `argv[:'--']` with everything after the `--`. Here's an example:
80
+ * `&unknown_block` - a block which is invoked with a command line parameter not
81
+ defined in the `opts` configuration object. If the function returns `false`, the
82
+ unknown option is not added to `argv`.
83
+
84
+ ```ruby
85
+ >> Rationalist.parse('one two three -- four five --six'.split(' '), { '--': true })
86
+ { :_=>["one", "two", "three"],
87
+ :"--"=>["four", "five", "--six"] }
88
+ ```
89
+
90
+ Note that with `opts[:'--']` set, parsing for arguments still stops after the
91
+ `--`.
92
+
93
+ # install
94
+
95
+ With [rubygems](https://rubygems.org) do:
96
+
97
+ ```
98
+ gem install rationalist
99
+ ```
100
+
101
+ # license
102
+
103
+ MIT
104
+
105
+ **rationalist** was written by Jan Lelis and [minimist](https://github.com/substack/minimist) was written by James Halliday.
@@ -0,0 +1,44 @@
1
+ # # #
2
+ # Get gemspec info
3
+
4
+ gemspec_file = Dir['*.gemspec'].first
5
+ gemspec = eval File.read(gemspec_file), binding, gemspec_file
6
+ info = "#{gemspec.name} | #{gemspec.version} | " \
7
+ "#{gemspec.runtime_dependencies.size} dependencies | " \
8
+ "#{gemspec.files.size} files"
9
+
10
+
11
+ # # #
12
+ # Gem build and install task
13
+
14
+ desc info
15
+ task :gem do
16
+ puts info + "\n\n"
17
+ print " "; sh "gem build #{gemspec_file}"
18
+ FileUtils.mkdir_p 'pkg'
19
+ FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
20
+ puts; sh %{gem install --no-document pkg/#{gemspec.name}-#{gemspec.version}.gem}
21
+ end
22
+
23
+
24
+ # # #
25
+ # Start an IRB session with the gem loaded
26
+
27
+ desc "#{gemspec.name} | IRB"
28
+ task :irb do
29
+ sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}"
30
+ end
31
+
32
+
33
+ # # #
34
+ # Run all specs
35
+
36
+ require 'rake/testtask'
37
+ Rake::TestTask.new do |t|
38
+ t.pattern = "spec/*_spec.rb"
39
+ end
40
+
41
+ # # #
42
+ # Default task
43
+
44
+ task default: :test
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/rationalist'
3
+ argv = Rationalist.parse(ARGV)
4
+ p argv
@@ -0,0 +1,273 @@
1
+ module Rationalist
2
+ VERSION = '2.0.0'
3
+
4
+ def self.parse(args = ARGV, **options, &unknown_block)
5
+ Argv.new(args, options, unknown_block).argv
6
+ end
7
+
8
+ class Argv
9
+ attr_reader :argv
10
+
11
+ private
12
+
13
+ def initialize(args, options = {}, unknown_block = nil)
14
+ @args = args
15
+ @options = options
16
+ @unknown_block = unknown_block
17
+ @bools = {}
18
+ @strings = {}
19
+ @all_bools = false
20
+ @aliases = {}
21
+ @not_flags = []
22
+ @argv = {_: []}
23
+
24
+ apply_boolean_option!
25
+ apply_alias_option!
26
+ apply_strings_option!
27
+ apply_defaults_option!
28
+
29
+ parse_arguments!
30
+
31
+ fill_with_defaults!
32
+ fill_with_non_flags!
33
+ end
34
+
35
+ def apply_boolean_option!
36
+ if @options[:boolean] == true
37
+ @all_bools = true
38
+ else
39
+ Array(@options[:boolean] || []).each{ |b| @bools[b.to_sym] = true }
40
+ end
41
+ end
42
+
43
+ def apply_alias_option!
44
+ Array(@options[:alias] || {}).each{ |key, value|
45
+ key = key.to_sym
46
+ @aliases[key] = value.is_a?(Array) ? value.map(&:to_sym) : value.to_sym
47
+ Array(@aliases[key]).each{ |x|
48
+ x = x.to_sym
49
+ @aliases[x] = [key] + Array(@aliases[key]).select{ |y| x != y }
50
+ }
51
+ }
52
+ end
53
+
54
+ def apply_strings_option!
55
+ Array(@options[:string] || []).each{ |s|
56
+ s = s.to_sym
57
+ @strings[s] = true
58
+ @strings[@aliases[s]] = true if @aliases[s]
59
+ }
60
+ end
61
+
62
+ def apply_defaults_option!
63
+ @defaults = @options[:default] || {}
64
+ @bools.keys.each{ |key|
65
+ set_argument key, @defaults.has_key?(key) ? @defaults[key] : false
66
+ }
67
+ end
68
+
69
+ def parse_arguments!
70
+ if i = @args.index('--')
71
+ @not_flags, @args = @args[i+1..-1], @args[0..i-1]
72
+ end
73
+
74
+ i = 0
75
+ while i < @args.length
76
+ skip_next = false
77
+
78
+ case arg = @args[i]
79
+ when /\A--([^=]+)=(.*)\z/m
80
+ set_argument($1, $2, arg)
81
+ when /\A--no-(.+)/
82
+ set_argument($1, false, arg)
83
+ when /\A--(.+)/
84
+ key = $1.to_sym
85
+ next_arg = @args[i+1]
86
+ skip_next = handle_dash_dash_argument(
87
+ key,
88
+ next_arg,
89
+ arg,
90
+ next_arg_is_value?(key, next_arg, /\A-/, false)
91
+ )
92
+ when /\A-[^-]+/
93
+ skip_next = handle_dash_argument(arg.to_sym, @args[i+1])
94
+ else
95
+ if handle_unknown_argument(arg.to_s)
96
+ @argv[:_] += @args[i+1 .. -1]
97
+ break
98
+ end
99
+ end
100
+
101
+ i += 1 if skip_next
102
+ i += 1
103
+ end
104
+ end
105
+
106
+ def handle_dash_dash_argument(key, next_arg, arg, next_arg_is_value)
107
+ if next_arg_is_value
108
+ set_argument(key, next_arg, arg)
109
+ true
110
+ elsif next_arg =~ /\A(true|false)\z/
111
+ set_argument(key, $& == "true", arg)
112
+ true
113
+ else
114
+ set_argument(key, @strings[key] ? '' : true, arg)
115
+ false
116
+ end
117
+ end
118
+
119
+ def handle_dash_argument(arg, next_arg)
120
+ letters = arg[1..-1].split('')
121
+ broken = false
122
+ j = -1
123
+ while j < letters.size - 2
124
+ j += 1
125
+ letter = letters[j].to_sym
126
+ next_letters = arg[j+2 .. -1]
127
+ if next_letters.to_sym == :-
128
+ set_argument letter, next_letters, arg
129
+ next
130
+ end
131
+
132
+ if letter =~ /[A-Za-z]/ && next_letters =~ /-?\d+(\.\d*)?(e-?\d+)?\z/
133
+ set_argument letter, next_letters, arg
134
+ broken = true
135
+ break
136
+ end
137
+
138
+ next_letter = letters[j+1]
139
+ if next_letter && next_letter =~ /\W/
140
+ set_argument letter, arg[j+2 .. -1], arg
141
+ broken = true
142
+ break
143
+ else
144
+ set_argument letter, @strings[letter] ? '' : true, arg
145
+ end
146
+ end
147
+
148
+ key = arg[-1].to_sym
149
+ if !broken && key != :-
150
+ return handle_dash_dash_argument(
151
+ key,
152
+ next_arg,
153
+ arg,
154
+ next_arg_is_value?(key, next_arg, /\A(-|--)[^-]/, true)
155
+ )
156
+ end
157
+
158
+ false
159
+ end
160
+
161
+ def handle_unknown_argument(arg)
162
+ if !@unknown_block || @unknown_block[arg.to_s]
163
+ @argv[:_] << ((@strings[:_] || !numeric?(arg)) ? arg : Numeric(arg))
164
+ end
165
+
166
+ !!@options[:stop_early]
167
+ end
168
+
169
+ def fill_with_defaults!
170
+ @defaults.each{ |key, value|
171
+ split_key_array = split_key_at_dots(key)
172
+ unless has_nested_key?(split_key_array)
173
+ set_key(split_key_array, value)
174
+ Array(@aliases[key] || []).each{ |sub_key|
175
+ split_sub_key_array = split_key_at_dots(sub_key)
176
+ set_key(split_sub_key_array, value)
177
+ }
178
+ end
179
+ }
180
+ end
181
+
182
+ def fill_with_non_flags!
183
+ if @options[:'--']
184
+ @argv[:'--'] = []
185
+ @not_flags.each{ |key| @argv[:'--'] << key }
186
+ else
187
+ @not_flags.each{ |key| @argv[:_] << key }
188
+ end
189
+ end
190
+
191
+ def argument_defined?(key, arg)
192
+ @all_bools && /\A--[^=]+\z/ =~ arg || @strings[key] || @bools[key] || @aliases[key]
193
+ end
194
+
195
+ def set_argument(key, value, arg = nil)
196
+ return if arg && @unknown_block && !argument_defined?(key, arg.to_sym) && !@unknown_block[arg.to_s]
197
+ value = (!@strings[key] && numeric?(value)) ? Numeric(value) : value
198
+ split_key = split_key_at_dots(key)
199
+ set_key(split_key, value)
200
+ Array(@aliases[key] || []).each{ |sub_key|
201
+ split_sub_key_array = split_key_at_dots(sub_key)
202
+ set_key(split_sub_key_array, value)
203
+ }
204
+ end
205
+
206
+ def set_key(keys, value)
207
+ o = @argv
208
+ keys[0..-2].each{ |key|
209
+ key = to_key_type(key)
210
+ o[key] = {} unless o.has_key?(key)
211
+ o = o[key]
212
+ }
213
+
214
+ key = to_key_type(keys[-1])
215
+
216
+ if !o.has_key?(key) || @bools[key] || o[key] == true || o[key] == false
217
+ o[key] = value
218
+ elsif o[key].is_a? Array
219
+ o[key] << value
220
+ else
221
+ o[key] = [o[key], value]
222
+ end
223
+ end
224
+
225
+ def next_arg_is_value?(key, next_arg, next_arg_regex, all_bools_true = true)
226
+ next_arg &&
227
+ next_arg !~ next_arg_regex &&
228
+ !@bools[key] &&
229
+ (all_bools_true || !@all_bools) &&
230
+ (@aliases[key] ? !(Array(@aliases[key]).any?{ |a| @bools[a] }) : true)
231
+ end
232
+
233
+ def numeric?(value)
234
+ value.is_a?(Numeric) ||
235
+ !(value !~ /\A0x[0-9a-f]+\z/) ||
236
+ !(value !~ /\A[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?\z/)
237
+ end
238
+
239
+ def Numeric(value)
240
+ case value
241
+ when Numeric
242
+ value
243
+ when /\A0x/
244
+ Integer(value)
245
+ when /\.|e/
246
+ Float(value)
247
+ else
248
+ Integer(value)
249
+ end
250
+ end
251
+
252
+ def to_key_type(key)
253
+ numeric?(key.to_s) ? Numeric(key.to_s) : key.to_sym
254
+ end
255
+
256
+ def split_key_at_dots(key)
257
+ if key.is_a?(Symbol) || key.is_a?(String)
258
+ key.to_s.split('.').map(&:to_sym)
259
+ else
260
+ Array(key)
261
+ end
262
+ end
263
+
264
+ def has_nested_key?(split_key_array)
265
+ catch :has_not do
266
+ split_key_array.reduce(@argv){ |acc, cur| (acc.has_key?(cur) or throw :has_not) && acc[cur] }
267
+ return true
268
+ end
269
+
270
+ false
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + "/lib/rationalist"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "rationalist"
7
+ gem.version = Rationalist::VERSION
8
+ gem.summary = "parse argument options"
9
+ gem.description = "parse argument options. a ruby fork of minimist."
10
+ gem.authors = ["Jan Lelis"]
11
+ gem.email = ["mail@janlelis.de"]
12
+ gem.homepage = "https://github.com/janlelis/Rationalist"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ }
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^spec/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.required_ruby_version = "~> 2.0"
21
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'all bools' do
6
+ it 'flag boolean true (default all --args to boolean)' do
7
+ argv = Rationalist.parse(['moo', '--honk', 'cow'], {
8
+ boolean: true
9
+ })
10
+
11
+ argv.must_equal({
12
+ honk: true,
13
+ _: ['moo', 'cow']
14
+ })
15
+ end
16
+ end
@@ -0,0 +1,106 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'bool' do
6
+ it 'flag boolean default false' do
7
+ argv = Rationalist.parse(['moo'], {
8
+ boolean: ['t', 'verbose'],
9
+ default: { verbose: false, t: false }
10
+ })
11
+
12
+ argv.must_equal({
13
+ verbose: false,
14
+ t: false,
15
+ _: ['moo']
16
+ })
17
+ end
18
+
19
+ it 'boolean groups' do
20
+ argv = Rationalist.parse(['-x', '-z', 'one', 'two', 'three'], {
21
+ boolean: ['x','y','z']
22
+ })
23
+
24
+ argv.must_equal({
25
+ x: true,
26
+ y: false,
27
+ z: true,
28
+ _: ['one', 'two', 'three']
29
+ })
30
+ end
31
+
32
+ it 'boolean and alias with chainable api' do
33
+ aliased = ['-h', 'derp']
34
+ regular = ['--herp', 'derp']
35
+ options = { herp: {alias: 'h', boolean: true} }
36
+ aliased_argv = Rationalist.parse(aliased, {
37
+ boolean: 'herp',
38
+ alias: { h: 'herp' }
39
+ })
40
+ property_argv = Rationalist.parse(regular, {
41
+ boolean: 'herp',
42
+ alias: { h: 'herp' }
43
+ })
44
+ expected = {
45
+ herp: true,
46
+ h: true,
47
+ _: ['derp']
48
+ };
49
+
50
+ aliased_argv.must_equal(expected);
51
+ property_argv.must_equal(expected);
52
+ end
53
+
54
+ it 'boolean and alias with options hash' do
55
+ aliased = ['-h', 'derp']
56
+ regular = ['--herp', 'derp']
57
+ options = {
58
+ alias: { h: 'herp' },
59
+ boolean: 'herp'
60
+ }
61
+
62
+ aliased_argv = Rationalist.parse(aliased, options)
63
+ property_argv = Rationalist.parse(regular, options)
64
+ expected = {
65
+ herp: true,
66
+ h: true,
67
+ _: ['derp']
68
+ }
69
+ aliased_argv.must_equal(expected);
70
+ property_argv.must_equal(expected);
71
+ end
72
+
73
+ it 'boolean and alias using explicit true' do
74
+ aliased = ['-h', 'true']
75
+ regular = ['--herp', 'true']
76
+ options = {
77
+ alias: { h: 'herp' },
78
+ boolean: 'h'
79
+ }
80
+
81
+ aliased_argv = Rationalist.parse(aliased, options)
82
+ property_argv = Rationalist.parse(regular, options)
83
+ expected = {
84
+ herp: true,
85
+ h: true,
86
+ _: []
87
+ }
88
+ aliased_argv.must_equal(expected);
89
+ property_argv.must_equal(expected);
90
+ end
91
+
92
+ it 'boolean and --x=true' do
93
+ parsed = Rationalist.parse(['--boool', '--other=true'], {
94
+ boolean: 'boool'
95
+ })
96
+ parsed[:boool].must_equal true
97
+ parsed[:other].must_equal 'true'
98
+
99
+ parsed = Rationalist.parse(['--boool', '--other=false'], {
100
+ boolean: 'boool'
101
+ })
102
+
103
+ parsed[:boool].must_equal true
104
+ parsed[:other].must_equal 'false'
105
+ end
106
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'dash' do
6
+ it '-' do
7
+ Rationalist.parse(['-n', '-']).must_equal({ n: '-', _: [] })
8
+ Rationalist.parse(['-']).must_equal({ _: ['-'] })
9
+ Rationalist.parse(['-f-']).must_equal({ f: '-', _: [] })
10
+ Rationalist.parse(['-b', '-'], boolean: 'b').must_equal({ b: true, _: ['-'] })
11
+ Rationalist.parse(['-s', '-'], string: 's').must_equal({ s: '-', _: [] })
12
+ end
13
+
14
+ it '-a -- b' do
15
+ Rationalist.parse(['-a', '--', 'b']).must_equal({ a: true, _: ['b'] })
16
+ Rationalist.parse(['--a', '--', 'b']).must_equal({ a: true, _: ['b'] })
17
+ end
18
+
19
+ it 'move arguments after the -- into their own `--` array' do
20
+ Rationalist.parse(['--name', 'John', 'before', '--', 'after'], { :'--' => true }).must_equal(
21
+ { name: 'John', _: ['before'], :'--' => ['after'] }
22
+ )
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'default bool' do
6
+ it 'boolean default true' do
7
+ argv = Rationalist.parse([], {
8
+ boolean: 'sometrue',
9
+ default: { sometrue: true }
10
+ });
11
+ argv[:sometrue].must_equal true
12
+ end
13
+
14
+ it 'boolean default false' do
15
+ argv = Rationalist.parse([], {
16
+ boolean: 'somefalse',
17
+ default: { somefalse: false }
18
+ });
19
+ argv[:somefalse].must_equal false
20
+ end
21
+
22
+ it 'boolean default to nil' do
23
+ argv = Rationalist.parse([], {
24
+ boolean: 'maybe',
25
+ default: { maybe: nil }
26
+ });
27
+ argv[:maybe].must_equal nil
28
+ argv = Rationalist.parse(['--maybe'], {
29
+ boolean: 'maybe',
30
+ default: { maybe: nil }
31
+ });
32
+ argv[:maybe].must_equal true
33
+ end
34
+ end
35
+
@@ -0,0 +1,23 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'dotted' do
6
+ it 'dotted alias' do
7
+ argv = Rationalist.parse(['--a.b', '22'], { default: { :'a.b' => 11 }, alias: { :'a.b' => 'aa.bb' } });
8
+ argv[:a][:b].must_equal(22)
9
+ argv[:aa][:bb].must_equal(22)
10
+ end
11
+
12
+ it 'dotted default' do
13
+ argv = Rationalist.parse('', { default: { :'a.b' => 11 }, alias: { :'a.b' => 'aa.bb' } });
14
+ argv[:a][:b].must_equal(11)
15
+ argv[:aa][:bb].must_equal(11)
16
+ end
17
+
18
+ it 'dotted default with no alias' do
19
+ argv = Rationalist.parse('', { default: { :'a.b' => 11 } });
20
+ argv[:a][:b].must_equal(11)
21
+ end
22
+ end
23
+
@@ -0,0 +1,25 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'long' do
6
+ it 'long boolean' do
7
+ Rationalist.parse([ '--bool' ]).must_equal({ bool: true, _: [] })
8
+ end
9
+
10
+ it 'long capture sp' do
11
+ Rationalist.parse([ '--pow', 'xixxle' ]).must_equal({ pow: 'xixxle', _: [] })
12
+ end
13
+
14
+ it 'long capture eq' do
15
+ Rationalist.parse([ '--pow=xixxle' ]).must_equal({ pow: 'xixxle', _: [] })
16
+ end
17
+
18
+ it 'long captures sp' do
19
+ Rationalist.parse([ '--host', 'localhost', '--port', '555' ]).must_equal({ host: 'localhost', port: 555, _: [] })
20
+ end
21
+
22
+ it 'long captures eq' do
23
+ Rationalist.parse([ '--host=localhost', '--port=555' ]).must_equal({ host: 'localhost', port: 555, _: [] })
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'num' do
6
+ it 'nums' do
7
+ argv = Rationalist.parse([
8
+ '-x', '1234',
9
+ '-y', '5.67',
10
+ '-z', '1e7',
11
+ '-w', '10f',
12
+ '--hex', '0xdeadbeef',
13
+ '789'
14
+ ])
15
+ argv.must_equal({
16
+ x: 1234,
17
+ y: 5.67,
18
+ z: 1e7,
19
+ w: '10f',
20
+ hex: 0xdeadbeef,
21
+ _: [789]
22
+ })
23
+ end
24
+
25
+ it 'already a number' do
26
+ argv = Rationalist.parse([ '-x', 1234, 789 ]);
27
+ argv.must_equal({ x: 1234, _: [789] });
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'parse modified' do
6
+ it 'parse with modifier functions' do
7
+ argv = Rationalist.parse([ '-b', '123' ], { boolean: 'b' })
8
+
9
+ argv.must_equal({
10
+ b: true,
11
+ _: [123]
12
+ })
13
+ end
14
+ end
@@ -0,0 +1,148 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'Rationalist.parse' do
6
+ it 'parses no' do
7
+ Rationalist.parse(['--no-moo']).must_equal({ moo: false, _: [] })
8
+ end
9
+
10
+ it 'parses multiple times the same option' do
11
+ Rationalist.parse(['-v', 'a', '-v', 'b', '-v', 'c']).must_equal({ v: ['a','b','c'], _: [] })
12
+ end
13
+
14
+ it 'comprehensive' do
15
+ Rationalist.parse([
16
+ '--name=meowmers', 'bare', '-cats', 'woo',
17
+ '-h', 'awesome', '--multi=quux',
18
+ '--key', 'value',
19
+ '-b', '--bool', '--no-meep', '--multi=baz',
20
+ '--', '--not-a-flag', 'eek'
21
+ ]).must_equal({
22
+ c: true,
23
+ a: true,
24
+ t: true,
25
+ s: 'woo',
26
+ h: 'awesome',
27
+ b: true,
28
+ bool: true,
29
+ key: 'value',
30
+ multi: ['quux', 'baz'],
31
+ meep: false,
32
+ name: 'meowmers',
33
+ _: ['bare', '--not-a-flag', 'eek']
34
+ })
35
+ end
36
+
37
+ it 'flag boolean' do
38
+ Rationalist.parse(['-t', 'moo'], { boolean: 't' }).must_equal({ t: true, _: ['moo'] })
39
+ end
40
+
41
+ it 'flag boolean value' do
42
+ Rationalist.parse(['--verbose', 'false', 'moo', '-t', 'true'], {
43
+ boolean: ['t', 'verbose'],
44
+ default: { verbose: true }
45
+ }).must_equal({
46
+ verbose: false,
47
+ t: true,
48
+ _: ['moo'],
49
+ })
50
+ end
51
+
52
+ it 'newlines in params' do
53
+ Rationalist.parse(['-s', "X\nX"]).must_equal({ _: [], s: "X\nX" })
54
+
55
+ # reproduce in bash:
56
+ # VALUE="new
57
+ # line"
58
+ # node program.js --s="$VALUE"
59
+ Rationalist.parse(["--s=X\nX"]).must_equal({ _: [], s: "X\nX" })
60
+ end
61
+
62
+ it 'strings' do
63
+ Rationalist.parse(['-s', '0001234'], { string: 's' })[:s].must_equal('0001234')
64
+ Rationalist.parse(['-x', '56'], { string: 'x' })[:x].must_equal('56')
65
+ end
66
+
67
+ it 'stringArgs' do
68
+ Rationalist.parse([' ', ' '], { string: '_' })[:_].must_equal(
69
+ [' ', ' ']
70
+ )
71
+ end
72
+
73
+ it 'empty strings' do
74
+ Rationalist.parse(['-s'], { string: 's' })[:s].must_equal('')
75
+ Rationalist.parse(['--str'], { string: 'str' })[:str].must_equal('')
76
+
77
+ letters = Rationalist.parse(['-art'], {
78
+ string: ['a', 't']
79
+ })
80
+ letters[:a].must_equal('')
81
+ letters[:r].must_equal(true)
82
+ letters[:t].must_equal('')
83
+ end
84
+
85
+ it 'string and alias' do
86
+ x = Rationalist.parse(['--str', '000123'], {
87
+ string: 's',
88
+ alias: { s: 'str' }
89
+ })
90
+
91
+ x[:str].must_equal('000123')
92
+ x[:s].must_equal('000123')
93
+
94
+ y = Rationalist.parse(['-s', '000123'], {
95
+ string: 'str',
96
+ alias: { str: 's' }
97
+ })
98
+
99
+ y[:str].must_equal('000123')
100
+ y[:s].must_equal('000123')
101
+ end
102
+
103
+ it 'slashBreak' do
104
+ Rationalist.parse(['-I/foo/bar/baz']).must_equal({ I: '/foo/bar/baz', _: [] })
105
+ Rationalist.parse(['-xyz/foo/bar/baz']).must_equal(
106
+ { x: true, y: true, z: '/foo/bar/baz', _: [] }
107
+ )
108
+ end
109
+
110
+ it 'alias' do
111
+ argv = Rationalist.parse(['-f', '11', '--zoom', '55'], {
112
+ alias: { z: 'zoom' }
113
+ })
114
+
115
+ argv[:zoom].must_equal(55)
116
+ argv[:z].must_equal(argv[:zoom])
117
+ argv[:f].must_equal(11)
118
+ end
119
+
120
+ it 'multiAlias' do
121
+ argv = Rationalist.parse(['-f', '11', '--zoom', '55'], {
122
+ alias: { z: ['zm', 'zoom'] }
123
+ })
124
+
125
+ argv[:zoom].must_equal(55)
126
+ argv[:z].must_equal(argv[:zoom])
127
+ argv[:z].must_equal(argv[:zm])
128
+ argv[:f].must_equal(11)
129
+ end
130
+
131
+ it 'nested dotted objects' do
132
+ argv = Rationalist.parse([
133
+ '--foo.bar', '3', '--foo.baz', '4',
134
+ '--foo.quux.quibble', '5', '--foo.quux.o_O',
135
+ '--beep.boop'
136
+ ])
137
+
138
+ argv[:foo].must_equal({
139
+ bar: 3,
140
+ baz: 4,
141
+ quux: {
142
+ quibble: 5,
143
+ o_O: true
144
+ },
145
+ })
146
+ argv[:beep].must_equal({ boop: true })
147
+ end
148
+ end
@@ -0,0 +1,48 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'short' do
6
+ it 'numeric' do
7
+ Rationalist.parse(['-n123']).must_equal({ n: 123, _: [] })
8
+ Rationalist.parse(['-123', '456']).must_equal({ 1 => true, 2 => true, 3 => 456, _: [] })
9
+ end
10
+
11
+ it 'boolean' do
12
+ Rationalist.parse(['-b']).must_equal({ b: true, _: [] })
13
+ end
14
+
15
+ it 'bare' do
16
+ Rationalist.parse(['foo', 'bar', 'baz']).must_equal({ _: ['foo', 'bar', 'baz'] })
17
+ end
18
+
19
+ it 'group' do
20
+ Rationalist.parse(['-cats']).must_equal({ c: true, a: true, t: true, s: true, _: [] })
21
+ end
22
+
23
+ it 'group next' do
24
+ Rationalist.parse(['-cats', 'meow']).must_equal({ c: true, a: true, t: true, s: 'meow', _: [] })
25
+ end
26
+
27
+ it 'short capture' do
28
+ Rationalist.parse(['-h', 'localhost']).must_equal({ h: 'localhost', _: [] })
29
+ end
30
+
31
+ it 'short captures' do
32
+ Rationalist.parse(['-h', 'localhost', '-p', '555']).must_equal({ h: 'localhost', p: 555, _: [] })
33
+ end
34
+
35
+ it 'mixed short bool and capture' do
36
+ Rationalist.parse(['-h', 'localhost', '-fp', '555', 'script.js']).must_equal({
37
+ f: true, p: 555, h: 'localhost',
38
+ _: ['script.js'],
39
+ })
40
+ end
41
+
42
+ it 'short and long' do
43
+ Rationalist.parse(['-h', 'localhost', '-fp', '555', 'script.js']).must_equal({
44
+ f: true, p: 555, h: 'localhost',
45
+ _: ['script.js'],
46
+ })
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'stop early' do
6
+ it 'stops parsing on the first non-option when stopEarly is set' do
7
+ argv = Rationalist.parse(
8
+ ['--aaa', 'bbb', 'ccc', '--ddd'],
9
+ stop_early: true,
10
+ )
11
+
12
+ argv.must_equal(
13
+ aaa: 'bbb',
14
+ _: ['ccc', '--ddd'],
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'unknown' do
6
+ it 'boolean and alias is not unknown' do
7
+ unknown = []
8
+ unknown_block = ->(arg){
9
+ unknown.push(arg)
10
+ false
11
+ }
12
+ aliased = ['-h', 'true', '--derp', 'true']
13
+ regular = ['--herp', 'true', '-d', 'true']
14
+ opts = {
15
+ alias: { h: 'herp' },
16
+ boolean: 'h',
17
+ }
18
+ aliased_argv = Rationalist.parse(aliased, opts, &unknown_block)
19
+ property_argv = Rationalist.parse(regular, opts, &unknown_block)
20
+
21
+ unknown.must_equal(['--derp', '-d'])
22
+ end
23
+
24
+ it 'flag boolean true any double hyphen argument is not unknown' do
25
+ unknown = []
26
+ unknown_block = ->(arg){
27
+ unknown.push(arg)
28
+ false
29
+ }
30
+
31
+ argv = Rationalist.parse(['--honk', '--tacos=good', 'cow', '-p', '55'], {
32
+ boolean: true,
33
+ }, &unknown_block)
34
+
35
+ unknown.must_equal(['--tacos=good', 'cow', '-p'])
36
+ argv.must_equal({
37
+ honk: true,
38
+ _: []
39
+ })
40
+ end
41
+
42
+ it 'string and alias is not unknown' do
43
+ unknown = []
44
+ unknown_block = ->(arg){
45
+ unknown.push(arg)
46
+ false
47
+ }
48
+
49
+ aliased = ['-h', 'hello', '--derp', 'goodbye']
50
+ regular = ['--herp', 'hello', '-d', 'moon']
51
+ opts = {
52
+ alias: { h: 'herp' },
53
+ string: 'h',
54
+ }
55
+
56
+ aliased_argv = Rationalist.parse(aliased, opts, &unknown_block)
57
+ property_argv = Rationalist.parse(regular, opts, &unknown_block)
58
+
59
+ unknown.must_equal(['--derp', '-d'])
60
+ end
61
+
62
+ it 'default and alias is not unknown' do
63
+ unknown = []
64
+ unknown_block = ->(arg){
65
+ unknown.push(arg)
66
+ false
67
+ }
68
+
69
+ aliased = ['-h', 'hello']
70
+ regular = ['--herp', 'hello']
71
+ opts = {
72
+ default: { h: 'bar' },
73
+ alias: { h: 'herp' },
74
+ }
75
+ aliased_argv = Rationalist.parse(aliased, opts, &unknown_block)
76
+ property_argv = Rationalist.parse(regular, opts, &unknown_block)
77
+
78
+ unknown.must_equal([])
79
+ unknown_block.call(nil) # exercise fn for 100% coverage
80
+ end
81
+
82
+ it 'value following -- is not unknown' do
83
+ unknown = []
84
+ unknown_block = ->(arg){
85
+ unknown.push(arg)
86
+ false
87
+ }
88
+
89
+ aliased = ['--bad', '--', 'good', 'arg']
90
+ opts = {
91
+ :'--' => true,
92
+ }
93
+ argv = Rationalist.parse(aliased, opts, &unknown_block)
94
+
95
+ unknown.must_equal(['--bad'])
96
+ argv.must_equal({
97
+ :'--' => ['good', 'arg'],
98
+ :_ => [],
99
+ })
100
+ end
101
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../lib/rationalist'
2
+ require 'minitest/autorun'
3
+ require 'minitest/expectations'
4
+
5
+ describe 'whitespace' do
6
+ it 'whitespace should be whitespace' do
7
+ Rationalist.parse([ '-x', "\t" ])[:x].must_equal "\t"
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rationalist
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Lelis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: parse argument options. a ruby fork of minimist.
14
+ email:
15
+ - mail@janlelis.de
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".travis.yml"
22
+ - CHANGELOG.md
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE
26
+ - README.md
27
+ - Rakefile
28
+ - example/parse.rb
29
+ - lib/rationalist.rb
30
+ - rationalist.gemspec
31
+ - spec/all_bools_spec.rb
32
+ - spec/bool_spec.rb
33
+ - spec/dash_spec.rb
34
+ - spec/default_bool_spec.rb
35
+ - spec/dotted_spec.rb
36
+ - spec/long_spec.rb
37
+ - spec/num_spec.rb
38
+ - spec/parse_modified_spec.rb
39
+ - spec/parse_spec.rb
40
+ - spec/short_spec.rb
41
+ - spec/stop_early_spec.rb
42
+ - spec/unknown_spec.rb
43
+ - spec/whitespace_spec.rb
44
+ homepage: https://github.com/janlelis/Rationalist
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '2.0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.4.6
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: parse argument options
68
+ test_files:
69
+ - spec/all_bools_spec.rb
70
+ - spec/bool_spec.rb
71
+ - spec/dash_spec.rb
72
+ - spec/default_bool_spec.rb
73
+ - spec/dotted_spec.rb
74
+ - spec/long_spec.rb
75
+ - spec/num_spec.rb
76
+ - spec/parse_modified_spec.rb
77
+ - spec/parse_spec.rb
78
+ - spec/short_spec.rb
79
+ - spec/stop_early_spec.rb
80
+ - spec/unknown_spec.rb
81
+ - spec/whitespace_spec.rb
82
+ has_rdoc: