mini-cli 0.3.0 → 0.6.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 +4 -4
- data/lib/mini-cli/run.rb +19 -0
- data/lib/mini-cli/version.rb +1 -1
- data/lib/mini-cli.rb +86 -42
- data/mini-cli.gemspec +19 -19
- data/rakefile.rb +3 -5
- data/samples/custom_args.rb +25 -16
- data/samples/demo.rb +15 -9
- data/test/apps/noop.rb +6 -0
- data/test/apps/sequence.rb +26 -0
- data/test/mini-cli/exec_test.rb +94 -0
- data/test/mini-cli/main_test.rb +14 -0
- data/test/mini-cli/ruby_run_test.rb +43 -0
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 287658b0aa4ac5340cde3aced9e0a411ed6504713c18505706ad741c7c966a8b
|
4
|
+
data.tar.gz: 7b6c95ddc87554a011c3f28355f3e181a7be249432d906861a92092978f5b22b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fa1fb33a71928b5fea02349709ba6191992b5375b690a8b39fe8dcb8b932932abe61f02135ca747bf729c0ed758276f7d9b3f41f42a2db1f128ee56eeda1bcb
|
7
|
+
data.tar.gz: fb7397ede3cf0f0265dbafd47ef4e070153a37e3afdf5a583b68ea95dd4482e7c54522af941bdba45680ab195e0b305b286bac1c241e27b741162bb28822fcb2
|
data/lib/mini-cli/run.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require('shellwords')
|
4
|
+
|
3
5
|
module MiniCli
|
4
6
|
def run(*cmd, stdin_data: nil, status: false, chdir: nil)
|
5
7
|
in_read, in_write = IO.pipe
|
@@ -14,6 +16,14 @@ module MiniCli
|
|
14
16
|
in_write&.close
|
15
17
|
end
|
16
18
|
|
19
|
+
def run_ruby(*cmd, **run_options)
|
20
|
+
run(Shellwords.join(__ruby_cmd + cmd), **run_options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_script(script, status: false, chdir: nil)
|
24
|
+
run_ruby(stdin_data: script, status: status, chdir: chdir)
|
25
|
+
end
|
26
|
+
|
17
27
|
private
|
18
28
|
|
19
29
|
def __run_proc(stdin_data, in_write)
|
@@ -29,4 +39,13 @@ module MiniCli
|
|
29
39
|
out.read
|
30
40
|
end
|
31
41
|
end
|
42
|
+
|
43
|
+
def __ruby_cmd
|
44
|
+
[
|
45
|
+
RbConfig.ruby,
|
46
|
+
'--disable=gems',
|
47
|
+
'--disable=did_you_mean',
|
48
|
+
'--disable=rubyopt'
|
49
|
+
]
|
50
|
+
end
|
32
51
|
end
|
data/lib/mini-cli/version.rb
CHANGED
data/lib/mini-cli.rb
CHANGED
@@ -2,8 +2,11 @@
|
|
2
2
|
|
3
3
|
module MiniCli
|
4
4
|
def self.included(mod)
|
5
|
-
|
6
|
-
|
5
|
+
mod.const_set(
|
6
|
+
:MiniCli__,
|
7
|
+
Instance.new(caller_locations(1, 1).first.absolute_path)
|
8
|
+
)
|
9
|
+
mod.private_constant(:MiniCli__)
|
7
10
|
end
|
8
11
|
|
9
12
|
def name(name = nil)
|
@@ -26,50 +29,68 @@ module MiniCli
|
|
26
29
|
__minicli__.show_errors = value ? true : false
|
27
30
|
end
|
28
31
|
|
32
|
+
def error_code
|
33
|
+
__minicli__.error_code
|
34
|
+
end
|
35
|
+
|
29
36
|
def error(code, message = nil)
|
30
37
|
$stderr.puts("#{name}: #{message}") if message && show_errors?
|
31
|
-
exit(code)
|
38
|
+
exit(__minicli__.error_code = code)
|
32
39
|
end
|
33
40
|
|
34
41
|
def parse_argv(argv = nil, &argv_converter)
|
35
42
|
return __minicli__.converter = argv_converter if argv_converter
|
36
|
-
argv
|
43
|
+
argv = Array.new(argv || ARGV)
|
37
44
|
exit(show_help) if argv.index('--help') || argv.index('-h')
|
38
|
-
__minicli__.
|
45
|
+
__minicli__.main(argv, method(:error).to_proc)
|
39
46
|
end
|
40
47
|
|
41
|
-
def main
|
42
|
-
|
43
|
-
yield(
|
48
|
+
def main
|
49
|
+
__minicli__.run do
|
50
|
+
yield(parse_argv)
|
44
51
|
rescue Interrupt
|
45
52
|
error(130, 'aborted')
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
56
|
+
def before(&callback)
|
57
|
+
callback and __minicli__.before << callback
|
58
|
+
end
|
59
|
+
|
60
|
+
def after(&callback)
|
61
|
+
callback and __minicli__.after << callback
|
62
|
+
end
|
63
|
+
|
49
64
|
private
|
50
65
|
|
51
66
|
def __minicli__
|
52
|
-
self.class
|
67
|
+
self.class.const_get(:MiniCli__)
|
53
68
|
end
|
54
69
|
|
55
70
|
class Instance
|
56
71
|
attr_reader :source
|
57
72
|
attr_writer :converter
|
58
|
-
attr_accessor :show_errors
|
73
|
+
attr_accessor :show_errors, :before, :after, :error_code
|
59
74
|
|
60
75
|
def initialize(source)
|
61
76
|
@source = source
|
62
77
|
@name = File.basename(source, '.*')
|
63
|
-
@
|
78
|
+
@converter = @main_proc = nil
|
79
|
+
@parser = ArgvParser.new('', [])
|
80
|
+
@before = []
|
81
|
+
@after = []
|
64
82
|
@show_errors = true
|
83
|
+
@before_ok = false
|
84
|
+
@error_code = 0
|
85
|
+
init_main
|
65
86
|
end
|
66
87
|
|
67
|
-
def name(name
|
88
|
+
def name(name)
|
68
89
|
name ? @name = name.to_s : @name
|
69
90
|
end
|
70
91
|
|
71
|
-
def help(
|
72
|
-
@parser = ArgvParser.new(
|
92
|
+
def help(*args)
|
93
|
+
@parser = ArgvParser.new(*args)
|
73
94
|
end
|
74
95
|
|
75
96
|
def show_help
|
@@ -77,18 +98,35 @@ module MiniCli
|
|
77
98
|
true
|
78
99
|
end
|
79
100
|
|
80
|
-
def
|
81
|
-
|
101
|
+
def run(&main_proc)
|
102
|
+
@main_proc = main_proc
|
82
103
|
end
|
83
104
|
|
84
|
-
def
|
105
|
+
def main(argv, error)
|
106
|
+
@before.each(&:call)
|
107
|
+
@before_ok = true
|
108
|
+
args = parser.parse(argv, error)
|
85
109
|
@converter ? @converter.call(args) || args : args
|
86
110
|
end
|
87
111
|
|
88
112
|
private
|
89
113
|
|
90
|
-
|
91
|
-
|
114
|
+
attr_reader :parser
|
115
|
+
|
116
|
+
def init_main
|
117
|
+
at_exit do
|
118
|
+
next if $! and not ($!.kind_of?(SystemExit) and $!.success?)
|
119
|
+
shutdown unless @after.empty?
|
120
|
+
@main_proc&.call
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def shutdown(pid = Process.pid)
|
125
|
+
at_exit do
|
126
|
+
next if Process.pid != pid
|
127
|
+
@after.reverse_each(&:call) if @before_ok
|
128
|
+
exit(@error_code)
|
129
|
+
end
|
92
130
|
end
|
93
131
|
|
94
132
|
class ArgvParser
|
@@ -96,16 +134,17 @@ module MiniCli
|
|
96
134
|
@helptext = helptext.to_s
|
97
135
|
@args = args.flatten.map!(&:to_s).uniq
|
98
136
|
@options = nil
|
137
|
+
@show_options_text = true
|
99
138
|
end
|
100
139
|
|
101
140
|
def show_help(name)
|
102
141
|
parse_help! unless @options
|
103
142
|
print("Usage: #{name}")
|
104
|
-
print(' [
|
143
|
+
print(' [<options>]') unless @options.empty?
|
105
144
|
print(' ', @args.join(' ')) unless @args.empty?
|
106
145
|
puts
|
107
|
-
puts(nil, 'Options:')
|
108
|
-
puts(@helptext) unless @helptext.empty?
|
146
|
+
puts(nil, 'Options:') if @show_options_text
|
147
|
+
puts(@helptext.gsub('<*name*>', name)) unless @helptext.empty?
|
109
148
|
end
|
110
149
|
|
111
150
|
def parse(argv, error)
|
@@ -116,13 +155,16 @@ module MiniCli
|
|
116
155
|
|
117
156
|
private
|
118
157
|
|
158
|
+
def error(msg)
|
159
|
+
@error[1, msg]
|
160
|
+
end
|
161
|
+
|
119
162
|
def parse_argv(argv)
|
120
163
|
arguments = []
|
121
164
|
while (arg = argv.shift)
|
122
165
|
case arg
|
123
166
|
when '--'
|
124
|
-
arguments += argv
|
125
|
-
break
|
167
|
+
break arguments += argv
|
126
168
|
when /\A--([[[:alnum:]]-]+)\z/
|
127
169
|
handle_option(Regexp.last_match[1], argv)
|
128
170
|
when /\A-([[:alnum:]]+)\z/
|
@@ -134,10 +176,6 @@ module MiniCli
|
|
134
176
|
arguments
|
135
177
|
end
|
136
178
|
|
137
|
-
def error(msg)
|
138
|
-
@error[1, msg]
|
139
|
-
end
|
140
|
-
|
141
179
|
def process(arguments)
|
142
180
|
@args.each do |arg|
|
143
181
|
process_arg(arg, arguments.shift) unless arg.index('..')
|
@@ -148,33 +186,38 @@ module MiniCli
|
|
148
186
|
end
|
149
187
|
|
150
188
|
def process_arg(arg, value)
|
151
|
-
if arg
|
152
|
-
|
189
|
+
if arg[0] == '[' && arg[-1] == ']'
|
190
|
+
return unless value
|
191
|
+
arg = arg[1..-2]
|
153
192
|
else
|
154
|
-
|
193
|
+
error("parameter expected - #{arg}") unless value
|
155
194
|
end
|
195
|
+
@result[(arg[0] == '<' && arg[-1] == '>') ? arg[1..-2] : arg] = value
|
156
196
|
end
|
157
197
|
|
158
|
-
def handle_option(option, argv,
|
159
|
-
key = @options[option] || error("unknown option - #{option}")
|
160
|
-
@result[key] =
|
198
|
+
def handle_option(option, argv, pref = '-')
|
199
|
+
key = @options[option] || error("unknown option - #{pref}-#{option}")
|
200
|
+
return @result[key[1..-1]] = true if key[0] == '!'
|
161
201
|
@result[key] = value = argv.shift
|
162
|
-
return unless value.nil? || value
|
163
|
-
error("parameter
|
202
|
+
return unless value.nil? || value[0] == '-'
|
203
|
+
error("parameter <#{key}> expected - #{pref}-#{option}")
|
164
204
|
end
|
165
205
|
|
166
206
|
def parse_options(options, argv)
|
167
|
-
|
168
|
-
options.each_char { |opt| handle_option(opt, argv, test) }
|
207
|
+
options.each_char { |opt| handle_option(opt, argv, nil) }
|
169
208
|
end
|
170
209
|
|
171
210
|
def parse_help!
|
172
211
|
@options = {}
|
173
212
|
@helptext.each_line do |line|
|
174
213
|
case line
|
175
|
-
when
|
214
|
+
when /Options:$/
|
215
|
+
@show_options_text = false
|
216
|
+
when /-([[:alnum:]]), --([[[:alnum:]]-]+) ([[:upper:]]+)\s+\S+/,
|
217
|
+
/-([[:alnum:]]), --([[[:alnum:]]-]+) \<([[:lower:]]+)\>\s+\S+/
|
176
218
|
option_with_argument(Regexp.last_match)
|
177
|
-
when /--([[[:alnum:]]-]+) ([[:upper:]]+)\s+\S
|
219
|
+
when /--([[[:alnum:]]-]+) ([[:upper:]]+)\s+\S+/,
|
220
|
+
/--([[[:alnum:]]-]+) \<([[:lower:]]+)\>\s+\S+/
|
178
221
|
short_option_with_argument(Regexp.last_match)
|
179
222
|
when /-([[:alnum:]]), --([[[:alnum:]]-]+)\s+\S+/
|
180
223
|
option(Regexp.last_match)
|
@@ -182,6 +225,7 @@ module MiniCli
|
|
182
225
|
short_option(Regexp.last_match)
|
183
226
|
end
|
184
227
|
end
|
228
|
+
@show_options_text &= !@options.empty?
|
185
229
|
end
|
186
230
|
|
187
231
|
def option_with_argument(match)
|
@@ -193,11 +237,11 @@ module MiniCli
|
|
193
237
|
end
|
194
238
|
|
195
239
|
def option(match)
|
196
|
-
@options[match[1]] = @options[match[2]] = match[2]
|
240
|
+
@options[match[1]] = @options[match[2]] = "!#{match[2]}"
|
197
241
|
end
|
198
242
|
|
199
243
|
def short_option(match)
|
200
|
-
@options[match[1]] = match[1]
|
244
|
+
@options[match[1]] = "!#{match[1]}"
|
201
245
|
end
|
202
246
|
end
|
203
247
|
end
|
data/mini-cli.gemspec
CHANGED
@@ -2,30 +2,30 @@
|
|
2
2
|
|
3
3
|
require_relative './lib/mini-cli/version'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'mini-cli'
|
7
|
+
spec.version = MiniCli::VERSION
|
8
|
+
spec.required_ruby_version = '>= 2.5.0'
|
9
|
+
|
10
|
+
spec.summary = 'The lean CLI framework for Ruby'
|
11
|
+
spec.description = <<~DESC
|
10
12
|
This gem is a lean, easy to use CLI framework with a very small footprint.
|
11
13
|
It provides an easy to use argument parsing, help displaying and
|
12
14
|
minimalistic error handling.
|
13
15
|
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
16
|
|
21
|
-
|
17
|
+
spec.author = 'Mike Blumtritt'
|
18
|
+
spec.homepage = 'https://github.com/mblumtritt/mini-cli'
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/mblumtritt/mini-cli'
|
20
|
+
spec.metadata['bug_tracker_uri'] =
|
21
|
+
'https://github.com/mblumtritt/mini-cli/issues'
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'minitest'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
26
|
|
27
|
-
all_files =
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
all_files = Dir.chdir(__dir__) { `git ls-files -z`.split(0.chr) }
|
28
|
+
spec.test_files = all_files.grep(%r{^(spec|test)/})
|
29
|
+
spec.files = all_files - spec.test_files
|
30
|
+
spec.extra_rdoc_files = %w[README.md]
|
31
31
|
end
|
data/rakefile.rb
CHANGED
@@ -3,13 +3,11 @@
|
|
3
3
|
require 'rake/testtask'
|
4
4
|
require 'bundler/gem_tasks'
|
5
5
|
|
6
|
-
|
6
|
+
$stdout.sync = $stderr.sync = true
|
7
7
|
|
8
|
-
|
8
|
+
task(:default) { exec('rake --tasks') }
|
9
9
|
|
10
|
-
|
11
|
-
exec "#{$PROGRAM_NAME} --tasks"
|
12
|
-
end
|
10
|
+
CLOBBER << 'prj'
|
13
11
|
|
14
12
|
Rake::TestTask.new(:test) do |t|
|
15
13
|
t.ruby_opts = %w[-w]
|
data/samples/custom_args.rb
CHANGED
@@ -4,25 +4,34 @@ require_relative '../lib/mini-cli'
|
|
4
4
|
|
5
5
|
include MiniCli
|
6
6
|
|
7
|
-
help <<~HELP, %w[
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
help <<~HELP, %w[<target> [<source>]]
|
8
|
+
|
9
|
+
Demonstration of converting arguments to a custom argument class.
|
10
|
+
|
11
|
+
Options:
|
12
|
+
-n, --name <name> option requires <name> argument, has shortcut
|
13
|
+
--url <url> option requires <url> argument
|
14
|
+
-s, --switch option without any argument, has shortcut
|
15
|
+
--opt option without any argument
|
12
16
|
HELP
|
13
17
|
|
14
18
|
main { |cfg| cfg.each_pair { |key, value| puts("#{key}: #{value}") } }
|
15
19
|
|
16
20
|
parse_argv do |args|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
# args['FILES'] is an array containing all surplus arguments
|
22
|
+
Struct
|
23
|
+
.new(:target, :sources, :name, :url, :switch, :opt)
|
24
|
+
.new(
|
25
|
+
args['target'],
|
26
|
+
args['FILES'],
|
27
|
+
args['name'] || 'default_name',
|
28
|
+
args['url'] || 'www.url.test',
|
29
|
+
args.key?('switch'),
|
30
|
+
args.key?('opt')
|
31
|
+
)
|
32
|
+
.tap do |cfg|
|
33
|
+
source = args['source'] || ENV['SOURCE']
|
34
|
+
cfg.sources.unshift(source) if source
|
35
|
+
cfg.sources << 'STDIN' if cfg.sources.empty?
|
36
|
+
end
|
28
37
|
end
|
data/samples/demo.rb
CHANGED
@@ -4,18 +4,24 @@ require_relative '../lib/mini-cli'
|
|
4
4
|
|
5
5
|
include MiniCli
|
6
6
|
|
7
|
-
help <<~HELP, %w[
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
help <<~HELP, %w[<target> [<source>]]
|
8
|
+
|
9
|
+
Demonstration of general Mini-CLI behavior.
|
10
|
+
|
11
|
+
Options:
|
12
|
+
-n, --name <name> option requires <name> argument, has shortcut
|
13
|
+
--url <url> option requires <url> argument
|
14
|
+
-s, --switch option without any argument, has shortcut
|
15
|
+
--opt option without any argument
|
16
|
+
|
17
|
+
Try to call this <*name*> command with various options and arguments.
|
12
18
|
HELP
|
13
19
|
|
14
20
|
main do |args|
|
15
|
-
puts("
|
16
|
-
puts("
|
17
|
-
puts("
|
18
|
-
puts("
|
21
|
+
puts("target: #{args['target']}")
|
22
|
+
puts("source: #{args['source']}") if args.key?('source')
|
23
|
+
puts("name: #{args['name']}") if args.key?('name')
|
24
|
+
puts("url: #{args['url']}") if args.key?('url')
|
19
25
|
puts("FILES: #{args['FILES']}") unless args['FILES'].empty?
|
20
26
|
puts('--switch was given') if args.key?('switch')
|
21
27
|
puts('--opt was given') if args.key?('opt')
|
data/test/apps/noop.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# demonstrates the call sequence
|
3
|
+
|
4
|
+
require_relative '../../lib/mini-cli'
|
5
|
+
include(MiniCli)
|
6
|
+
|
7
|
+
help <<~HELP
|
8
|
+
-x, --exit early exit
|
9
|
+
-e, --error exit with error
|
10
|
+
HELP
|
11
|
+
|
12
|
+
main do |*args|
|
13
|
+
puts('main' + args.inspect)
|
14
|
+
exit if args.first['exit']
|
15
|
+
error(42, '!error!') if args.first['error']
|
16
|
+
end
|
17
|
+
|
18
|
+
before { |*args| puts('before_1' + args.inspect) }
|
19
|
+
after { |*args| puts('after_1' + args.inspect) }
|
20
|
+
before { |*args| puts('before_2' + args.inspect) }
|
21
|
+
after { |*args| puts('after_2' + args.inspect) }
|
22
|
+
|
23
|
+
parse_argv do |*args|
|
24
|
+
puts('parse_argv' + args.inspect)
|
25
|
+
args.first
|
26
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'shellwords'
|
5
|
+
require_relative '../helper'
|
6
|
+
|
7
|
+
class ExecTest < Minitest::Test
|
8
|
+
def test_noop
|
9
|
+
assert_empty(assert_no_err('noop.rb'))
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_noop_help
|
13
|
+
assert_equal("Usage: noop\n", assert_no_err('noop.rb', '--help'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_sequence
|
17
|
+
expected = [
|
18
|
+
'before_1[]',
|
19
|
+
'before_2[]',
|
20
|
+
"parse_argv[{\"FILES\"=>[]}]",
|
21
|
+
"main[{\"FILES\"=>[]}]",
|
22
|
+
'after_2[]',
|
23
|
+
'after_1[]'
|
24
|
+
]
|
25
|
+
assert_equal(expected, assert_no_err('sequence.rb').split("\n"))
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_sequence_help
|
29
|
+
expected = [
|
30
|
+
'Usage: sequence [<options>]',
|
31
|
+
'',
|
32
|
+
'Options:',
|
33
|
+
'-x, --exit early exit',
|
34
|
+
'-e, --error exit with error'
|
35
|
+
]
|
36
|
+
assert_equal(expected, assert_no_err('sequence.rb', '--help').split("\n"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_sequence_early_exit
|
40
|
+
expected = [
|
41
|
+
'before_1[]',
|
42
|
+
'before_2[]',
|
43
|
+
"parse_argv[{\"exit\"=>true, \"FILES\"=>[]}]",
|
44
|
+
"main[{\"exit\"=>true, \"FILES\"=>[]}]",
|
45
|
+
'after_2[]',
|
46
|
+
'after_1[]'
|
47
|
+
]
|
48
|
+
assert_equal(expected, assert_no_err('sequence.rb', '-x').split("\n"))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_sequence_error
|
52
|
+
expected = [
|
53
|
+
'before_1[]',
|
54
|
+
'before_2[]',
|
55
|
+
"parse_argv[{\"error\"=>true, \"FILES\"=>[]}]",
|
56
|
+
"main[{\"error\"=>true, \"FILES\"=>[]}]",
|
57
|
+
'after_2[]',
|
58
|
+
'after_1[]'
|
59
|
+
]
|
60
|
+
std, err, status = invoke('sequence.rb', '-e')
|
61
|
+
assert_same(42, status.exitstatus)
|
62
|
+
assert_equal("sequence: !error!\n", err)
|
63
|
+
assert_equal(expected, std.split("\n"))
|
64
|
+
end
|
65
|
+
|
66
|
+
def assert_no_err(...)
|
67
|
+
std, err = assert_success(...)
|
68
|
+
assert_empty(err)
|
69
|
+
std
|
70
|
+
end
|
71
|
+
|
72
|
+
def assert_success(...)
|
73
|
+
std, err, status = invoke(...)
|
74
|
+
assert(status.success?)
|
75
|
+
return std, err
|
76
|
+
end
|
77
|
+
|
78
|
+
def invoke(name, *args)
|
79
|
+
Open3.capture3(
|
80
|
+
Shellwords.join(
|
81
|
+
[
|
82
|
+
RbConfig.ruby,
|
83
|
+
'--disable',
|
84
|
+
'gems',
|
85
|
+
'--disable',
|
86
|
+
'did_you_mean',
|
87
|
+
'--disable',
|
88
|
+
'rubyopt',
|
89
|
+
File.expand_path("../apps/#{name}", __dir__)
|
90
|
+
] + args
|
91
|
+
)
|
92
|
+
)
|
93
|
+
end
|
94
|
+
end
|
data/test/mini-cli/main_test.rb
CHANGED
@@ -13,12 +13,17 @@ class MainTest < Test
|
|
13
13
|
subject = Class.new { include MiniCli }.new
|
14
14
|
|
15
15
|
expected_methods = %i[
|
16
|
+
after
|
17
|
+
before
|
16
18
|
error
|
19
|
+
error_code
|
17
20
|
help
|
18
21
|
main
|
19
22
|
name
|
20
23
|
parse_argv
|
21
24
|
run
|
25
|
+
run_ruby
|
26
|
+
run_script
|
22
27
|
show_errors=
|
23
28
|
show_errors?
|
24
29
|
show_help
|
@@ -176,4 +181,13 @@ class MainTest < Test
|
|
176
181
|
result = subject.parse_argv(as_argv('-nup name port in out opt file'))
|
177
182
|
assert_equal(expected, result)
|
178
183
|
end
|
184
|
+
|
185
|
+
def test_run
|
186
|
+
call_sequence = []
|
187
|
+
subject.main { call_sequence << :main }
|
188
|
+
subject.before { call_sequence << :start_1 }
|
189
|
+
subject.after { call_sequence << :end_1 }
|
190
|
+
subject.before { call_sequence << :start_2 }
|
191
|
+
subject.after { call_sequence << :end_2 }
|
192
|
+
end
|
179
193
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../helper'
|
4
|
+
|
5
|
+
class RubyRunTest < Test
|
6
|
+
def test_simple
|
7
|
+
result = subject.run_script('puts("Hello World")')
|
8
|
+
assert_equal("Hello World\n", result)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_error
|
12
|
+
result = subject.run_script('UNDEFINED')
|
13
|
+
assert_match(/NameError/, result)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_chdir
|
17
|
+
home = Dir.home
|
18
|
+
refute(home == Dir.pwd)
|
19
|
+
result = subject.run_script('print Dir.pwd', chdir: home)
|
20
|
+
assert_equal(home, result)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_status
|
24
|
+
status, result = subject.run_script('print :Ok', status: true)
|
25
|
+
assert_instance_of(Process::Status, status)
|
26
|
+
assert(status.success?)
|
27
|
+
assert_equal('Ok', result)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_status_error
|
31
|
+
status, result = subject.run_script('print :Err;exit 42', status: true)
|
32
|
+
assert_instance_of(Process::Status, status)
|
33
|
+
refute(status.success?)
|
34
|
+
assert_same(42, status.exitstatus)
|
35
|
+
assert_equal('Err', result)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_stream
|
39
|
+
stream = StringIO.new('puts "Hello World"')
|
40
|
+
result = subject.run_script(stream)
|
41
|
+
assert_equal("Hello World\n", result)
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,8 +74,12 @@ files:
|
|
74
74
|
- samples/custom_args.rb
|
75
75
|
- samples/demo.rb
|
76
76
|
- samples/simple.rb
|
77
|
+
- test/apps/noop.rb
|
78
|
+
- test/apps/sequence.rb
|
77
79
|
- test/helper.rb
|
80
|
+
- test/mini-cli/exec_test.rb
|
78
81
|
- test/mini-cli/main_test.rb
|
82
|
+
- test/mini-cli/ruby_run_test.rb
|
79
83
|
- test/mini-cli/run_test.rb
|
80
84
|
homepage: https://github.com/mblumtritt/mini-cli
|
81
85
|
licenses: []
|
@@ -97,11 +101,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
101
|
- !ruby/object:Gem::Version
|
98
102
|
version: '0'
|
99
103
|
requirements: []
|
100
|
-
rubygems_version: 3.
|
104
|
+
rubygems_version: 3.2.28
|
101
105
|
signing_key:
|
102
106
|
specification_version: 4
|
103
107
|
summary: The lean CLI framework for Ruby
|
104
108
|
test_files:
|
109
|
+
- test/apps/noop.rb
|
110
|
+
- test/apps/sequence.rb
|
105
111
|
- test/helper.rb
|
112
|
+
- test/mini-cli/exec_test.rb
|
106
113
|
- test/mini-cli/main_test.rb
|
114
|
+
- test/mini-cli/ruby_run_test.rb
|
107
115
|
- test/mini-cli/run_test.rb
|