mini-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3f71b96747e645a7e4ab1131c3e52840f63f22af4035d06b98f2d21172716d9b
4
+ data.tar.gz: a8ec28b1326a313f16ec8986f85a56b60f1b8c9832583324b79fd6a55c6a6228
5
+ SHA512:
6
+ metadata.gz: 72575dc73beedd924a2080b8cb436dcb11b78d9897e4f9eb87836dff6af028845d077c069540b06a5b7b93c6a2719c2de3a53a4e19996476a8c5871332fe97bb
7
+ data.tar.gz: 6848f5981ef7ce5bb4545a015b309f549450796a5d6530f4fd0f56fd3c315e7347da2afa318048facdb077db0eeee21676cd305b5cd17a863cb2037f5323cf32
@@ -0,0 +1,4 @@
1
+ idea/
2
+ tmp/
3
+ pkg/
4
+ gems.locked
@@ -0,0 +1,64 @@
1
+ # Mini Cli
2
+
3
+ This gem is a minimalistic, easy to use CLI framework with a very small footprint. I provides an easy to use argument parsing, help displaying, minimalistic error handling and some tools like executing external programs and gather their output.
4
+
5
+ ## Installation
6
+
7
+ To use Mini CLI just install the gem with
8
+
9
+ ```shell
10
+ gem install mini-cli
11
+ ```
12
+
13
+ or include it to you project's gemspec:
14
+
15
+ ```ruby
16
+ gem 'mini-cli'
17
+ ```
18
+
19
+ ## Sample
20
+
21
+ A very minimalistic program may look like this sample program:
22
+
23
+ ```ruby
24
+ require 'mini-cli'
25
+
26
+ include MiniCli
27
+
28
+ help <<~HELP, %w[TARGET [SOURCE]]
29
+ -n, --name NAME option requires NAME argument, has shortcut
30
+ --url URL option requires URL argument
31
+ -s, --switch option without any argument, has shortcut
32
+ --opt option without any argument
33
+
34
+ This is a sample application only.
35
+ HELP
36
+
37
+ main do |args|
38
+ puts "TARGET: #{args['TARGET']}"
39
+ puts "SOURCE: #{args['SOURCE']}" if args.key?('SOURCE')
40
+ puts "NAME: #{args['NAME']}" if args.key?('NAME')
41
+ puts "URL: #{args['URL']}" if args.key?('URL')
42
+ puts "FILES: #{args['FILES']}" unless args['FILES'].empty?
43
+ puts '--switch was given' if args.key?('switch')
44
+ puts '--opt was given' if args.key?('opt')
45
+ end
46
+ ```
47
+
48
+ The sample uses the powerful `#help` method to generate an argument parser which handles the command line for you. You only need to handle the given `Hash` parameter (named `args` in the sample) in the body of your `#main` block.
49
+
50
+ Executing the sample with `--help` or `-h` will provide following help screen:
51
+
52
+ ```
53
+ Usage: sample [OPTIONS] TARGET [SOURCE]
54
+
55
+ Valid Options:
56
+ -n, --name NAME option requires NAME argument, has shortcut
57
+ --url URL option requires URL argument
58
+ -s, --switch option without any argument, has shortcut
59
+ --opt option without any argument
60
+
61
+ This is a sample application only.
62
+ ```
63
+
64
+ See the `./samples` directory for more sample programs…
data/gems.rb ADDED
@@ -0,0 +1 @@
1
+ gemspec
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniCli
4
+ def self.included(_)
5
+ return if const_defined?(:SRC)
6
+ const_set(:SRC, caller_locations(1, 1).first.absolute_path)
7
+ end
8
+
9
+ def name(name = nil)
10
+ return name ? @__name = name : @__name if defined?(@__name)
11
+ @__name = name || File.basename(MiniCli::SRC, '.*')
12
+ end
13
+
14
+ def help(helptext, *args)
15
+ @__argv_parser = ArgvParser.new(helptext, args)
16
+ end
17
+
18
+ def show_help
19
+ __argv_parser.show_help(name)
20
+ true
21
+ end
22
+
23
+ def error(code, message)
24
+ $stderr.puts("#{name}: #{message}")
25
+ exit(code)
26
+ end
27
+
28
+ def parse_argv(argv = nil, &block)
29
+ return @__argv_converter = block if block
30
+ argv ||= ARGV.dup
31
+ exit(show_help) if argv.index('--help') || argv.index('-h')
32
+ args = __argv_parser.parse(argv, method(:error).to_proc)
33
+ defined?(@__argv_converter) ? @__argv_converter.call(args) || args : args
34
+ end
35
+
36
+ def main(args = nil)
37
+ at_exit do
38
+ yield(args || parse_argv)
39
+ rescue Interrupt
40
+ error(130, 'aborted')
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def __argv_parser
47
+ @__argv_parser ||= ArgvParser.new(nil, [])
48
+ end
49
+
50
+ class ArgvParser
51
+ def initialize(helptext, args)
52
+ @helptext = helptext.to_s
53
+ @args = args.flatten.map!(&:to_s).uniq
54
+ @options = nil
55
+ end
56
+
57
+ def show_help(name)
58
+ parse_help! unless @options
59
+ print("Usage: #{name}")
60
+ print(' [OPTIONS]') unless @options.empty?
61
+ print(' ', @args.join(' ')) unless @args.empty?
62
+ puts
63
+ puts(nil, 'Valid Options:') unless @options.empty?
64
+ puts(@helptext) unless @helptext.empty?
65
+ end
66
+
67
+ def parse(argv, error)
68
+ @error = error
69
+ parse_help! unless @options
70
+ @result, arguments = {}, []
71
+ loop do
72
+ case arg = argv.shift
73
+ when nil
74
+ break
75
+ when '--'
76
+ arguments += argv
77
+ break
78
+ when /\A--([[[:alnum:]]-]+)\z/
79
+ handle_option(Regexp.last_match[1], argv)
80
+ when /\A-([[:alnum:]]+)\z/
81
+ parse_options(Regexp.last_match[1], argv)
82
+ else
83
+ arguments << arg
84
+ end
85
+ end
86
+ process(arguments)
87
+ end
88
+
89
+ private
90
+
91
+ def error(msg)
92
+ @error.call(1, msg)
93
+ end
94
+
95
+ def process(arguments)
96
+ @args.each do |arg|
97
+ next if arg.index('..')
98
+ value = arguments.shift
99
+ if arg.start_with?('[')
100
+ @result[arg[1..-2]] = value if value
101
+ else
102
+ @result[arg] = value || error("parameter expected - #{arg}")
103
+ end
104
+ end
105
+ arguments.unshift(@result['FILES']) if @result.key?('FILES')
106
+ @result['FILES'] = arguments
107
+ @result
108
+ end
109
+
110
+ def handle_option(option, argv)
111
+ key = @options[option] || error("unknown option - #{option}")
112
+ return @result[key] = true if option == key
113
+ @result[key] = value = argv.shift
114
+ return unless value.nil? || value.start_with?('-')
115
+ error("parameter #{key} expected - --#{option}")
116
+ end
117
+
118
+ def parse_options(options, argv)
119
+ options.each_char do |opt|
120
+ key = @options[opt] || error("unknown option - #{opt}")
121
+ next @result[key] = true if key == key.downcase
122
+ @result[key] = value = argv.shift
123
+ next unless value.nil? || value.start_with?('-')
124
+ error("parameter #{key} expected - -#{opt}")
125
+ end
126
+ end
127
+
128
+ def parse_help!
129
+ @options = {}
130
+ @helptext.each_line do |line|
131
+ case line
132
+ when /-([[:alnum:]]), --([[[:alnum:]]-]+) ([[:upper:]]+)\s+\S+/
133
+ named_option(Regexp.last_match)
134
+ when /--([[[:alnum:]]-]+) ([[:upper:]]+)\s+\S+/
135
+ named_option_short(Regexp.last_match)
136
+ when /-([[:alnum:]]), --([[[:alnum:]]-]+)\s+\S+/
137
+ option(Regexp.last_match)
138
+ when /--([[[:alnum:]]-]+)\s+\S+/
139
+ option_short(Regexp.last_match)
140
+ end
141
+ end
142
+ end
143
+
144
+ def named_option(match)
145
+ @options[match[1]] = @options[match[2]] = match[3]
146
+ end
147
+
148
+ def named_option_short(match)
149
+ @options[match[1]] = match[2]
150
+ end
151
+
152
+ def option(match)
153
+ @options[match[1]] = @options[match[2]] = match[2]
154
+ end
155
+
156
+ def option_short(match)
157
+ @options[match[1]] = match[1]
158
+ end
159
+ end
160
+
161
+ private_constant(:ArgvParser)
162
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module MiniCli
6
+ def run(*cmd)
7
+ opts = Hash === cmd.last ? __run_opt(cmd.last) : [:stdout]
8
+ opts.delete(:stderr) ? __run3(opts, cmd) : __run2(opts, cmd)
9
+ rescue SystemCallError
10
+ nil
11
+ end
12
+
13
+ private
14
+
15
+ def __run3(opts, cmd)
16
+ result = Open3.capture3(*cmd)
17
+ result.shift unless opts.first == :stdout
18
+ result.pop unless opts.last == :status
19
+ result.size == 1 ? result.first : result
20
+ end
21
+
22
+ def __run2(opts, cmd)
23
+ result = Open3.capture2e(*cmd)
24
+ return result.last.success? if opts.empty?
25
+ return result if opts.size == 2
26
+ opts.first == :status ? result.last : result.first
27
+ end
28
+
29
+ def __run_opt(opts)
30
+ %i[stdout stderr status].keep_if{ |s| opts.delete(s) }
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniCli
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './lib/mini-cli/version'
4
+
5
+ GemSpec = Gem::Specification.new do |gem|
6
+ gem.name = 'mini-cli'
7
+ gem.version = MiniCli::VERSION
8
+ gem.summary = 'The minimalistic CLI framework for Ruby'
9
+ gem.description = <<~DESC
10
+ This gem is a minimalistic, easy to use CLI framework with a very small
11
+ footprint. I provides an easy to use argument parsing, help displaying and
12
+ minimalistic error handling.
13
+ DESC
14
+ gem.author = 'Mike Blumtritt'
15
+ gem.homepage = 'https://github.com/mblumtritt/mini-cli'
16
+ gem.metadata = {
17
+ 'source_code_uri' => 'https://github.com/mblumtritt/mini-cli',
18
+ 'bug_tracker_uri' => 'https://github.com/mblumtritt/mini-cli/issues'
19
+ }
20
+
21
+ gem.required_ruby_version = '>= 2.5.0'
22
+
23
+ gem.add_development_dependency 'bundler'
24
+ gem.add_development_dependency 'minitest'
25
+ gem.add_development_dependency 'rake'
26
+
27
+ all_files = %x(git ls-files -z).split(0.chr)
28
+ gem.test_files = all_files.grep(%r{^(spec|test)/})
29
+ gem.files = all_files - gem.test_files
30
+ # gem.extra_rdoc_files = %w[README.MD]
31
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+ require 'bundler/gem_tasks'
5
+
6
+ STDOUT.sync = STDERR.sync = true
7
+
8
+ CLOBBER << 'prj'
9
+
10
+ task :default do
11
+ exec "#{$PROGRAM_NAME} --tasks"
12
+ end
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.ruby_opts = %w[-w]
16
+ t.verbose = true
17
+ t.test_files = FileList['test/**/*_test.rb']
18
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/mini-cli'
4
+
5
+ include MiniCli
6
+
7
+ help <<~HELP, %w[TARGET [SOURCE]]
8
+ -n, --name NAME option requires NAME argument, has shortcut
9
+ --url URL option requires URL argument
10
+ -s, --switch option without any argument, has shortcut
11
+ --opt option without any argument
12
+ HELP
13
+
14
+ main do |cfg|
15
+ cfg.each_pair{ |key, value| puts("#{key}: #{value}") }
16
+ end
17
+
18
+ parse_argv do |args|
19
+ Struct.new(:target, :sources, :name, :url, :switch, :opt).new.tap do |cfg|
20
+ cfg.target = args['TARGET']
21
+ # args['FILES'] is an array containing all surplus arguments
22
+ cfg.sources = args['FILES']
23
+ source = args['SOURCE'] || ENV['SOURCE']
24
+ cfg.sources.unshift(source) if source
25
+ cfg.sources << 'STDIN' if cfg.sources.empty?
26
+ cfg.name = args['NAME'] || 'default_name'
27
+ cfg.url = args['URL'] || 'www.url.test'
28
+ cfg.switch = args.key?('switch')
29
+ cfg.opt = args.key?('opt')
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/mini-cli'
4
+
5
+ include MiniCli
6
+
7
+ help <<~HELP, %w[TARGET [SOURCE]]
8
+ -n, --name NAME option requires NAME argument, has shortcut
9
+ --url URL option requires URL argument
10
+ -s, --switch option without any argument, has shortcut
11
+ --opt option without any argument
12
+ HELP
13
+
14
+ main do |args|
15
+ puts("TARGET: #{args['TARGET']}")
16
+ puts("SOURCE: #{args['SOURCE']}") if args.key?('SOURCE')
17
+ puts("NAME: #{args['NAME']}") if args.key?('NAME')
18
+ puts("URL: #{args['URL']}") if args.key?('URL')
19
+ puts("FILES: #{args['FILES']}") unless args['FILES'].empty?
20
+ puts('--switch was given') if args.key?('switch')
21
+ puts('--opt was given') if args.key?('opt')
22
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/mini-cli'
4
+
5
+ include MiniCli
6
+
7
+ help <<~HELP
8
+
9
+ This is a very simple sample without any required parameter.
10
+ HELP
11
+
12
+ main do |args|
13
+ puts("given files: #{args['FILES']}")
14
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'minitest/parallel'
5
+
6
+ require_relative '../lib/mini-cli'
7
+ require_relative '../lib/mini-cli/run'
8
+
9
+ class Test < Minitest::Test
10
+ parallelize_me!
11
+ attr_reader :subject
12
+
13
+ def setup
14
+ @subject = Class.new do
15
+ include MiniCli
16
+ attr_reader :exit_args
17
+
18
+ def exit(*args)
19
+ @exit_args = args
20
+ end
21
+ end.new
22
+ end
23
+
24
+ def assert_stop_with_error(code, text, &block)
25
+ assert_output(nil, "helper: #{text}\n", &block)
26
+ assert_equal([code], subject.exit_args)
27
+ end
28
+
29
+ def as_argv(str)
30
+ str.split(' ')
31
+ end
32
+ end
@@ -0,0 +1,178 @@
1
+ require_relative '../helper'
2
+
3
+ class MainTest < Test
4
+ def test_defaults
5
+ assert_equal('helper', subject.name)
6
+ assert_output("Usage: helper\n"){ subject.show_help }
7
+ end
8
+
9
+ def test_methods
10
+ subject = Class.new{ include MiniCli }.new
11
+
12
+ expected_methods = %i[
13
+ error
14
+ help
15
+ main
16
+ name
17
+ parse_argv
18
+ run
19
+ show_help
20
+ ].sort!
21
+ methods = (subject.methods - Object.new.methods).sort!
22
+ assert_equal(expected_methods, methods)
23
+ end
24
+
25
+ def test_error
26
+ assert_stop_with_error(42, 'some error text') do
27
+ subject.error(42, 'some error text')
28
+ end
29
+
30
+ assert_stop_with_error(21, 'error') do
31
+ subject.error(21, :error)
32
+ end
33
+ end
34
+
35
+ def test_help_simple
36
+ subject.help 'Some helptext'
37
+ expected_text = <<~EXPECTED
38
+ Usage: helper
39
+ Some helptext
40
+ EXPECTED
41
+
42
+ assert_output(expected_text){ subject.show_help }
43
+ end
44
+
45
+ def test_help_with_args
46
+ subject.help <<~HELP, 'ARG1', :ARG2
47
+ Some helptext comes
48
+ here
49
+ HELP
50
+
51
+ expected_text = <<~EXPECTED
52
+ Usage: helper ARG1 ARG2
53
+ Some helptext comes
54
+ here
55
+ EXPECTED
56
+
57
+ assert_output(expected_text){ subject.show_help }
58
+ end
59
+
60
+ def test_argument_required
61
+ subject.help :text, :ARG
62
+
63
+ assert_stop_with_error(1, 'parameter expected - ARG') do
64
+ subject.parse_argv(as_argv(''))
65
+ end
66
+
67
+ expected = {'ARG' => 'arg', 'FILES' => []}
68
+ assert_equal(expected, subject.parse_argv(as_argv('arg')))
69
+
70
+ expected = {'ARG' => 'arg1', 'FILES' => %w[arg2 arg3]}
71
+ assert_equal(expected, subject.parse_argv(as_argv('arg1 arg2 arg3')))
72
+ end
73
+
74
+ def test_name
75
+ subject.name 'test-42'
76
+ assert_equal('test-42', subject.name)
77
+ end
78
+
79
+ def test_argument_optional
80
+ subject.help :text, 'ARG1', '[ARG2]'
81
+
82
+ assert_stop_with_error(1, 'parameter expected - ARG1') do
83
+ subject.parse_argv(as_argv(''))
84
+ end
85
+
86
+ expected = {'ARG1' => 'arg1', 'ARG2' => 'arg2', 'FILES' => []}
87
+ assert_equal(expected, subject.parse_argv(as_argv('arg1 arg2')))
88
+
89
+ expected = {'ARG1' => 'arg', 'FILES' => []}
90
+ assert_equal(expected, subject.parse_argv(as_argv('arg')))
91
+ end
92
+
93
+ def test_options
94
+ subject.help <<~HELP
95
+ -n, --named NAME option NAME with shortcut
96
+ --named-long LNAME option LNAME without shortcut
97
+ -u, --unnamed option unnamed with shortcut
98
+ --un-named option un-named without shortcut
99
+
100
+ Some additional explaination can be here
101
+ HELP
102
+
103
+ expected = {'FILES' => []}
104
+ assert_equal(expected, subject.parse_argv(as_argv('')))
105
+
106
+ expected = {'NAME' => 'name', 'FILES' => []}
107
+ assert_equal(expected, subject.parse_argv(as_argv('--named name')))
108
+ assert_equal(expected, subject.parse_argv(as_argv('-n name')))
109
+
110
+ expected = {'LNAME' => 'long', 'FILES' => []}
111
+ assert_equal(expected, subject.parse_argv(as_argv('--named-long long')))
112
+
113
+ expected = {'unnamed' => true, 'FILES' => []}
114
+ assert_equal(expected, subject.parse_argv(as_argv('--unnamed')))
115
+ assert_equal(expected, subject.parse_argv(as_argv('-u')))
116
+
117
+ expected = {'un-named' => true, 'FILES' => []}
118
+ assert_equal(expected, subject.parse_argv(as_argv('--un-named')))
119
+
120
+ expected = {
121
+ 'NAME' => 'name',
122
+ 'LNAME' => 'long',
123
+ 'unnamed' => true,
124
+ 'un-named' => true,
125
+ 'FILES' => %w[FILE1 FILE2]
126
+ }
127
+
128
+ result = subject.parse_argv(%w[
129
+ --named name
130
+ --named-long long
131
+ --unnamed
132
+ --un-named
133
+ FILE1
134
+ FILE2
135
+ ])
136
+ assert_equal(expected, result)
137
+
138
+ result = subject.parse_argv(%w[
139
+ -nu name
140
+ --named-long long
141
+ --un-named
142
+ FILE1
143
+ FILE2
144
+ ])
145
+ assert_equal(expected, result)
146
+ end
147
+
148
+ def test_complex_options
149
+ subject.help <<~HELP, %w[INFILE OUTFILE [OPTFILE]]
150
+ -n, --named NAME key 'NAME'
151
+ -p, --port PORT key 'PORT'
152
+ -u, --un-named key 'unnamed'
153
+ HELP
154
+
155
+ expected = {
156
+ 'INFILE' => 'in',
157
+ 'OUTFILE' => 'out',
158
+ 'NAME' => 'name',
159
+ 'PORT' => 'port',
160
+ 'un-named' => true,
161
+ 'FILES' => []
162
+ }
163
+ result = subject.parse_argv(as_argv('-nup name port in out'))
164
+ assert_equal(expected, result)
165
+
166
+ expected = {
167
+ 'INFILE' => 'in',
168
+ 'OUTFILE' => 'out',
169
+ 'OPTFILE' => 'opt',
170
+ 'NAME' => 'name',
171
+ 'PORT' => 'port',
172
+ 'un-named' => true,
173
+ 'FILES' => %w[file]
174
+ }
175
+ result = subject.parse_argv(as_argv('-nup name port in out opt file'))
176
+ assert_equal(expected, result)
177
+ end
178
+ end
@@ -0,0 +1,48 @@
1
+ require_relative '../helper'
2
+
3
+ class RunTest < Test
4
+ def setup
5
+ super
6
+ @pwd = Dir.pwd + "\n"
7
+ end
8
+
9
+ def test_std_out_only
10
+ out = subject.run('pwd')
11
+ assert_equal(@pwd, out)
12
+
13
+ out = subject.run('pwd', stdout: true)
14
+ assert_equal(@pwd, out)
15
+ end
16
+
17
+ def test_status
18
+ result = subject.run('pwd', stdout: false)
19
+ assert_instance_of(TrueClass, result)
20
+
21
+ status = subject.run('pwd', status: true)
22
+ assert_instance_of(Process::Status, status)
23
+
24
+ out, status = subject.run('pwd', stdout: true, status: true)
25
+ assert_equal(@pwd, out)
26
+ assert_instance_of(Process::Status, status)
27
+ assert(status.success?)
28
+ end
29
+
30
+ def test_std_error
31
+ err = subject.run('ls /no-valid-dir', stderr: true)
32
+ assert_match(/No such file or directory/, err)
33
+
34
+ out, err = subject.run('ls /no-valid-dir', stdout: true, stderr: true)
35
+ assert_empty(out)
36
+ assert_match(/No such file or directory/, err)
37
+
38
+ err, status = subject.run('ls /no-valid-dir', stderr: true, status: true)
39
+ assert_match(/No such file or directory/, err)
40
+ assert_instance_of(Process::Status, status)
41
+ refute(status.success?)
42
+ end
43
+
44
+ def test_failure
45
+ result = subject.run('this-is-not-a-valid-command')
46
+ assert_instance_of(NilClass, result)
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mike Blumtritt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-08 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |
56
+ This gem is a minimalistic, easy to use CLI framework with a very small
57
+ footprint. I provides an easy to use argument parsing, help displaying and
58
+ minimalistic error handling.
59
+ email:
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - README.md
66
+ - gems.rb
67
+ - lib/mini-cli.rb
68
+ - lib/mini-cli/run.rb
69
+ - lib/mini-cli/version.rb
70
+ - mini-cli.gemspec
71
+ - rakefile.rb
72
+ - samples/custom_args.rb
73
+ - samples/demo.rb
74
+ - samples/simple.rb
75
+ - test/helper.rb
76
+ - test/mini-cli/main_test.rb
77
+ - test/mini-cli/run_test.rb
78
+ homepage: https://github.com/mblumtritt/mini-cli
79
+ licenses: []
80
+ metadata:
81
+ source_code_uri: https://github.com/mblumtritt/mini-cli
82
+ bug_tracker_uri: https://github.com/mblumtritt/mini-cli/issues
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 2.5.0
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.1.2
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: The minimalistic CLI framework for Ruby
102
+ test_files:
103
+ - test/helper.rb
104
+ - test/mini-cli/main_test.rb
105
+ - test/mini-cli/run_test.rb