rationalist 2.0.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.
@@ -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: