miniparse 0.3.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/FAQ.md +38 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +76 -0
- data/Rakefile +18 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/ex01_simple.rb +22 -0
- data/examples/ex02_options.rb +27 -0
- data/examples/ex03_commands.rb +24 -0
- data/examples/ex04_mixed.rb +37 -0
- data/examples/ex05_block.rb +31 -0
- data/examples/ex06_task_app.rb +36 -0
- data/examples/ex07_controls.rb +63 -0
- data/lib/miniparse.rb +51 -0
- data/lib/miniparse/app.rb +51 -0
- data/lib/miniparse/command.rb +210 -0
- data/lib/miniparse/commander.rb +143 -0
- data/lib/miniparse/control.rb +67 -0
- data/lib/miniparse/option_broker.rb +113 -0
- data/lib/miniparse/parser.rb +136 -0
- data/lib/miniparse/version.rb +9 -0
- data/lib/miniparse/word_wrap.rb +59 -0
- data/miniparse.gemspec +34 -0
- metadata +129 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Miniparse
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
DEFAULT_CONTROLS = {
|
|
5
|
+
# gives an error if there is an unrecognized option either short or long
|
|
6
|
+
# (if not then passes them as arguments)
|
|
7
|
+
raise_on_unrecognized: true,
|
|
8
|
+
|
|
9
|
+
# intercepts .parse ArgumentError (i.e. the commandline user introduced
|
|
10
|
+
# wrong or invalid options) and exits with a helpful msg
|
|
11
|
+
rescue_argument_error: true,
|
|
12
|
+
|
|
13
|
+
# gives usage help and exits if commandline is empty
|
|
14
|
+
# useful if your app always needs args or options to work
|
|
15
|
+
help_cmdline_empty: false,
|
|
16
|
+
|
|
17
|
+
# raises an ArgumentError if there are global args
|
|
18
|
+
# (after parsing options and commands)
|
|
19
|
+
# useful if you don't expect any args
|
|
20
|
+
raise_global_args: false,
|
|
21
|
+
|
|
22
|
+
# formats help output with the width_... controls
|
|
23
|
+
formatted_help: true,
|
|
24
|
+
|
|
25
|
+
width_display: 79,
|
|
26
|
+
width_indent: 3,
|
|
27
|
+
width_left: 18,
|
|
28
|
+
|
|
29
|
+
# use a detailed options help usage msg or a generic one
|
|
30
|
+
detailed_usage: true,
|
|
31
|
+
|
|
32
|
+
# uses --no-... options for all options
|
|
33
|
+
# useful if you want all your options to be negatable by default
|
|
34
|
+
autonegatable: false,
|
|
35
|
+
|
|
36
|
+
# uses short options (besides long ones) for all options
|
|
37
|
+
# useful if you want all your options to be shortable by default
|
|
38
|
+
autoshortable: false,
|
|
39
|
+
|
|
40
|
+
# TODO: consider adding this option
|
|
41
|
+
# admits -h besides --help in help predefined option
|
|
42
|
+
# shortable_help: false,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
def self.reset_controls
|
|
46
|
+
@behaviour_controls = {}
|
|
47
|
+
@behaviour_controls.merge! DEFAULT_CONTROLS
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
self.reset_controls
|
|
51
|
+
|
|
52
|
+
# raises a KeyError if key is not a recognized control
|
|
53
|
+
# TODO consider raising SyntaxError with a custom msg instead of KeyError
|
|
54
|
+
def self.control(key)
|
|
55
|
+
@behaviour_controls.fetch(key)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# raises a KeyError if any key is not a recognized control
|
|
59
|
+
def self.set_control(opts = {})
|
|
60
|
+
opts.keys.each { |key| @behaviour_controls.fetch key }
|
|
61
|
+
@behaviour_controls.merge! opts
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Miniparse
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OptionBroker
|
|
6
|
+
|
|
7
|
+
attr_reader :parsed_values
|
|
8
|
+
|
|
9
|
+
def initialize(&block)
|
|
10
|
+
@parsed_values = {}
|
|
11
|
+
@added_options = {}
|
|
12
|
+
if block
|
|
13
|
+
add_option(spec: "--help", negatable: false, &block)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_option(args, &block)
|
|
18
|
+
opt = new_option(args, &block)
|
|
19
|
+
# FEATURE duplicate option overwrite the old one
|
|
20
|
+
# NOTE defining a switch option and a flag option with the same name doesn't work (the first one gets overwritten)
|
|
21
|
+
if opt.shortable
|
|
22
|
+
duplicate = added_options.values.collect { |o|
|
|
23
|
+
(o.shortable && o.name.to_s[0] == opt.name.to_s[0])? o.name : nil }
|
|
24
|
+
duplicate.compact!
|
|
25
|
+
unless duplicate.empty? || duplicate.include?(opt.name)
|
|
26
|
+
raise SyntaxError, "shortable option '#{opt.name}' conflicts with previously defined '" + duplicate.join(', ') + "'"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
@added_options[opt.name] = opt
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param argv is like ARGV but just for this broker
|
|
33
|
+
# @return unprocessed arguments
|
|
34
|
+
def parse_argv(argv)
|
|
35
|
+
av = argv.dup
|
|
36
|
+
rest_argv = []
|
|
37
|
+
while av.size > 0
|
|
38
|
+
arg = av.shift
|
|
39
|
+
opt = check_arg(arg)
|
|
40
|
+
if opt
|
|
41
|
+
val = opt.parse_value(arg)
|
|
42
|
+
if val.nil? && (av.size > 0) && (av[0][0] != '-')
|
|
43
|
+
new_arg = arg + "=" + av.shift
|
|
44
|
+
val = opt.parse_value(new_arg)
|
|
45
|
+
end
|
|
46
|
+
if val.nil?
|
|
47
|
+
raise ArgumentError, "#{opt.class} invalid invocation format '#{arg}'"
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
if Miniparse.control(:raise_on_unrecognized) && (arg[0] == '-')
|
|
51
|
+
raise ArgumentError, "unrecognized option '#{arg}'"
|
|
52
|
+
end
|
|
53
|
+
rest_argv << arg
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
update_parsed_values
|
|
57
|
+
rest_argv
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def help_usage
|
|
61
|
+
helps = added_options.values.collect do |opt|
|
|
62
|
+
opt.help_usage
|
|
63
|
+
end
|
|
64
|
+
helps.compact.join(" ")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def help_desc
|
|
68
|
+
helps = added_options.values.collect { |opt| opt.help_desc }
|
|
69
|
+
helps.compact.join("\n")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
protected
|
|
73
|
+
|
|
74
|
+
attr_reader :added_options
|
|
75
|
+
|
|
76
|
+
def new_option(args, &block)
|
|
77
|
+
if SwitchOption.valid_spec args[:spec]
|
|
78
|
+
SwitchOption.new(args, &block)
|
|
79
|
+
elsif FlagOption.valid_spec args[:spec]
|
|
80
|
+
FlagOption.new(args, &block)
|
|
81
|
+
else
|
|
82
|
+
raise SyntaxError,
|
|
83
|
+
"unknown or invalid option specification '#{args[:spec]}'"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def check_arg(arg)
|
|
88
|
+
match = added_options.values.collect { |opt| opt.check(arg) ? opt : nil }
|
|
89
|
+
match.compact!
|
|
90
|
+
if match.size > 1
|
|
91
|
+
# NOTE this shouldn't be happening, just a sanity check
|
|
92
|
+
names = match.collect { |opt| opt.name }
|
|
93
|
+
raise "Ambiguous options: '" + names.join(', ') + "'"
|
|
94
|
+
elsif match.size > 0
|
|
95
|
+
match[0]
|
|
96
|
+
else
|
|
97
|
+
nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def update_parsed_values
|
|
102
|
+
@parsed_values = {}
|
|
103
|
+
added_options.values.each do |opt|
|
|
104
|
+
@parsed_values[opt.name] = opt.value if opt.value != nil
|
|
105
|
+
end
|
|
106
|
+
parsed_values
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Miniparse
|
|
2
|
+
|
|
3
|
+
# TODO create external documentation, maybe auto
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Parser
|
|
7
|
+
|
|
8
|
+
# @return after parsing (i.e. specified) rest of arguments
|
|
9
|
+
attr_reader :args, :program_desc
|
|
10
|
+
# @return parsed (i.e. specified) global options
|
|
11
|
+
def options; global_broker.parsed_values; end
|
|
12
|
+
|
|
13
|
+
# @return parsed (i.e. specified) command (nil if none), options and arguments
|
|
14
|
+
def command; commander.parsed_command; end
|
|
15
|
+
def command_options; commander.parsed_values; end
|
|
16
|
+
def command_args; commander.parsed_args; end
|
|
17
|
+
|
|
18
|
+
# @return the command the next add_option will apply to
|
|
19
|
+
def current_command; commander.current_command; end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def initialize(program_description = '')
|
|
23
|
+
@global_broker = OptionBroker.new do
|
|
24
|
+
puts program_desc
|
|
25
|
+
puts help_usage
|
|
26
|
+
puts help_desc
|
|
27
|
+
exit ERR_HELP_REQ
|
|
28
|
+
end
|
|
29
|
+
@commander = Commander.new
|
|
30
|
+
@program_desc = program_description
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param spec is the option specification, similar to the option invocation
|
|
34
|
+
# in the command line (ex. "--debug" or "--verbose LEVEL")
|
|
35
|
+
#
|
|
36
|
+
# @param desc is a short description of the option
|
|
37
|
+
#
|
|
38
|
+
# @param opts are the options to apply to the option
|
|
39
|
+
# :default
|
|
40
|
+
# :negatable (used only for switches)
|
|
41
|
+
# :shortable
|
|
42
|
+
def add_option(spec, desc, opts={}, &block)
|
|
43
|
+
args = opts.merge(spec: spec, desc: desc)
|
|
44
|
+
current_broker.add_option(args, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @param name is the command name (ex. either "kill" or :kill)
|
|
48
|
+
#
|
|
49
|
+
# @param desc is a short description of the command
|
|
50
|
+
#
|
|
51
|
+
# @param opts are the options to apply to the command
|
|
52
|
+
# :no_options indicates the command has no command line options
|
|
53
|
+
def add_command(name, desc, opts={}, &block)
|
|
54
|
+
args = opts.merge(spec: name, desc: desc)
|
|
55
|
+
commander.add_command(args, &block)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @param argv is like ARGV but just for this parser
|
|
59
|
+
# @return unprocessed arguments
|
|
60
|
+
def parse(argv)
|
|
61
|
+
if Miniparse.control(:help_cmdline_empty) && argv.empty?
|
|
62
|
+
puts help_usage
|
|
63
|
+
exit ERR_HELP_REQ
|
|
64
|
+
end
|
|
65
|
+
try_argument do
|
|
66
|
+
global_argv, cmd_name, cmd_argv = commander.split_argv(argv)
|
|
67
|
+
@args = global_broker.parse_argv(global_argv)
|
|
68
|
+
if cmd_name
|
|
69
|
+
commander.parse_argv(cmd_name, cmd_argv)
|
|
70
|
+
end
|
|
71
|
+
if Miniparse.control(:raise_global_args) && (! args.empty?)
|
|
72
|
+
# FIXME review this logic later
|
|
73
|
+
error = current_command ? "unrecognized command" : "extra arguments"
|
|
74
|
+
raise ArgumentError, "#{error} '#{args[0]}'"
|
|
75
|
+
end
|
|
76
|
+
args
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @return a help message with the short descriptions
|
|
81
|
+
def help_desc
|
|
82
|
+
#FIXME
|
|
83
|
+
text = ""
|
|
84
|
+
if (global = global_broker.help_desc).size > 0
|
|
85
|
+
text += "\nOptions:\n"
|
|
86
|
+
text += global
|
|
87
|
+
end
|
|
88
|
+
text += commander.help_desc
|
|
89
|
+
text
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @return a usage message
|
|
93
|
+
def help_usage
|
|
94
|
+
#FIXME
|
|
95
|
+
if Miniparse.control(:detailed_usage)
|
|
96
|
+
right_text = @global_broker.help_usage
|
|
97
|
+
elsif current_command
|
|
98
|
+
right_text = "[global_options]"
|
|
99
|
+
else
|
|
100
|
+
right_text = "[options]"
|
|
101
|
+
end
|
|
102
|
+
if current_command
|
|
103
|
+
right_text += " <command> [command_options]"
|
|
104
|
+
end
|
|
105
|
+
right_text += " <args>"
|
|
106
|
+
Miniparse.help_usage_format(right_text)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
protected
|
|
110
|
+
|
|
111
|
+
attr_reader :commander, :global_broker
|
|
112
|
+
|
|
113
|
+
def current_broker
|
|
114
|
+
commander.current_broker || global_broker
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def try_argument
|
|
118
|
+
#FIXME
|
|
119
|
+
begin
|
|
120
|
+
yield
|
|
121
|
+
rescue ArgumentError => except
|
|
122
|
+
raise unless Miniparse.control(:rescue_argument_error)
|
|
123
|
+
prg = File.basename($PROGRAM_NAME)
|
|
124
|
+
$stderr.puts "#{prg}: error: #{except.message}"
|
|
125
|
+
$stderr.puts
|
|
126
|
+
$stderr.puts help_usage
|
|
127
|
+
# (#{except.backtrace[-1]})")
|
|
128
|
+
exit ERR_ARGUMENT
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module WordWrap
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# wrap a text at word boundaries
|
|
6
|
+
#
|
|
7
|
+
# @param text: the text to wrap
|
|
8
|
+
# @param width: the maximum width allowed for on line before inserting line breaks
|
|
9
|
+
# @param reformat: if true then the previous line breaks are removed and then the text wrappeed
|
|
10
|
+
# @return text with line breaks inserted as necessasry
|
|
11
|
+
def self.word_wrap(text, width, reformat:false)
|
|
12
|
+
text = text.gsub(/\s*\n/, ' ') if reformat
|
|
13
|
+
|
|
14
|
+
clean = (text[-1] != "\n")
|
|
15
|
+
res = text.gsub(/(.{1,#{width-1}}\S)(\s+|$)/, "\\1\n")
|
|
16
|
+
(clean)? res.chomp : res
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# same as word_wrap(...) but returns an array of lines
|
|
21
|
+
#
|
|
22
|
+
# @return an array of lines containing the rearranged text
|
|
23
|
+
def self.word_wrap_lines(*args)
|
|
24
|
+
word_wrap(*args).split("\n")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# same as two_cols_word_wrap(...) but returns an array of lines
|
|
29
|
+
#
|
|
30
|
+
# @return an array of lines containing the merged and rearranged texts
|
|
31
|
+
def self.two_cols_word_wrap_lines(text_left, separator, text_right,
|
|
32
|
+
width_left, width_right, reformat:false)
|
|
33
|
+
left = word_wrap_lines(text_left, width_left, reformat:reformat)
|
|
34
|
+
right = word_wrap_lines(text_right, width_right, reformat:reformat)
|
|
35
|
+
|
|
36
|
+
top = [left.size, right.size].max
|
|
37
|
+
lines = []
|
|
38
|
+
i = 0
|
|
39
|
+
while i < top
|
|
40
|
+
l_part = left[i] || ''
|
|
41
|
+
r_part = right[i] || ''
|
|
42
|
+
lines << "%-*s%s%s" % [width_left, l_part, separator, r_part]
|
|
43
|
+
i += 1
|
|
44
|
+
end
|
|
45
|
+
lines
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# wrap two texts in two separate columms
|
|
50
|
+
#
|
|
51
|
+
# @param separator: a string of characters inserted at every line between the two collums, for example ' ' or ' | '
|
|
52
|
+
# @return text with line breaks inserted as necessary
|
|
53
|
+
def self.two_cols_word_wrap(*args)
|
|
54
|
+
two_cols_word_wrap_lines(*args).join("\n")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
end
|
data/miniparse.gemspec
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'miniparse/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "miniparse"
|
|
8
|
+
spec.version = Miniparse::VERSION
|
|
9
|
+
spec.authors = ["Juanma Rodriguez"]
|
|
10
|
+
spec.email = ["jmrod4@gmail.com"]
|
|
11
|
+
|
|
12
|
+
spec.summary = %q{Miniparse is a easy to use yet flexible and powerful ruby library for parsing command-line options.}
|
|
13
|
+
# spec.description = %q{TODO: Write a longer description or delete this line.}
|
|
14
|
+
spec.homepage = "https://github.com/jmrod4/miniparse"
|
|
15
|
+
spec.license = "MIT"
|
|
16
|
+
|
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
|
19
|
+
# if spec.respond_to?(:metadata)
|
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
|
21
|
+
# else
|
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
spec.bindir = "exe"
|
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
+
spec.require_paths = ["lib"]
|
|
29
|
+
|
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
32
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
34
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: miniparse
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Juanma Rodriguez
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-03-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.11'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.11'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '5.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '5.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
description:
|
|
70
|
+
email:
|
|
71
|
+
- jmrod4@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- ".rspec"
|
|
78
|
+
- ".travis.yml"
|
|
79
|
+
- FAQ.md
|
|
80
|
+
- Gemfile
|
|
81
|
+
- LICENSE.txt
|
|
82
|
+
- README.md
|
|
83
|
+
- Rakefile
|
|
84
|
+
- bin/console
|
|
85
|
+
- bin/setup
|
|
86
|
+
- examples/ex01_simple.rb
|
|
87
|
+
- examples/ex02_options.rb
|
|
88
|
+
- examples/ex03_commands.rb
|
|
89
|
+
- examples/ex04_mixed.rb
|
|
90
|
+
- examples/ex05_block.rb
|
|
91
|
+
- examples/ex06_task_app.rb
|
|
92
|
+
- examples/ex07_controls.rb
|
|
93
|
+
- lib/miniparse.rb
|
|
94
|
+
- lib/miniparse/app.rb
|
|
95
|
+
- lib/miniparse/command.rb
|
|
96
|
+
- lib/miniparse/commander.rb
|
|
97
|
+
- lib/miniparse/control.rb
|
|
98
|
+
- lib/miniparse/option_broker.rb
|
|
99
|
+
- lib/miniparse/parser.rb
|
|
100
|
+
- lib/miniparse/version.rb
|
|
101
|
+
- lib/miniparse/word_wrap.rb
|
|
102
|
+
- miniparse.gemspec
|
|
103
|
+
homepage: https://github.com/jmrod4/miniparse
|
|
104
|
+
licenses:
|
|
105
|
+
- MIT
|
|
106
|
+
metadata: {}
|
|
107
|
+
post_install_message:
|
|
108
|
+
rdoc_options: []
|
|
109
|
+
require_paths:
|
|
110
|
+
- lib
|
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '0'
|
|
121
|
+
requirements: []
|
|
122
|
+
rubyforge_project:
|
|
123
|
+
rubygems_version: 2.4.8
|
|
124
|
+
signing_key:
|
|
125
|
+
specification_version: 4
|
|
126
|
+
summary: Miniparse is a easy to use yet flexible and powerful ruby library for parsing
|
|
127
|
+
command-line options.
|
|
128
|
+
test_files: []
|
|
129
|
+
has_rdoc:
|